Date: Fri, 08 Oct 2010 12:39:52 -0500 From: Alan Cox <alc@rice.edu> To: Kurt Alstrup <kalstrup@frontier.com> Cc: freebsd-stable@freebsd.org Subject: Re: Panic: attempted pmap_enter on 2MB page Message-ID: <4CAF5768.4020605@rice.edu> In-Reply-To: <4CAF4D64.4050105@frontier.com> References: <4CAC14DA.7050409@verizon.net> <4CADFD60.9040005@rice.edu> <4CAF4D64.4050105@frontier.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Kurt Alstrup wrote:
> Apologies for late response, wanted to check the code again.
>
>
> On 10/07/2010 10:03 AM, Alan Cox wrote:
>
>> Alan Cox wrote:
>> At a high-level, I agree with much of what you say. In particular, if
>> pmap_enter() is applied to a virtual address that is already mapped by a large
>> page, the reported panic could result. However, barring bugs, for example, in
>> memory allocation by the upper levels of the kernel, the panic inducing
>> situation shouldn't occur.
>>
> Calls to malloc() of items larger than a page takes a turn through UMA and
> eventually ends up in kmem_malloc() via its page_alloc() routine.
> Kmem_malloc() in turn gets the pages from vm_page_alloc(), parks them in
> the kmem_object and maps them into the kernel_pmap in a loop callings
> pmap_enter() for each page. The assigned VA's are pulled from kmem_map.
> Pages acquired through vm_page_alloc() may be backed by a super page
> reservation and thus are eligible for auto-promotion.
>
> Calls to free() initially take a similar route, ending up on kmem_free()
> via UMAs page_free() routine. From there the call path is vm_map_remove(),
> vm_map_remove(), vm_map_delete() to pmap_remove().
>
> This logic indicate, that from the kernel/vm perspective the malloc/free()
> pair will map/unmap pages as needed. However, the pmapper never unmaps
> these pages as far as I can tell. The call path is pmap_remove(),
> pmap_remove_pte() to pmap_unuse_pt() who ignores the removal because the
> VA >= VM_MAXUSER_ADDRESS.
>
>
No, consider:
static int
pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t va,
pd_entry_t ptepde, vm_page_t *free)
{
pt_entry_t oldpte;
vm_page_t m;
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
oldpte = pte_load_clear(ptq);
pte_load_clear() zeroes the PTE, regardless of whether it is a kernel or
user PTE.
I'm afraid that I need to catch an airplane. I'll follow up to the rest
of your message later.
Regards,
Alan
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4CAF5768.4020605>
