Subject: pmap interface deficiency?
To: None <tech-kern@NetBSD.ORG>
From: Charles Hannum <Charles-Hannum@deshaw.com>
List: tech-kern
Date: 01/07/1996 22:06:41
On looking at the problem reported in PR 1834, mlock() panicking on
the i386 port, I've discovered an interesting deficiency in the pmap
interface.  It goes something like this:

On the i386 port, the kernel and user process share the same address
space.  Because of this, it's useful to minimize the amount of space
that the kernel uses.  At the same time, in order to speed up
copyout*() on the i386, it's useful to have the page table represented
by one contiguous chunk of 4MB.  These are competing goals; if you
created a 4MB page table for every process in the same map, you'd
significantly reduce the amount of space available to user processes.

The way Jolitz dealt with this is to map the page table at a fixed
location within itself.  Because each pmap only contains one page
table, only 4MB (actually 8MB, because there's a second mapping) of
virtual space is ever taken up by page tables.

So far, everything is fine, and it's a fairly simple and clean
solution.  Now I get a fault, and try to map a page in.  The page
table page for that user page doesn't happen to have anything in it
yet, so it hasn't yet been allocated.

At this point, Jolitz's code does a special hack in the trap handler
to check for a missing page table, and does a separate vm_fault() for
it beforehand.

Again, so far, everything is fine.  Now someone calls mlock(), or
anything else that causes a page to be mapped into a 4MB region where
there was none, without invoking the trap handler.

Now I'm moderately screwed.  At this point, the hp300 (et al) pmap
modules do a call to pmap_enter_ptpage() to create a new page table
page, which in turn does a vm_fault().  In order to do this, however,
it must know which VM map to allocate the page from.  The pmap
interface doesn't provide this information.

Most ports deal with this by simply allocating one map which holds all
of the page tables.  As noted above, however, this solution doesn't
easily work on the i386; at least without eating a large chunk of the
user address space.

Any ideas on how to fix this?