Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 3 Oct 2010 19:03:56 -0500
From:      Alan Cox <alan.l.cox@gmail.com>
To:        Svatopluk Kraus <onwahe@gmail.com>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: page table fault, which should map kernel virtual address space
Message-ID:  <AANLkTinx28JG_43_P_xSa6PE1dUD9MTcs3icU%2BfgsQ-4@mail.gmail.com>
In-Reply-To: <AANLkTim_i2KFjrGpeuRndu2LXLpugJ%2By5RVDpJjN=5mj@mail.gmail.com>
References:  <29760054.post@talk.nabble.com> <AANLkTin6fPhb4R1T=99S1AT-sPk3He2akWf2taKUa2ry@mail.gmail.com> <AANLkTim_i2KFjrGpeuRndu2LXLpugJ%2By5RVDpJjN=5mj@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, Sep 30, 2010 at 6:28 AM, Svatopluk Kraus <onwahe@gmail.com> wrote:

> On Tue, Sep 21, 2010 at 7:38 PM, Alan Cox <alan.l.cox@gmail.com> wrote:
> > On Mon, Sep 20, 2010 at 9:32 AM, Svatopluk Kraus <onwahe@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.
>

I have a patch that implements one possible fix for this problem.  I'll
probably commit that patch in the next day or two.

Regards,
Alan



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?AANLkTinx28JG_43_P_xSa6PE1dUD9MTcs3icU%2BfgsQ-4>