page table fault, which should map kernel virtual address space

Svatopluk Kraus onwahe at gmail.com
Thu Sep 30 11:55:31 UTC 2010


On Tue, Sep 21, 2010 at 7:38 PM, Alan Cox <alan.l.cox at gmail.com> wrote:
> On Mon, Sep 20, 2010 at 9:32 AM, Svatopluk Kraus <onwahe at gmail.com> wrote:
>> Beyond 'kernel_map', some submaps of 'kernel_map' (buffer_map,
>> pager_map,...) exist as result of 'kmem_suballoc' function call.
>> When this submaps are used (for example 'kmem_alloc_nofault'
>> function) and its virtual address subspace is at the end of
>> used kernel virtual address space at the moment (and above 'NKPT'
>> preallocation), then missing page tables are not allocated
>> and double fault can happen.
>>
>
> No, the page tables are allocated.  If you create a submap X of the kernel
> map using kmem_suballoc(), then a vm_map_findspace() is performed by
> vm_map_find() on the kernel map to find space for the submap X.  As you note
> above, the call to vm_map_findspace() on the kernel map will call
> pmap_growkernel() if needed to extend the kernel page table.
>
> If you create another submap X' of X, then that submap X' can only map
> addresses that fall within the range for X.  So, any necessary page table
> pages were allocated when X was created.

You are right. Mea culpa. I was focused on a solution and made
too quick conclusion. The page table fault hitted in 'pager_map',
which is submap of 'clean_map' and when I debugged the problem
I didn't see a submap stuff as a whole.

> That said, there may actually be a problem with the implementation of the
> superpage_align parameter to kmem_suballoc().  If a submap is created with
> superpage_align equal to TRUE, but the submap's size is not a multiple of
> the superpage size, then vm_map_find() may not allocate a page table page
> for the last megabyte or so of the submap.
>
> There are only a few places where kmem_suballoc() is called with
> superpage_align set to TRUE.  If you changed them to FALSE, that is an easy
> way to test this hypothesis.

Yes, it helps.

My story is that the problem started up when I updated a project
('coldfire' port)
based on FreeBSD 8.0. to FreeBSD current version. In the current version
the 'clean_map' submap is created with superpage_align set to TRUE.

I have looked at vm_map_find() and debugged the page table fault once again.
IMO, it looks that a do-while loop does not work in the function as intended.
A vm_map_findspace() finds a space and calls pmap_growkernel() if needed.
A pmap_align_superpage() arrange the space but never call pmap_growkernel().
A vm_map_insert() inserts the aligned space into a map without error
and never call pmap_growkernel() and does not invoke loop iteration.

I don't know too much about an idea how a virtual memory model is implemented
and used in other modules. But it seems that it could be more reasonable to
align address space in vm_map_findspace() internally and not to loop externally.

I have tried to add a check in vm_map_insert() that checks the 'end' parameter
against 'kernel_vm_end' variable and returns KERN_NO_SPACE error if needed.
In this case the loop in vm_map_find() works and I have no problem with
the page table fault. But 'kernel_vm_end' variable must be initializated
properly before first use of vm_map_insert(). The 'kernel_vm_end' variable
can be self-initializated in pmap_growkernel() in FreeBSD 8.0 (it is too late),
but it was changed in current version ('i386' port).

Thanks for your answer, but I'm still looking for permanent
and approved solution.

 Regards, Svata


More information about the freebsd-hackers mailing list