Subject: Re: UVM - Kernel & User access question
To: Eric Circlaeys <eric.c@mac.com>
From: Stephan Uphoff <ups@stups.com>
List: tech-kern
Date: 10/17/2003 10:16:09
error = uvm_map(&p->p_vmspace->vm_map, &handler, segment_size,
> *object, 0, 0,
> UVM_MAPFLAG(prot, prot, UVM_INH_SHARE, UVM_ADV_RANDOM, 0));
p->p_vmspace->vm_map is the user space map of the process p.
Since you want kernel space you need to use kernel_map instead
error = uvm_map(kernel_map,....
I would also replace UVM_INH_SHARE with UVM_INH_NONE.
( Not that inheritance matters in the kernel ... )
> strncpy(pointeur, "toto\0", 5);
strncpy(pointeur, "toto\0", 5); is a dangerous way to access the memory.
If the buffer is paged out and the swap is bad (disk error) you will get
a kernel panic.
Using kcopy/uiomove you can try to copy the memory - and the functions will
just return an error on failure (no kernel panic).
> BUT questions:
> Is that new allocated pointer available at any time physically?
The memory is pageable and in kernel space.
Since accessing it can cause a (major) page fault (sleep) the memory can
not be accessed from interrupt context. (Unless wired before - making it
non pageable)
It should only be accessed using special functions (unless temporarily wired)
to avoid kernel panics on swap space errors.
> Is this using virtual space, or physical?
pageable virtual space - physical pages are allocated by page faults and
can change.
> Is it similar to malloc used in kernel?
malloc memory is not pageable.
Stephan
Eric Circlaeys wrote:
> Here the code I used:
>
> TEST is a test call used in a kthread.
> And get a page fault...
>
> TEST
> {
> struct uvm_object *o;
> char *pointeur;
>
> pointeur = (char *)nm_core_uvm_allocate(curproc, 6, &o);
>
> // tried
> strncpy(pointeur, "toto\0", 5);
> // or
> copyout("toto\0", pointeur, 5);
>
> printf("%s", pointeur);
>
> nm_core_uvm_deallocate(p, 5, pointeur, o);
> }
>
> void *nm_core_uvm_allocate(struct proc *p, int size,
> struct uvm_object **object)
> {
> size_t segment_size;
> vaddr_t handler;
> vm_prot_t prot;
> int error;
>
> segment_size = (size + PGOFSET) & ~PGOFSET;
> *object = uao_create(segment_size, 0);
> prot = VM_PROT_READ | VM_PROT_WRITE;
> handler = round_page((vaddr_t)p->p_vmspace->vm_taddr + MAXTSIZ +
> MAXDSIZ);
>
> uao_reference(*object);
> error = uvm_map(&p->p_vmspace->vm_map, &handler, segment_size,
> *object, 0, 0,
> UVM_MAPFLAG(prot, prot, UVM_INH_SHARE, UVM_ADV_RANDOM, 0));
> if (error)
> {
> printf("uvm_map failed\n");
>
> return (NULL);
> }
>
> return ((void *)handler);
> }
>
> void nm_core_uvm_deallocate(struct proc *p, int size, void *handler,
> struct uvm_object *object)
> {
> size_t segment_size;
>
> segment_size = (size + PGOFSET) & ~PGOFSET;
> uao_detach(object);
> uvm_deallocate(&p->p_vmspace->vm_map, (vaddr_t)handler, segment_size);
> }
>
>
> I just tried the following with your help and it works:
>
> TEST
> {
> char *pointeur;
>
> pointeur = (char *)uvm_km_valloc_wait(kernel_map, 10);
>
> strcpy(pointeur, "toto\0");
>
> printf("%s\n", pointeur);
> }
>
> BUT questions:
> Is that new allocated pointer available at any time physically?
> Is this using virtual space, or physical?
> Is it similar to malloc used in kernel?
>
> What I would like is to allocate large amount of data without using
> physical kernel memory but using the vm, all of this in a kernel
> process.
> This data should be able to access in the kernel process for read and
> write...
>
> Thank you a lot for your help.
> Eric.
>
> On 17 oct. 03, at 03:49, Stephan Uphoff wrote:
>
> >
> >> der Mouse wrote:
> >>> Eric Circlaeys wrote:
> >>> I would like to use UVM to allocate large memory in kernel land. I
> >>> used uao_create, round_page, uvm_map to allocate virtual space.
> >>
> >> As I understand it, those allocate userland VM.
> >
> > Depends on the map passed to uvm_map().
> > A kernel (sub) map will result in kernel virtual space.
> >
> > Do you need more than uvm_km_valloc_wait(kernel_map, sizeOfYourBuffer)
> > ?
> >
> >>
> >>> But now I would like to write and read inside those pages still being
> >>> in kernel land. When I tried with copyout to write buffer inside it
> >>> I got a page fault...
> >
> > copyin/copyin_proc from userspace to your buffer
> > or kcopy from/to "normal" kernel space to/from your buffer.
> > (or uiomove() as a parameter based wrapper around the functions above)
> >
> > You can also temporary wire the memory to access it without special
> > functions.
> > ( The only way to access it from interrupt context)
> >
> > Without more information is is hard to guess your problem.
> >
> >
> > Stephan
> >