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