I'm developping a linux device driver, and I need to understand how to access a memory area allocated by the user. In details, for a 32-bytes buffer, the user calls:
void *UserAddr;
posix_memalign(&UserAddr, getpagesize(), 32); //allocation of the page-alligned buffer
memset(UserAddr, 0x55, 32); //just to see if the data in the buffer is correct
ioctl(fd, MAP_BUFFER, UserAddr); //call kernel module
now, in the kernel module ioctl, I need the phys address to pass it to a pci device for a DMA operation. what i'm currently doing is (this example is just for 1 page, to understand if it's correct):
if(!access_ok(VERIFY_READ,(char *)user_address,32*sizeof(u32)))
goto error1;
down_read(¤t->mm->mmap_sem);
if(get_user_pages(current, current->mm,(unsigned long)user_address,1,1,0,pages_list,NULL)<1)
goto error2;
up_read(¤t->mm->mmap_sem);
phys_addr=pci_map_page(dev,pages_list[0],0,PAGE_SIZE,DMA_BIDIRECTIONAL);
the code works correctly, but my questions are:
- who is "pinning" the page? or I must call explicitly SetPageReserved(pages_list[0])?
- how it works for the release when I finish using the buffer? pci_unmap and that's all? even if I called SetPageReserved?
- is it safe, in general, to call a virt_to_phys on a user-space address (if the page is pinned)? (or the virt_to_bus in case of a DMA)
- is this the "best practice" to access a user-space buffer?