Date: Wed, 24 Aug 2016 03:51:40 +0000 (UTC) From: Justin Hibbits <jhibbits@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r304727 - in head/sys/powerpc: booke include Message-ID: <201608240351.u7O3peXQ019475@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201608240351.u7O3peXQ019475>