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()) { \