Hackers,

I want to access a userland share memory in a kernel thread. 
So I tried to map the share memory to the kernel space. 
The basic idea is to map the shm_object into kernel_map
when the share memory is created.

Using the following patch, I found the vm_object in kernel_map,
and the vm_object in the address space of userland process are the same.
But their content in the kernel and userland address mapped are different.

It's very strang since they are exactly the same vm_object.
Do I miss something, please help.

Thanks!


Index: sys/kern/sysv_shm.c
===================================================================
--- sys/kern/sysv_shm.c (revision xxxxxx)
+++ sys/kern/sysv_shm.c (working copy)
@@ -90,11 +90,14 @@
 #include <vm/vm.h>
 #include <vm/vm_param.h>
 #include <vm/pmap.h>
+#include <vm/vm_kern.h>
 #include <vm/vm_object.h>
 #include <vm/vm_map.h>
 #include <vm/vm_page.h>
 #include <vm/vm_pager.h>
 
 static MALLOC_DEFINE(M_SHM, "shm", "SVID compatible shared memory segments");
 
 static int shmget_allocate_segment(struct thread *td,
@@ -421,6 +424,7 @@
        shmseg->u.shm_atime = time_second;
        shmseg->u.shm_nattch++;
        td->td_retval[0] = attach_va;
 done2:
        mtx_unlock(&Giant);
        return (error);
@@ -678,10 +682,61 @@
         * We make sure that we have allocated a pager before we need
         * to.
         */
-       shm_object = vm_pager_allocate(shm_use_phys ? OBJT_PHYS : OBJT_SWAP,
-           0, size, VM_PROT_DEFAULT, 0, cred);
+       if (uap->key == aaaaaa) {
+               shm_object = vm_pager_allocate(shm_use_phys ? OBJT_PHYS : 
OBJT_SWAP,
+                   0, size, VM_PROT_DEFAULT, 0, cred);
+       } else {
+               shm_object = vm_pager_allocate(OBJT_PHYS, 0, size,
+                   VM_PROT_DEFAULT, 0, cred);
+       }
        if (shm_object == NULL)
                return (ENOMEM);
+
+       if (uap->key == aaaaaa) {
+               vm_offset_t addr;
+               vm_offset_t offset;
+               vm_offset_t i;
+
+               printf("attach to kernel map.\n");
+
+               vm_map_lock(kernel_map);
+               if (vm_map_findspace(kernel_map, vm_map_min(kernel_map),
+                   size, &addr)) {
+                       vm_map_unlock(kernel_map);
+                       return (0);
+               }
+               offset = addr - VM_MIN_KERNEL_ADDRESS;
+               vm_object_reference(shm_object);
+               vm_map_insert(kernel_map, shm_object, offset, addr, addr + size,
+                       VM_PROT_ALL, VM_PROT_ALL, 0);
+               vm_map_unlock(kernel_map);
+
+               VM_OBJECT_LOCK(shm_object);
+               for (i = 0; i < size; i += PAGE_SIZE) {
+                       vm_page_t mem;
+
+                       mem = vm_page_grab(shm_object, OFF_TO_IDX(offset + i),
+                           VM_ALLOC_NOBUSY | VM_ALLOC_ZERO | VM_ALLOC_RETRY);
+                       mem->valid = VM_PAGE_BITS_ALL;
+                       KASSERT((mem->flags & PG_UNMANAGED) != 0,
+                           ("shm_alloc: page %p is managed", mem));
+               }
+               VM_OBJECT_UNLOCK(shm_object);
+
+               /*
+                * And finally, mark the data as non-pageable.
+                */
+               (void) vm_map_wire(kernel_map, addr, addr + size,
+                   VM_MAP_WIRE_USER|VM_MAP_WIRE_NOHOLES);
+
+               vm_map_inherit(kernel_map, addr, addr + size, VM_INHERIT_SHARE);
+       }
+
        VM_OBJECT_LOCK(shm_object);
        vm_object_clear_flag(shm_object, OBJ_ONEMAPPING);
        vm_object_set_flag(shm_object, OBJ_NOSPLIT);


2011-02-14 



beezarliu 
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"

Reply via email to