tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: UVM patch for PR port-xen/45975
On Fri, Feb 17, 2012 at 04:42:04PM +0100, Manuel Bouyer wrote:
> Hello,
> there is an issue with SMP Xen guests (see port-xen/45975), where uvm
> can put a page back to free list before clearing its mappings.
> This happens when uvm_km_pgremove_intrsafe() is used: is has to be called
> before pmap_kremove() because it uses pmap_extract(), and (I guess for
> efficiency), all pages are freed before calling pmap_kremove() for the
> whole range.
> This is a problem for Xen, because one of these pages can be grabbed by
> another CPU for a PDP, and Xen won't allow to pin a page as PDP if it
> still has R/W mappings. As a CPU can be preempted by the hypervisor,
> there is potentially plenty of time for another CPU to grab the
> page, initialize it and try to use it as PDP between
> uvm_km_pgremove_intrsafe()
> and pmap_kremove().
>
> To fix this I propose the attached patch:
> - change uvm_km_pgremove_intrsafe()'s semantic to also unmap the page
> (all uvm_km_pgremove_intrsafe() use are followed by a pmap_kremove(),
> just move the call in uvm_km_pgremove_intrsafe()).
> - If __PMAP_NEEDS_UNMAP_BEFORE_FREE is defined, uvm_km_pgremove_intrsafe()
> does a pmap_kremove() for each page, after pmap_extract() but before
> uvm_pagefree(). If not defined, uvm_km_pgremove_intrsafe() does
> a tail pmap_kremove() call at the end
> - __PMAP_NEEDS_UNMAP_BEFORE_FREE is defined for XEN in x86/include/pmap.h
>
> Does anyone see a problem with this ?
hi manuel,
this is fine in general, but there are a few details:
- it would be better to remove the mappings before freeing the page
on all platforms, not just xen. that's just a good practice.
if you're concerned about a potential performance impact,
you could process the pages in batches of 16 or so using a little
array on the stack, which should handle most operations in one batch.
I did a quick experiment just now and found that most calls
to uvm_km_pgremove_intrsafe() are for 4 pages or less.
(I wonder why those aren't using some higher-level cache?)
about 10% of the calls were for 16 pages, and none were larger.
- the calls to pmap_update() should be moved along with the calls to
pmap_kremove().
- a non-xen kernel with the patch dies during boot with:
panic: kernel diagnostic assertion "!pmap_extract(pmap_kernel(), loopva, NULL)"
failed: file "/home/chs/netbsd/src/sys/uvm/uvm_km.c", line 749
loopva=0xffff80001d1df000 loopsize=0x3000 vmem=0xffffffff80f01ae8
fatal breakpoint trap in supervisor mode
trap type 1 code 0 rip ffffffff802599e5 cs 8 rflags 246 cr2 0 cpl 8 rsp
ffffffff810c1af0
Stopped in pid 0.1 (system) at netbsd:breakpoint+0x5: leave
db{0}> t
breakpoint() at netbsd:breakpoint+0x5
vpanic() at netbsd:vpanic+0x1f2
kern_assert() at netbsd:kern_assert+0x48
uvm_km_kmem_alloc() at netbsd:uvm_km_kmem_alloc+0x19f
kmem_intr_alloc() at netbsd:kmem_intr_alloc+0x5b
kmem_intr_zalloc() at netbsd:kmem_intr_zalloc+0xf
mpacpi_find_interrupts() at netbsd:mpacpi_find_interrupts+0x102
acpi_md_callback() at netbsd:acpi_md_callback+0x1a
acpi_attach() at netbsd:acpi_attach+0x163
config_attach_loc() at netbsd:config_attach_loc+0x182
mainbus_attach() at netbsd:mainbus_attach+0x200
config_attach_loc() at netbsd:config_attach_loc+0x182
cpu_configure() at netbsd:cpu_configure+0x26
main() at netbsd:main+0x2b0
-Chuck
Home |
Main Index |
Thread Index |
Old Index