svn commit: r304727 - in head/sys/powerpc: booke include
Justin Hibbits
jhibbits at FreeBSD.org
Wed Aug 24 03:51:42 UTC 2016
Author: jhibbits
Date: Wed Aug 24 03:51:40 2016
New Revision: 304727
URL: https://svnweb.freebsd.org/changeset/base/304727
Log:
Fix system hang when large FDT is in use
Summary:
Kernel maps only one page of FDT. When FDT is more than one page in size, data
TLB miss occurs on memmove() when FDT is moved to kernel storage
(sys/powerpc/booke/booke_machdep.c, booke_init())
This introduces a pmap_early_io_unmap() to complement pmap_early_io_map(), which
can be used for any early I/O mapping, but currently is only used when mapping
the fdt.
Submitted by: Ivan Krivonos <int0dster_gmail.com>
Differential Revision: https://reviews.freebsd.org/D7605
Modified:
head/sys/powerpc/booke/booke_machdep.c
head/sys/powerpc/booke/pmap.c
head/sys/powerpc/include/pmap.h
Modified: head/sys/powerpc/booke/booke_machdep.c
==============================================================================
--- head/sys/powerpc/booke/booke_machdep.c Wed Aug 24 03:44:20 2016 (r304726)
+++ head/sys/powerpc/booke/booke_machdep.c Wed Aug 24 03:51:40 2016 (r304727)
@@ -249,6 +249,7 @@ static int
booke_check_for_fdt(uint32_t arg1, vm_offset_t *dtbp)
{
void *ptr;
+ int fdt_size;
if (arg1 % 8 != 0)
return (-1);
@@ -257,6 +258,19 @@ booke_check_for_fdt(uint32_t arg1, vm_of
if (fdt_check_header(ptr) != 0)
return (-1);
+ /*
+ * Read FDT total size from the header of FDT.
+ * This for sure hits within first page which is
+ * already mapped.
+ */
+ fdt_size = fdt_totalsize((void *)ptr);
+
+ /*
+ * Ok, arg1 points to FDT, so we need to map it in.
+ * First, unmap this page and then map FDT again with full size
+ */
+ pmap_early_io_unmap((vm_offset_t)ptr, PAGE_SIZE);
+ ptr = (void *)pmap_early_io_map(arg1, fdt_size);
*dtbp = (vm_offset_t)ptr;
return (0);
Modified: head/sys/powerpc/booke/pmap.c
==============================================================================
--- head/sys/powerpc/booke/pmap.c Wed Aug 24 03:44:20 2016 (r304726)
+++ head/sys/powerpc/booke/pmap.c Wed Aug 24 03:51:40 2016 (r304727)
@@ -3419,6 +3419,29 @@ tlb1_init()
set_mas4_defaults();
}
+void
+pmap_early_io_unmap(vm_offset_t va, vm_size_t size)
+{
+ int i;
+ tlb_entry_t e;
+
+ for (i = 0; i < TLB1_ENTRIES && size > 0; i ++) {
+ tlb1_read_entry(&e, i);
+ if (!(e.mas1 & MAS1_VALID))
+ continue;
+ /*
+ * FIXME: this code does not work if VA region
+ * spans multiple TLB entries. This does not cause
+ * problems right now but shall be fixed in the future
+ */
+ if (va >= e.virt && (va + size) <= (e.virt + e.size)) {
+ size -= e.size;
+ e.mas1 &= ~MAS1_VALID;
+ tlb1_write_entry(&e, i);
+ }
+ }
+}
+
vm_offset_t
pmap_early_io_map(vm_paddr_t pa, vm_size_t size)
{
Modified: head/sys/powerpc/include/pmap.h
==============================================================================
--- head/sys/powerpc/include/pmap.h Wed Aug 24 03:44:20 2016 (r304726)
+++ head/sys/powerpc/include/pmap.h Wed Aug 24 03:51:40 2016 (r304727)
@@ -260,6 +260,7 @@ extern vm_offset_t msgbuf_phys;
extern int pmap_bootstrapped;
vm_offset_t pmap_early_io_map(vm_paddr_t pa, vm_size_t size);
+void pmap_early_io_unmap(vm_offset_t va, vm_size_t size);
#endif
More information about the svn-src-head
mailing list