system calls for physical buffers allocation

Andrea Cisternino (acister@pcape1.pi.infn.it)
Wed, 04 Mar 1998 17:26:56 +0100


Hi Everybody,
Thanks for your work and excuse me for the lengthy message.

I'm trying to write a small set of new system calls for 2.0.33 as part of
a project here at INFN. These calls will allow user-space applications to
"malloc" in user space contiguous buffers of physical RAM originally
obtained with the BIGPHYSAREA patch.

I've implemented three new system calls:

bpalloc()
bpfree()
bpgetphys()

All of them passed a minuscule set of tests (dont' crash the system, get
executed, their results are meaningful, I can R/W to the area :-) but I'm
far from being a MM expert so I would like to have your comments on some
details.

** bpalloc() **

This is basically a stripped down version of do_mmap with the addition of
a bigphysarea_alloc_pages() call near the beginning to actually get the
memory. In the vma that I'm using to build the mappings I set the flags in
the following way:

vma->vm_flags = (PROT_READ | PROT_WRITE) | mm->def_flags;
vma->vm_flags |= (VM_SHARED| VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE);

The virtual address is obtained with:

virt_addr = get_unmapped_area (0, size_in_bytes);

Other settings in the vma are:

vma->vm_start = virt_addr;
vma->vm_ops = NULL;
vma->vm_inode = NULL;
vma->vm_pte = 0;

The actual mapping is performed with (stripped code):

vma->vm_offset = phys_addr_from_bigphysalloc;
remap_page_range (vma->vm_start, vma->vm_offset, size, vma->
vm_page_prot);
insert_vm_struct (mm, vma);
merge_segments (mm, vma->vm_start, vma->vm_end);
mm->total_vm += size_in_bytes >> PAGE_SHIFT;

return virt_addr;

Comments and/or suggestions?

** bpfree() **

This is very simple:

asmlinkage void sys_bpfree(unsigned long addr)
{
range_t **range_ptr;

if (addr == 0UL)
return;

/*
* Search the block in the used list.
*/
for (range_ptr = &used_list; *range_ptr != NULL;
range_ptr = &(*range_ptr)->next)
if ((*range_ptr)->virt == addr)
break;

if (*range_ptr == NULL)
return;

(void) do_munmap((*range_ptr)->virt, (*range_ptr)->size);
bigphysarea_free_pages((*range_ptr)->base);
}

Do I have to use the do_munmap() return code in some way?

** bpgetphys() **

This returns to the user the physical address of the memory buffer. This address could be used to set PCI hardware registers directly from user-space (I know that this can be dangerous but this could be a requirement for our particular application).

One last question: right now the real system calls are defined in this way:

asmlinkage unsigned long sys_bpalloc (unsigned int size)
asmlinkage void sys_bpfree (unsigned long addr)
asmlinkage unsigned long sys_bpgetphys (unsigned long addr)

These definitions shut up gcc during compilation but are they correct as regards the pointer<=>integer issue? In other words are there any types that would fit better (e.g. be "64 bit clean") without giving warnings? I'm sorry but I'm a little bit confused by long, int, caddr_t, void *, daddr_t, __kernel_caddr_t etc. :-)

TIA,
Andrea.

-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~~~~~~~~~~~~
Andrea Cisternino    (Tel: 39-50-880306)| APEmille Team
INFN Pisa - Italy    (Fax: 39-50-880317)| Debian GNU/Linux
<URL:http://pcape1.pi.infn.it/~acister> | Climb and be happy !!!!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+~~~~~~~~~~~~~~~~~~~~~~~~~~~
  PGP FP: 72 ED D4 1E DE 1E 92 9D  88 E9 C7 6A 32 33 32 1D
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu