On Mon, Sep 21, 2009 at 10:15 PM, Andrea Gasparini <[email protected]> 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 [email protected]
> Please read the FAQ at http://kernelnewbies.org/FAQ
>
>



-- 
Regards,
Peter Teoh

--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to [email protected]
Please read the FAQ at http://kernelnewbies.org/FAQ

Reply via email to