sorry again....now I understood why the old program worked
(http://www.scs.ch/~frey/linux/memorymap.html) - because the function
declaration for remap_page_range() is different!!!
>From 2.4.17 kernel source:
/* Note: this is only safe if the mm semaphore is held when called. */
int remap_page_range(unsigned long from, unsigned long phys_addr, unsigned long
size, pgprot_t prot)
{
so phys_addr is a true physical address. and as i read a particular
instance in drivers/usb/usbvideo.c, the address is a kernel-allocated
address, which is why u don't see any vma stuff here.
On Thu, Sep 24, 2009 at 8:30 AM, Peter Teoh <[email protected]> wrote:
> 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
>
--
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