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>