On Thu, October 16, 2014 11:40 pm, Patrick Wildt wrote: > I do believe that this is a pmap issue. > > I just got hands on an Allwinner A20 and suffered the same issues: > pool_setlowat crashing randomly, same for ahci and so on. > > I believe we are not syncing the PTEs correctly. > > Here?s the snippet from PTE_SYNC(), but PTE_SYNC_RANGE() has > the same issue: > > #define PTE_SYNC(pte) > \ > do { \ > if (PMAP_NEEDS_PTE_SYNC) { \ > paddr_t pa; \ > cpu_drain_writebuf(); \ > cpu_dcache_wb_range((vaddr_t)(pte), sizeof(pt_entry_t));\ > if (cpu_sdcache_enabled()) { \ > (void)pmap_extract(pmap_kernel(), (vaddr_t)(pte), &pa); \ > cpu_sdcache_wb_range((vaddr_t)(pte), (paddr_t)(pa), \ > sizeof(pt_entry_t)); \ > }; \ > cpu_drain_writebuf(); \ > } \ > } while (/*CONSTCOND*/0) > > I believe that when we change things in the pagetables, we need to make > sure the tables are synced before we?re going to use them. In our case > we believe that we are using uncached pagetables, which means that > every write will directly hit the tables. > > But that does not have an affect on the write buffer. The write buffer is > still > there and has to be cleared manually. If it isn?t, and something accesses > an area which was just mapped, then we?re fucked. > > Therefore I firmly believe that the cpu_drain_writebuf() call has to be made > regardless of PMAP_NEEDS_PTE_SYNC and that it has to be called before > that if-clause. > > Doing that fixes my issues. > > \Patrick >
I think this is correct. With the diff below, my A20 board doesn't panic anymore. I still get a lot of messages like the following though: pmap_fault_fixup: va 00008000 ftype 1 u pte 7f24f02e Index: sys/arch/arm/include/pmap.h =================================================================== RCS file: /cvs/src/sys/arch/arm/include/pmap.h,v retrieving revision 1.27 diff -u -p -u -p -r1.27 pmap.h --- sys/arch/arm/include/pmap.h 7 Oct 2014 10:10:58 -0000 1.27 +++ sys/arch/arm/include/pmap.h 20 Oct 2014 09:33:14 -0000 @@ -328,9 +328,9 @@ extern int pmap_needs_pte_sync; #define PTE_SYNC(pte) \ do { \ + cpu_drain_writebuf(); \ if (PMAP_NEEDS_PTE_SYNC) { \ paddr_t pa; \ - cpu_drain_writebuf(); \ cpu_dcache_wb_range((vaddr_t)(pte), sizeof(pt_entry_t));\ if (cpu_sdcache_enabled()) { \ (void)pmap_extract(pmap_kernel(), (vaddr_t)(pte), &pa); \ @@ -343,9 +343,9 @@ do { \ #define PTE_SYNC_RANGE(pte, cnt) \ do { \ + cpu_drain_writebuf(); \ if (PMAP_NEEDS_PTE_SYNC) { \ paddr_t pa; \ - cpu_drain_writebuf(); \ cpu_dcache_wb_range((vaddr_t)(pte), \ (cnt) << 2); /* * sizeof(pt_entry_t) */ \ if (cpu_sdcache_enabled()) { \