Hi, I use remap_pfn_range to do mmap, and it can work.
Best Regards, Peter Chen On Thu, 2009-03-26 at 14:03 +0800, yihect wrote: > It seems the mux_vma_nopage() operation hadn't been called. > ----- Original Message ----- > From: yihect > To: kernelnewbie > Cc: [email protected] > 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[J > 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.
