Re: implementing mmap

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Sep 21, 2009 at 10:15 PM, Andrea Gasparini <gaspa@xxxxxxxxxxx> wrote:
> Hi,
> I'm just writing some code that wants to implement a stupid mmap on a
> device.
> What  I did is the following:
> 1 - allocating a buffer with kmalloc:
>        kmalloc_ptr = kmalloc(LEN + 2 * PAGE_SIZE, GFP_KERNEL);
> 2 - make sure that it's page aligned:
>        kmalloc_area = (kmalloc_ptr + PAGE_SIZE -1) & PAGE_MASK;
>  ( _area and _ptr point to the same address, though )
> 3 - fill it with some dumb numbers and print them to check:
>        for( i = 0; i < LEN; i++) {
>                ((unsigned char*)kmalloc_area)[i] = (unsigned char)i;
>        }
>        for( i = 0; i < 20; i++) {
>                printk(" %d ",( (unsigned char*)kmalloc_area)[i]);
>        }
> 4 - in properly registered mmap, driver side, i wrote simply:
>      ret = remap_pfn_range(vma, vma->vm_start,
>             virt_to_phys(kmalloc_area) >> PAGE_SHIFT,
>             vma->vm_end-vma->vm_start, vma->vm_page_prot);

this is wrong.    read the comment for the function:

  1688	/**
  1689	 * remap_pfn_range - remap kernel memory to userspace
  1690	 * @vma: user vma to map to
  1691	 * @addr: target user address to start at
  1692	 * @pfn: physical address of kernel memory
  1693	 * @size: size of map area
  1694	 * @prot: page protection flags for this mapping
  1695	 *
  1696	 *  Note: this is only safe if the mm semaphore is held when called.
  1697	 */
  1698	int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
  1699                      unsigned long pfn, unsigned long size, pgprot_t prot
)

so addr is a user virtual address, not physical, and must be allocated
from userspace.   (get_user_pages() or something like that).

another code to confirm your understanding is inside the above function:

  1724		 */
  1725		if (addr == vma->vm_start && end == vma->vm_end) {
  1726			vma->vm_pgoff = pfn;
  1727			vma->vm_flags |= VM_PFN_AT_MMAP;
  1728		} else if (is_cow_mapping(vma->vm_flags))
  1729			return -EINVAL;
  1730
  1731		vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;

remember, vma's start and end is the limits bounding the userspace
address, in terms of VMA chunks.   so addr must be withing this range,
ie, must be allocated and added to the VMA linked list as well.

>
> Ok, what's wrong with that? From a userspace test program, I got only
> zeroes:
>   fd = open("/dev/mmaptest",O_RDWR);
>   mmapped_ptr = mmap(NULL,SIZE,PROT_READ | PROT_WRITE, MAP_FILE |
> MAP_SHARED ,fd,0);
>   for( i=0; i < SIZE; i++){
>       printf(" i=%d, mmap[%d]=%d\n",i,i,mmapped_ptr[i]);
>   }
> and that's the output:
>  i=0, mmap[0]=0
>  i=1, mmap[1]=0
>  i=2, mmap[2]=0
> ...
>
> I'm clearly missing something trivial, and probably need more coffe... ;)
> Ideas?
> Thanks in advance.
> --
> -gaspa-
> -----------------------------------------------
> -------- https://launchpad.net/~gaspa ---------
> ------ HomePage: iogaspa.altervista.org -------
> -Il lunedi'dell'arrampicatore: www.lunedi.org -
>
> --
> To unsubscribe from this list: send an email with
> "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
> Please read the FAQ at http://kernelnewbies.org/FAQ
>
>



-- 
Regards,
Peter Teoh

--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx
Please read the FAQ at http://kernelnewbies.org/FAQ



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux