On Wed, 4 Jul 2007, Nicolas Cormier wrote:

On 7/4/07, Robert Watson <[EMAIL PROTECTED]> wrote:

On Mon, 2 Jul 2007, Nicolas Cormier wrote:

I am trying to map some data allocated in kernel to a user process (via a syscall). I need the proc's vmspace, but the value of p_vmspace of the input proc argument is NULL ... How can I get a valid vmspace ?

When operating in a system call, the 'td' argument to the system call function is the current thread pointer. You can follow td->td_proc to get to the current process (and therefore, its address space). In general, I prefer mapping user pages into kernel instead of kernel pages into user space, as it reduces the chances of leakage of kernel data to user space, and there are some useful primitives for making this easier. For example, take a look at the sf_buf infrastructure used for things like socket zero-copy send, which manages a temporary kernel mapping for a page.

Yes Roman told me in private that I'm wrong with the first argument, I thought that it was a proc*...

For my module I try to create a simple interface of a network allocator: User code should look like this:

unsigned id;
void* data = netmalloc(host, size, &id);
memcpy(data, "toto", sizeof("toto");
netdetach(data);

and later in another process:
void* data = netattach(host, id);
...
netfree(data);

netmalloc syscall does something like that:
- query distant host to allocate size
- receive an id from distant host
- malloc in kernel size
- map the buffer to user process (*)

netdetach syscall:
- send data to distant host

netattach syscall:
- get data from host
- malloc in kernel size
- map the buffer to user process (*)

* I already watch the function vm_pgmoveco
(http://fxr.watson.org/fxr/source/kern/kern_subr.c?v=RELENG62#L78)

I used pgmoveco as follow:

vm_map_t mapa = &proc->p_vmspace->vm_map,
size = round_page(size);
void* data = malloc(size,  M_NETMALLOC, M_WAITOK);
vm_offset_t addr = vm_map_min(mapa);
vm_map_find(mapa, NULL, 0, &addr, size, TRUE, VM_PROT_ALL,
VM_PROT_ALL, MAP_NOFAULT);
vm_pgmoveco(mapa, (vm_offset_t)data, addr);


With this I have a panic with vm_page_insert, I am not sure to understand the reason of this panic. I can't have multiple virtual pages on the same physical page ?

I think part of what you're running into here is a conceptual issue. The pages allocated by malloc(9) belong to the kernel memory allocator, and are generally managed by the slab allocator. While in principle you can map them into user space, you're going to have to set up a lot of book-keeping to properly free them again later, etc. There are really two approaches you could be looking at:

(1) The user app allocates memory pages, perhaps using mmap() to map anonymous
    memory or a file.  You then borrow those pages to use in-kernel, mapping
    as required.

(2) Your kernel code allocates pages directly from the VM system, possibly
    anonymous swap-backed pages from the page allocator, and maps them into
    the kernel as required.

In either case, you'll need to think about address space limits, especially if the buffer is large -- the kernel address space on 32-bit systems is limited in size, since it shares the address space with a user application. On 64-bit systems, this is not an issue. You'll also need to make sure that the pages are both paged in and pinned in memory. So before we talk about the details of the calls, we should think about how you plan to use the memory.

How much memory are we talking about -- enough to potentially run into kernel address space problems on 32-bit systems? How long will the mappings persist -- do you map them into kernel for a brief period to fill them, and then leave them mapped into user space, or is this going to be a persistent shared mapping over a very long period of time? Is the memory going to be pageable? How will it interact with things like mprotect(), msync(), etc? What should happen if a the pages are released by the process using munmap() or by mapping over the region with mmap()? What should happen in a child process if a process forks after netattach() and the parent calls netdatach()? What happens if the process calls send() using a source address in the memory region, and zero-copy sockets are enabled, which would normally lead the page to be "borrowed" from the user process?

The underlying point here is that there is a model by which VM is managed -- pages, pagers, memory objects, mappings, address spaces, etc. We can't just talk about pages being shared or mapped, we need to think about what is to be accomplished, and how to map that into the abstractions that already exist. Memory comes in different flavours, and generally speaking, you don't want to use pages that come from malloc(9) for sharing with userspace, so we need to think about what kind of memory you do need.

Robert N M Watson
Computer Laboratory
University of Cambridge
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to