Subject: Re: UVM - Kernel & User access question
To: None <tech-kern@NetBSD.org>
From: Eric Circlaeys <eric.c@mac.com>
List: tech-kern
Date: 10/25/2003 11:16:20
--Apple-Mail-5-719351052
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed

Thanks a lot!

I am closed to the success, the module runs well!

BUT a last bug appeared and seems to be in relation to UVM...

I used the following code as we built together:

void		*nm_core_uvm_allocate(struct proc *p, int size,
				      struct uvm_object **object)
{
   vsize_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(kernel_map, &handler, segment_size,
		  *object, 0, 0,
		  UVM_MAPFLAG(prot, prot, UVM_INH_NONE, 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(kernel_map, (vaddr_t)handler, segment_size);
}

Using this API in my kernel module I can now allocate and deallocate 
pageable kernel memory.
I use right now kcopy for all my needs.

BUT BUT BUT after deallocating such memory,

sometimes, my NetBSD 1.6.1, or other applications running raised an 
uvm_page_fault, or other uvm_* errors and cause a kernel panic.

Did I forget something to do when deallocating memory or usage of 
virtual / physical pages???

Thank you very much in advanced.

Best regards,
Eric.


On 20 oct. 03, at 16:21, Stephan Uphoff wrote:

>
>>> 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).
>>
>> You say that kcopy will avoid kernel panic if page is out,
>> how can I be sure that all the time I can read or write to my pageable
>> kernel memory.
>> Because as I understand kcopy will return an error if the page is out
>> but will not force the page to be up and wait for it to copy the data?
>
> Both normal memory access and kcopy will try to page in the memory
> if it is paged out - this is not the problem.
>
> However if paging in fails (disk error,...) kcopy will return an error
> while strncpy or access through a pointer would cause a kernel panic.
>
> ( for i386 take a look at pcb_onfault (PCB_ONFAULT) - an architecture
> specific exception mechanisms used for recovering from page faults
> that encountered errors in kcopy/copyin,...)
>
>
>> What kind of other functions can I use to play with that memory and be
>> sure it is wired at a time for usage?
>
> uvm_fault_wire can be used to wire the pages and you can then use 
> anything
> to access the memory and even use it in a an interrupt context.
> (uvm_fault_unwire removes the wiring)
> Once the page is wired you no longer have to worry about page faults.
> However wiring/unwiring is a relative expensive function.
>
> kcopy/copyin/copyout can be used without first wiring the pages because
> of their internal exception handling.
> ( However these functions can not be used from interrupt context)
>
>
> 	Stephan
>

--Apple-Mail-5-719351052
Content-Transfer-Encoding: 7bit
Content-Type: text/enriched;
	charset=US-ASCII

Thanks a lot!


I am closed to the success, the module runs well!


BUT a last bug appeared and seems to be in relation to UVM...


I used the following code as we built together:

<fixed><bigger>

<color><param>7675,0F0E,504F</param>void</color>		*nm_core_uvm_allocate(<color><param>7675,0F0E,504F</param>struct</color>
proc *p, <color><param>7675,0F0E,504F</param>int</color> size, 

				      <color><param>7675,0F0E,504F</param>struct</color>
uvm_object **object)

{

  vsize_t	segment_size;

  vaddr_t	handler;

  vm_prot_t	prot;

  <color><param>7675,0F0E,504F</param>int</color>		error;


  segment_size = (size + PGOFSET) & ~PGOFSET;

  *object = uao_create(segment_size,
<color><param>0000,0000,FFFE</param>0</color>);

  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(kernel_map, &handler, segment_size,

		  *object, <color><param>0000,0000,FFFE</param>0</color>,
<color><param>0000,0000,FFFE</param>0</color>,

		  UVM_MAPFLAG(prot, prot, UVM_INH_NONE, UVM_ADV_RANDOM,
<color><param>0000,0000,FFFE</param>0</color>));

  <color><param>7675,0F0E,504F</param>if</color> (error)

    {

      printf(<color><param>8988,1312,1514</param>"uvm_map
failed\n"</color>);

    

      <color><param>7675,0F0E,504F</param>return</color>
(<color><param>7675,0F0E,504F</param>NULL</color>);

    }

  

  <color><param>7675,0F0E,504F</param>return</color>
((<color><param>7675,0F0E,504F</param>void</color> *)handler);

}


<color><param>7675,0F0E,504F</param>void</color>		nm_core_uvm_deallocate(<color><param>7675,0F0E,504F</param>struct</color>
proc *p, <color><param>7675,0F0E,504F</param>int</color> size,
<color><param>7675,0F0E,504F</param>void</color> *handler,

				       <color><param>7675,0F0E,504F</param>struct</color>
uvm_object *object)

{

  size_t	segment_size;


  segment_size = (size + PGOFSET) & ~PGOFSET;

  uao_detach(object);

  uvm_deallocate(kernel_map, (vaddr_t)handler, segment_size);

}


Using this API in my kernel module I can now allocate and deallocate
pageable kernel memory.

I use right now kcopy for all my needs.


BUT BUT BUT after deallocating such memory,


sometimes, my NetBSD 1.6.1, or other applications running raised an
uvm_page_fault, or other uvm_* errors and cause a kernel panic.


Did I forget something to do when deallocating memory or usage of
virtual / physical pages???


Thank you very much in advanced.


Best regards,

Eric.

</bigger></fixed>


On 20 oct. 03, at 16:21, Stephan Uphoff wrote:


<excerpt>

<excerpt><excerpt>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).

</excerpt>

You say that kcopy will avoid kernel panic if page is out,

how can I be sure that all the time I can read or write to my pageable 

kernel memory.

Because as I understand kcopy will return an error if the page is out 

but will not force the page to be up and wait for it to copy the data?

</excerpt>

Both normal memory access and kcopy will try to page in the memory

if it is paged out - this is not the problem.


However if paging in fails (disk error,...) kcopy will return an error

while strncpy or access through a pointer would cause a kernel panic.


( for i386 take a look at pcb_onfault (PCB_ONFAULT) - an architecture

specific exception mechanisms used for recovering from page faults 

that encountered errors in kcopy/copyin,...)



<excerpt>What kind of other functions can I use to play with that
memory and be 

sure it is wired at a time for usage?

</excerpt>

uvm_fault_wire can be used to wire the pages and you can then use
anything

to access the memory and even use it in a an interrupt context.

(uvm_fault_unwire removes the wiring)

Once the page is wired you no longer have to worry about page faults.

However wiring/unwiring is a relative expensive function.


kcopy/copyin/copyout can be used without first wiring the pages because

of their internal exception handling.

( However these functions can not be used from interrupt context)



	Stephan


</excerpt>
--Apple-Mail-5-719351052--