2009-06-25 05:05:25     Still unsure on MMAP

Document created by Aaronwu Employee on Aug 15, 2013
Version 1Show Document
  • View in full screen mode

2009-06-25 05:05:25     Still unsure on MMAP

Dave Henning (UNITED STATES)

Message: 76316   

 

I am trying to convert a driver (drivers/media/dvb/siano) that was written for Linux with the assumption that it could use mmap() to map a driver structure into user-space.

 

The user code that calls mmap() is here:

 

hd->common_buffer = (unsigned char *) mmap (NULL, hd->common_buffer_size, PROT_READ, MAP_SHARED, hd->fd, 0);

 

The kernel code looks like this:

 

***

struct file_operations smschar_fops = {

    .owner = THIS_MODULE,

    .read = smschar_read,

    .write = smschar_write,

    .open = smschar_open,

    .release = smschar_release,

    .mmap = smschar_mmap,

    .poll = smschar_poll,

    .ioctl = smschar_ioctl,

};

 

static int smschar_mmap(struct file *file, struct vm_area_struct *vma)

{

    struct smschar_device_t *dev = file->private_data;

    return smscore_map_common_buffer(dev->coredev, vma);

}

 

int smscore_map_common_buffer(struct smscore_device_t *coredev,

        struct vm_area_struct *vma)

{

    unsigned long end = vma->vm_end,

    start = vma->vm_start,

    size = PAGE_ALIGN(coredev->common_buffer_size);

 

    if (!(vma->vm_flags & (VM_READ | VM_SHARED)) ||

            (vma->vm_flags & VM_WRITE)) {

        sms_err("invalid vm flags");

        return -EINVAL;

    }

 

    if ((end - start) != size) {

        sms_err("invalid size %d expected %d",

                (int)(end - start), (int)size);

        return -EINVAL;

    }

 

    if (remap_pfn_range(vma, start,

            coredev->common_buffer_phys >> PAGE_SHIFT,

            size, pgprot_noncached(vma->vm_page_prot))) {

        sms_err("remap_page_range failed");

        return -EAGAIN;

    }

    return 0;

}

#endif /* SMS_HOSTLIB_SUBSYS */

 

******

 

I am trying to re-write the code to deal with uClinux's NOMMU world.   I saw the page on MMAP here:

 

  docs.blackfin.uclinux.org/doku.php?id=:mmap

 

I have also read a few threads regarding MMAP.  It seems like if I change the calling code to use MAP_PRIVATE and modify the smscore_map_common_buffer() like this, I should be well on my way.

 

int smscore_map_common_buffer(struct smscore_device_t *coredev,

        struct vm_area_struct *vma) {

 

    vma->vm_start = (unsigned long)(coredev->common_buffer_phys);

    vma->vm_flags |= VM_MAYSHARE | VM_SHARED;

    return 0;

}

 

 

 

After I switched the MAP_PRIVATE, I got the mmap() to execute without reporting an error, but I think I have the address wrong because I quickly got a kernel panic starting with:

 

*****

 

COMM=events/0 PID=5                                                           

CPU = 0                                                                       

invalid mm

 

*****

 

My questions are

 

1. I read that Blackfin wants me to use MAP_PRIVATE instead of MAP_SHARED on one of the video-related mmap() threads.  Why is this or is it specific to certain drivers?

 

2.  Am I going to set vma->vm_start to the physical or logical address of the buffer in kernel space?

 

3.  Is it necessary to set my devices .get_unmapped_buffer field to something?

 

4.  Am I on the right track here?

QuoteReplyEditDelete

 

 

2009-06-25 11:44:50     Re: Still unsure on MMAP

Dave Henning (UNITED STATES)

Message: 76334   

 

Please ignore the above post for now as I think I was on the wrong track.

 

Let me ask some general questions that will help point me in the right direction so I don't waste your time with reading specific code.

 

The driver I was given implements a character device.   This device provides a common buffer to a userspace library that interfaces with the kernel driver .  As written, the library uses a read-only, shared mmap() call to set up this buffer.   However, when executed in uClinux, the mmap() fails because it does not have a get_unmapped_buffer() function and the kernel rejects the request in mm/nommu.c::validate_mmap_request().

 

I re-read the 'nommu-mmap.txt' file in the Documentation folder of the kernel and studied nommuc.  I believe I need to follow the directions in the section "PROVIDING SHAREABLE CHARACTER DEVICE SUPPORT."  If that is the case, I want to be sure I understand what is being said there.

 

This is the process I believe I need to go through.  Please let me know if this is correct.

 

- Implement a function for f_op->get_unmapped_buffer()

 

- Set the f_op->mapping->backing_dev_info->capabilities to include BDI_CAP_MAP_DIRECT | BDI_CAP_READ_MAP in my kernel driver's init function.

 

- Modify my f_op->mmap function to simply return the address of the buffer without using remap_pfn_range().

 

- Do not change the userspace call to mmap(), specifically keeping the flag MAP_SHARED.

 

Does that correct?

 

Thanks,

 

Dave ...

Attachments

    Outcomes