On Thu, Dec 09, 2010 at 10:32:57PM +0100, Wouter Coene wrote: > On 9 dec 2010, at 08:32, Ariane van der Steldt wrote: > > I'm not yet convinced. What are you trying to do? > > Pretty much as I described: I allocate kernel memory through > uvm_km_kmemalloc() from kernel_map, and then free it through uvm_km_free(), > returning it to the kernel_map. > > The code I'm working on is a bit large as a test-case, but I've abused > diskmap(4) to reproduce the panic: > > Index: diskmap.c > =================================================================== > RCS file: /cvs/openbsd/src/sys/dev/diskmap.c,v > retrieving revision 1.2 > diff -u -a -r1.2 diskmap.c > --- diskmap.c 14 Jun 2010 16:51:55 -0000 1.2 > +++ diskmap.c 9 Dec 2010 09:04:56 -0000 > @@ -37,6 +37,9 @@ > #include <sys/proc.h> > #include <sys/vnode.h> > > +#include <uvm/uvm_extern.h> > +#define DIOCBOOM _IO('d', 42) > + > int > diskmapopen(dev_t dev, int flag, int fmt, struct proc *p) > { > @@ -59,6 +62,18 @@ > struct vnode *vp = NULL, *ovp; > char *devname; > int fd, error = EINVAL; > + > + if (cmd == DIOCBOOM) { > + vaddr_t addr; > + > + addr = uvm_km_kmemalloc(kernel_map, NULL, PAGE_SIZE, > + UVM_KMF_CANFAIL | UVM_KMF_ZERO);
If you specify NULL as your object, you'll be given intr-safe memory. You want to use kernel object instead: addr = uvm_km_kmemalloc(kernel_map, uvm.kernel_object, PAGE_SIZE, UVM_KMF_CANFAIL | UVM_KMF_ZERO); > + if (addr == NULL) > + return (ENOMEM); > + uvm_km_free(kernel_map, addr, PAGE_SIZE); > + > + return (0); > + } > > if (cmd != DIOCMAP) > return EINVAL; > > This triggers the panic with the following test program: > > #include <err.h> > #include <sys/fcntl.h> > #include <sys/dkio.h> > #define DIOCBOOM _IO('d', 42) > > int > main() > { > int fd; > > fd = open("/dev/diskmap", O_RDWR, 0); > if (fd < 0) > err(1, "open(/dev/diskmap)"); > if (ioctl(fd, DIOCBOOM, 0) < 0) > err(1, "DIOCBOOM"); > close(fd); > > return (0); > } > > This is in -current from a few days ago, basically in GENERIC on amd64 but > with an ISA ne2k driver added (as bochs' PCI ne2k and OpenBSD don't agree > much). > > DDB output: > > panic: pmap_remove_pte: managed page without PG_PVLIST for 0xffff80000607b000 Exception is expected: page is entered by pmap_kenter_pa, but removed by pmap_remove. > > Coming back to your error: > >> ("pmap_remove_pte: managed page without PG_PVLIST for <address>" on > amd64), > > That's actually an error from the pmap layer. While uvm controls a lot > > of the pmap layer, many parts of the kernel will manage pages themselves > > (often using pmap_kenter_pa). > > The error message complains that you are freeing a managed page (one > > that was entered using pmap_enter) but it's pvlist is missing. The > > pvlist is a list that keeps track of which pmaps use that page. The > > missing pvlist usually happens when the page was entered using > > pmap_kenter_pa. > > The kernel_map in uvm consists of managed pages, only kmem_map (and > > other intrsafe maps) may contain unmanaged pages. Unmanaged pages cannot > > be shared across processes (because the invalidation of such a page is > > impossible due to the lack of pvlist). > > But I'm not doing anything special with pmap, and I'm not using kmem_map (no > need to be intrsafe). My own code pretty much only adds a pmap_extract() to > the above testcase, but not calling pmap_extract() doesn't prevent the > testcase from crashing. > > Is this actually a bug instead of an undocumented bit of the UVM interface? It's not well documented. I think the object parameter is one of the more recent additions, actually. I hope this helps you, -- Ariane