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 (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
Stopped at      Debugger+0x5:   leave
RUN AT LEAST 'trace' AND 'ps' AND INCLUDE OUTPUT WHEN REPORTING THIS PANIC!
DO NOT EVEN BOTHER REPORTING THIS WITHOUT INCLUDING THAT INFORMATION!
ddb> trace
Debugger() at Debugger+0x5
panic() at panic+0xe4
pmap_remove_pte() at pmap_remove_pte+0x109
pmap_do_remove() at pmap_do_remove+0x377
uvm_unmap_remove() at uvm_unmap_remove+0x19c
uvm_unmap_p() at uvm_unmap_p+0x4c
diskmapioctl() at diskmapioctl+0x26b
VOP_IOCTL() at VOP_IOCTL+0x39
vn_ioctl() at vn_ioctl+0x71
sys_ioctl() at sys_ioctl+0x111
syscall() at syscall+0x14f
--- syscall (number 54) ---
end of kernel
end trace frame: 0x7f7fffff4820, count: -11
0x20d9b5d0a:
ddb> ps
   PID   PPID   PGRP    UID  S       FLAGS  WAIT          COMMAND
*10340  22013  10340      0  7      0x4000                boom
  3266      0      0      0  3    0x100280  nfsidl        nfsio
 26078      0      0      0  3    0x100280  nfsidl        nfsio
 24745      0      0      0  3    0x100280  nfsidl        nfsio
 20995      0      0      0  3    0x100280  nfsidl        nfsio
 22818      1  22818     77  3       0x180  poll          dhclient
  4157      1   5372      0  3        0x80  poll          dhclient
 22013      1  22013      0  3      0x4080  pause         sh
    10      0      0      0  3    0x100200  aiodoned      aiodoned
     9      0      0      0  3    0x100200  syncer        update
     8      0      0      0  3    0x100200  cleaner       cleaner
     7      0      0      0  3    0x100200  reaper        reaper
     6      0      0      0  3    0x100200  pgdaemon      pagedaemon
     5      0      0      0  3    0x100200  bored         crypto
     4      0      0      0  3    0x100200  pftm          pfpurge
     3      0      0      0  3    0x100200  bored         syswq
     2      0      0      0  3  0x40100200                idle0
     1      0      1      0  3      0x4080  wait          init
     0     -1      0      0  3     0x80200  scheduler     swapper

(system wasn't running multi-user, so there's not much going on)

> 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?

Thanks,
Wouter

Reply via email to