> Date: Thu, 17 Dec 2020 19:25:44 -0300
> From: Martin Pieuchot <m...@openbsd.org>
> 
> On 17/12/20(Thu) 23:16, Mark Kettenis wrote:
> > > Date: Thu, 17 Dec 2020 18:56:52 -0300
> > > From: Martin Pieuchot <m...@openbsd.org>
> > > 
> > > On 16/12/20(Wed) 22:49, Greg Steuck wrote:
> > > > I just hit this while booting an i386-current in vmd. The source tree is
> > > > synced to "Remove the assertion in uvm_km_pgremove()."
> > > > 
> > > > I enabled WITNESS on top of GENERIC. Naturally, GENERIC-Dec15 snap 
> > > > works.
> > > > 
> > > > Anybody else see this so I know it's worth a bisect?
> > > > [...]
> > > 
> > > I can reproduce it.  Diff below fixes it.  This is the beginning of a
> > > rabbit hole... thanks!
> > > 
> > > > witness: lock_object uninitialized: 0xd0f3c828
> > > > Starting stack trace...
> > > > witness_checkorder(0,d6bb011c,d1155e6c,d02e10e4,90) at 
> > > > witness_checkorder+0x8a
> > > > witness_checkorder(d0f3c828,9,0) at witness_checkorder+0x8a
> > > > mtx_enter(d0f3c81c) at mtx_enter+0x27
> > > > pmap_extract_pae(d8bb0d80,f5605000,d8bb0da0) at pmap_extract_pae+0x53
> > > > pmap_pinit_pd_pae(d8bb0d80) at pmap_pinit_pd_pae+0x268
> > > > pmap_create(1,1000,f6fe5e86,d8bbfd54,d0f5ba18) at pmap_create+0xa8
> > > > uvmspace_fork(d0f5b5fc,d8bb3e34,d0f5b5fc,1,d1155f70) at 
> > > > uvmspace_fork+0x56
> > > > process_new(d8bb3e34,d0f5b5fc,1) at process_new+0xeb
> > > > fork1(d0eb7b14,1,d04eb560,0,0,d1155f90) at fork1+0x1ba
> > > > panic: acquiring blockable sleep lock with spinlock or critical section 
> > > > held (rwlock) kmmaplk
> > > 
> > > pmap_kernel()'s mutexes aren't initialized.  Diff below does that.
> > 
> > Well, that is somewhat intentional.  Those mutexes should never be
> > used for the kernel pmap.  The kernel pmap is always there and is
> > updated atomically.
> > 
> > So how did we end up trying to grab one of these mutexs?
> 
> pmap_map_ptes() (both version of them) grab the current's pmap
> `pm_apte_mtx' which ends up being the kernel one in this case.

Actually I think only pmap_pinit_pd_pae() runs into this problem,
because it does this:

            if (!pmap_extract(pmap, va + i * NBPG,
                (paddr_t *)&pmap->pm_pdidx_intel[i]))
                    panic("%s: can't locate PD page\n", __func__);

I'm womewhat surprized by this.  Why are we extracting addresses out
of the freshly created pmap?

Anyway, your analysis is right.  When a kernel thread wants to use
pmap_extract(9) on a userland pmap, it needs to lock pm_apte_mtx to
prevent another thread from simultaniously activating a userland pmap
too.  So indeed, pm_apte_mtx needs to be properly initialized for the
kernel pmap.

However, pm_mtx should never be used for the kernel pmap.  If we don't
initialize the lock, witness will help us catching this condition, so
maybe we shouldn't...

> > > Index: arch/i386/i386/pmap.c
> > > ===================================================================
> > > RCS file: /cvs/src/sys/arch/i386/i386/pmap.c,v
> > > retrieving revision 1.209
> > > diff -u -p -r1.209 pmap.c
> > > --- arch/i386/i386/pmap.c 24 Sep 2020 11:36:50 -0000      1.209
> > > +++ arch/i386/i386/pmap.c 17 Dec 2020 21:47:11 -0000
> > > @@ -961,6 +961,8 @@ pmap_bootstrap(vaddr_t kva_start)
> > >    */
> > >  
> > >   kpm = pmap_kernel();
> > > + mtx_init(&kpm->pm_mtx, IPL_VM);
> > > + mtx_init(&kpm->pm_apte_mtx, IPL_VM);
> > >   uvm_objinit(&kpm->pm_obj, NULL, 1);
> > >   bzero(&kpm->pm_list, sizeof(kpm->pm_list));  /* pm_list not used */
> > >   kpm->pm_pdir = (vaddr_t)(proc0.p_addr->u_pcb.pcb_cr3 + KERNBASE);
> > > 
> > > 
> 

Reply via email to