On Fri, Dec 10, 2010 at 02:04:17PM +0100, Wouter Coene wrote:
> According to Ariane van der Steldt (ari...@stack.nl):
> > On Thu, Dec 09, 2010 at 10:32:57PM +0100, Wouter Coene wrote:
> > > +               addr = uvm_km_kmemalloc(kernel_map, NULL, PAGE_SIZE,
> > > +                   UVM_KMF_CANFAIL |  UVM_KMF_ZERO);
> > 
> > If you specify NULL as your object, you'll be given intr-safe memory.
> > You want to use kernel object instead:
> 
> Ah, now it makes sense. How about this diff:
> 
> Index: uvm.9
> ===================================================================
> RCS file: /cvs/openbsd/src/share/man/man9/uvm.9,v
> retrieving revision 1.42
> diff -u -a -r1.42 uvm.9
> --- uvm.9     9 Nov 2010 16:03:38 -0000       1.42
> +++ uvm.9     10 Dec 2010 13:00:05 -0000
> @@ -534,7 +534,12 @@
>  .Fa size
>  bytes of wired memory in the kernel map, zeroing the memory if the
>  .Fa zeroit
> -argument is non-zero.
> +argument is non-zero. Unless called on an interrupt-safe map, if memory is
> +currently unavailable,
> +.Fn uvm_km_alloc1
> +may sleep to wait for resources to be released by other processes. If not
> +enough memory is available, this function returns
> +.Dv NULL .

uvm_km_alloc1 may not be called with an intr-safe map. Only kmemalloc is
capable of understanding them. And valloc can handle any map type, since
it only allocates space, no backing store (physical pages) for the
allocation.

More on this matter below.

>  .Pp
>  The
>  .Fn uvm_km_kmemalloc
> @@ -542,6 +547,10 @@
>  .Fa size
>  bytes of wired kernel memory into
>  .Fa obj .
> +.Fa obj
> +can only be
> +.Dv NULL
> +when allocating from an interrupt-safe map.

That is correct.

>  The flags can be any of:
>  .Bd -literal
>  #define UVM_KMF_NOWAIT  0x1                     /* matches M_NOWAIT */
> @@ -608,9 +617,9 @@
>  bytes of memory in the kernel map, starting at address
>  .Fa addr .
>  .Fn uvm_km_free_wakeup
> -calls
> -.Fn thread_wakeup
> -on the map before unlocking the map.
> +wakes up any processes waiting for memory on the map (via 
> +.Fn thread_wakeup )
> +before unlocking the map.

That is also correct.

>  .Sh ALLOCATION OF PHYSICAL MEMORY
>  .nr nS 1
>  .Ft struct vm_page *
> 
> Also, maybe a stupid question, but why doesn't the irq-safety of the
> allocation depend on the VM_MAP_INTRSAFE flag, like for uvm_km_free()?

It should. In fact, I don't think there is more than 1 kernel object,
but I'd have to verify.


Strictly speaking, uvm_km should do:
[1] allocation and freeing of kernel memory
[2] submap management
[3] support the intr-safe mapping of single pages (which is special
    because some archs are pmap_direct archs).
[4] initialize kernel memory

Task 4 is implemented in uvm_km_init.
Task 3 is managed by uvm_km_getpage, uvm_km_putpage. This works well and
is clean. Non-pmap-direct archs get a lot of support code to create the
correct behaviour.
Task 2 is trivial and lives in uvm_km_suballoc.

After splitting off these functions, you get, for task 1, uvm_km_free*
for freeing (2 functions), page management (uvm_km_pgremove*) and
allocators...
  uvm_km_kmemalloc  (via a define in uvm/uvm_extern.h)
  uvm_km_kmemalloc_pla
  uvm_km_alloc1
  uvm_km_valloc
  uvm_km_valloc_try
  uvm_km_valloc_align
  uvm_km_valloc_prefer_wait
  uvm_km_valloc_wait
  uvm_km_zalloc  (via a define in uvm/uvm_extern.h)
  uvm_km_alloc  (via a define in uvm/uvm_extern.h)
This gives you 10 ways of allocating kernel memory.
uvm_km_kmemalloc is the most versatile.
The only special case are the _wait allocation functions:
uvm_km_kmemalloc would need an additional flag to duplicate their
behaviour.

There's too many allocation functions and it's too easy to get confused.
They need to be reduced (point 3 on my todo list).
Only uvm_km_kmemalloc can handle intr-safe maps.

Wired memory simply means that the memory will be there during
interrupts, but only intr-safe maps can be used to allocate from during
interrupt time. And the reason the intr-safe map is safe is because the
caller protects the map against other cpus and interrupts.


I hope this help you,
-- 
Ariane

Reply via email to