It seems the mux_vma_nopage() operation hadn't been called.
  ----- Original Message ----- 
  From: yihect 
  To: kernelnewbie 
  Cc: yih...@163.com 
  Sent: Thursday, March 26, 2009 1:48 PM
  Subject: question about mapping RAM into user space.


  Hi, all:
      I'm a newbie of kernel. I'm working on my mux driver in hand, and want to 
map some RAM(say, 1024*1024*2 bytes totally)into user space. 

      Accroding the LDD3 book, I'm using __get_free_pages() which be called in 
nopage() operation of struct vm_operations_struct like follow:

      /* get page from mux dev, and return it to the user. */
   struct page *mux_vma_nopage(struct vm_area_struct *vma,
   unsigned long address, int *type)
  {
      unsigned long offset;
      struct mux_dev *dev = vma->vm_private_data;
      struct page *page = NOPAGE_SIGBUS;
      void *pageptr = NULL; /* default to "missing" */


      printk("In mux_vma_nopage ############################################\n" 
);

      down(&dev->sem);
      offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
      if (offset >= dev->size) goto out; /* out of range */

      /* get page from our dev, get free page if inavialable */
      offset >>= PAGE_SHIFT; /* offset is a number of pages */
      if (!dev->data[offset])
      {
       dev->data[offset] = (void *)__get_free_pages(GFP_KERNEL, 0); /* order 
must be 0 */
       if (!dev->data[offset]) 
           goto out;
       memset(dev->data[offset], 0, PAGE_SIZE); 
      } 
      pageptr = dev->data[offset];
      page = virt_to_page(pageptr);

      /* now increment the count */
      get_page(page);
      if (type)
           *type = VM_FAULT_MINOR;

  out:
      up(&dev->sem);
      return page;
  }


      The mmap() operation of fops is like:

  int nc_mux_mmap(struct file *filp, struct vm_area_struct *vma)
  {
      /* don't do anything here: "nopage" will set up page table entries */
      vma->vm_ops = &mux_vm_ops;
      vma->vm_flags |= VM_RESERVED;
      vma->vm_private_data = filp->private_data;
      mux_vma_open(vma);
      return 0;
  }

       When I test useing code :
  address=mmap(0, len, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, offset);

      if (address == (void *)-1) {
          fprintf(stderr,"%s: mmap(): %s\n",argv[0],strerror(errno));
          exit(1);
      }
      strcpy((char *)address, "hello, world.");

  It gives me msg of "segmen fault":

  /mnt/nfs $ ./mapper /dev/mux_dev 0x0 0x400
  SDVR22xxMX MUX Device Driver Open...
  pgd = c01a4000
  [40018000] *pgd=001e8031, *pte=00000000, *ppte=00000000

  Pid: 151, comm:               mapper
  CPU: 0
  PC is at 0x4008b9f8
  LR is at 0x8960
  pc : [<4008b9f8>]    lr : [<00008960>]    Tainted: P     
  sp : bec9a64c  ip : 4008b9ec  fp : bec9ae88
  r10: 40133000  r9 : 00000000  r8 : 00008738
  r7 : 00000004  r6 : 00008b3c  r5 : 00008ad8  r4 : bec9aeb4
  r3 : 00000068  r2 : 4000f3c3  r1 : 00008c3d  r0 : 40018000
  Flags: nZCv  IRQs on  FIQs on  Mode USER_32  Segment user
  Control: 397F  Table: 001A4000  DAC: 00000015
  [<c052e7d8>] (show_regs+0x0/0x4c) from [<c0533bcc>] 
(__do_user_fault+0x5c/0xa4)
   r4 = C0039820 
  [<c0533b70>] (__do_user_fault+0x0/0xa4) from [<c0533e98>] 
(do_page_fault+0x218/0x250)
   r7 = C05240CC  r6 = C0047FB0  r5 = C0039820  r4 = FFFFFFEB
  [<c0533c80>] (do_page_fault+0x0/0x250) from [<c053401c>] 
(do_DataAbort+0x3c/0xa0)
  [<c0533fe0>] (do_DataAbort+0x0/0xa0) from [<c052c908>] 
(ret_from_exception+0x0/0x10)
   r8 = 00008738  r7 = 00000004  r6 = 00008B3C  r5 = 00008AD8
   r4 = FFFFFFFF
   SDVR22xxMX MUX Device Driver Release...
  Segmentation fault

  Platform is arm and kernel version is 2.6.14, I don'e know how to do nextly, 
is somebody have any suggestion? thanks.

Reply via email to