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