[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-users] mmap in PV xen-4.0.1
On Tue, Aug 9, 2011 at 6:57 PM, Eric Camachat <eric.camachat@xxxxxxxxx> wrote: > Hi, > This is probably a better question for the xen-devel mailing list. See: http://wiki.xensource.com/xenwiki/AskingXenDevelQuestions > I have a problem to map kernel memory to userspace via /dev/mem. > The mmap() succeeded, but when I try to access it, the program will > hang forever (until press ctrl-c to terminate it). > > # memtest-user > memtest_vma_open: virt 0x7fbc90085000, phys 0x3eee8000 > paddr = 0x3eee8000 > mem = 0x7fbc90089000 > map = 0x7fbc90085000 > map[0]= 4c4c4c4c > map[1]= 4c4c4c4c > *** Hang here, it cannot (finish) access the memory mapped via /dev/mem *** > > My test source below, and it runs properly on HVM, VirtualBox, QEM and > physical machines. > What mistake I did? > > My kernel module look like this: > ================================================================================= > #include <linux/module.h> > #include <linux/moduleparam.h> > #include <linux/types.h> > #include <linux/kernel.h> > #include <linux/fs.h> > #include <linux/mm.h> > #include <asm/io.h> > #include <asm/page.h> > > #define MEMTEST_MAJOR 886 > #define MEMTEST_NAME "memtest" > > #define MEMTEST_MAGIC 'M' > #define MEMTEST_DMA_SIZE _IO(MEMTEST_MAGIC, 0) > #define MEMTEST_DMA_PADDR _IO(MEMTEST_MAGIC, 1) > #define MEMTEST_DMA_VADDR _IO(MEMTEST_MAGIC, 2) > > #define SIZE_ORDER 2 > static uint32_t _size = (PAGE_SIZE << SIZE_ORDER); > static unsigned long _vbase = 0; > static phys_addr_t _pbase = 0; > > static int > memtest_ioctl(struct inode *inode, struct file *file, unsigned int cmd, > unsigned long arg) > { > int ret = -ENOIOCTLCMD; > phys_addr_t *paddr; > unsigned long *vaddr; > uint32_t *size; > > switch(cmd) { > case MEMTEST_DMA_SIZE: > size = (uint32_t*)arg; > *size = _size; > ret = 0; > break; > case MEMTEST_DMA_PADDR: > paddr = (phys_addr_t*)arg; > *paddr = _pbase; > ret = 0; > break; > case MEMTEST_DMA_VADDR: > vaddr = (unsigned long*)arg; > *vaddr = _vbase; > ret = 0; > break; > } > return ret; > } > > static void memtest_vma_open(struct vm_area_struct *vma) > { > printk("%s: virt %#lx, phys %#lx\n", __func__, vma->vm_start, > vma->vm_pgoff << PAGE_SHIFT); > } > static void memtest_vma_close(struct vm_area_struct *vma) > { > printk("%s\n", __func__); > } > static struct vm_operations_struct memtest_vm_ops = { > .open = memtest_vma_open, > .close = memtest_vma_close, > }; > static int memtest_mmap(struct file * file, struct vm_area_struct * vma) > { > /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ > if (remap_pfn_range(vma, > vma->vm_start, > vma->vm_pgoff, > vma->vm_end - vma->vm_start, > vma->vm_page_prot)) { > return -EAGAIN; > } > > vma->vm_ops = &memtest_vm_ops; > memtest_vma_open(vma); > return 0; > } > > static struct file_operations memtest_fops = { > .owner = THIS_MODULE, > .llseek = no_llseek, > .ioctl = memtest_ioctl, > .mmap = memtest_mmap, > }; > > static int __init memtest_init(void) > { > int retval; > > printk(MEMTEST_NAME ": registering /dev/" MEMTEST_NAME " > (%d)\n",MEMTEST_MAJOR ); > retval = register_chrdev(MEMTEST_MAJOR, MEMTEST_NAME, &memtest_fops); > if (retval < 0) > { > printk(MEMTEST_NAME ": failed to register /dev/" MEMTEST_NAME > "\n"); > } > printk(MEMTEST_NAME ": size of phys_addr_t is %lu bytes\n", > sizeof(phys_addr_t)); > > //_vbase = get_zeroed_page(GFP_KERNEL); > _vbase = __get_free_pages(GFP_KERNEL, SIZE_ORDER); > if (_vbase == 0) > { > printk(MEMTEST_NAME ": kmalloc(%d, GFP_KERNEL) failed\n", > _size); > } > else > { > memset((void*)_vbase, 'L', _size); > ((uint32_t*)_vbase)[0] = 0x1234; > ((uint32_t*)_vbase)[1] = 0xabcd; > ((uint32_t*)_vbase)[2] = 0xeeee; > ((uint32_t*)_vbase)[3] = 0xffff; > _pbase = virt_to_bus((void*)_vbase); > } > > printk(MEMTEST_NAME ": _vbase = %#lx\n", _vbase); > printk(MEMTEST_NAME ": _pbase = %#lx\n", (unsigned long)_pbase); > return retval; > } > > static void __exit memtest_exit(void) > { > if (_vbase != 0) > free_page(_vbase); > unregister_chrdev(MEMTEST_MAJOR, MEMTEST_NAME); > } > > > MODULE_LICENSE("GPL"); > > module_init(memtest_init); > module_exit(memtest_exit); > ================================================================================= > > Here is my user program: > > ================================================================================= > #include <stdio.h> > #include <stdlib.h> > #include <sys/mman.h> > #include <unistd.h> > #include <sys/ioctl.h> > #include <fcntl.h> > #include <errno.h> > #include <stdint.h> > > #define MEMTEST_MAGIC 'M' > #define MEMTEST_DMA_SIZE _IO(MEMTEST_MAGIC, 0) > #define MEMTEST_DMA_PADDR _IO(MEMTEST_MAGIC, 1) > #define MEMTEST_DMA_VADDR _IO(MEMTEST_MAGIC, 2) > > #define DEVDIAG "/dev/memtest" > #define DEVMEM "/dev/mem" > uint32_t get_size(void); > unsigned long get_paddr(void); > unsigned int * mmap_memtest(unsigned long paddr, uint32_t size); > unsigned int * mmap_mem(unsigned long paddr, uint32_t size); > > uint32_t get_size(void) > { > int diagfd, rv; > uint32_t size; > > diagfd = open( DEVDIAG, O_RDWR | O_SYNC | O_DSYNC | O_RSYNC ); > if (diagfd < 0) > { > perror("Error : fail to open" DEVDIAG); > return 0; > } > > rv = ioctl( diagfd, MEMTEST_DMA_SIZE, &size); > if (rv < 0) > { > perror("Fail to perform ioctl"); > return 0; > } > close(diagfd); > > return size; > } > > unsigned long get_paddr(void) > { > int diagfd, rv; > unsigned long paddr; > > diagfd = open( DEVDIAG, O_RDWR | O_SYNC | O_DSYNC | O_RSYNC ); > if (diagfd < 0) > { > perror("Error : fail to open" DEVDIAG); > return 0; > } > rv = ioctl( diagfd, MEMTEST_DMA_PADDR, &paddr); > if ( rv < 0 ) { > perror("Fail to perform ioctl"); > return 0; > } > close(diagfd); > > return paddr; > } > > unsigned int * mmap_memtest(unsigned long paddr, uint32_t size) > { > int diagfd; > unsigned int page_size = getpagesize(); > unsigned int page_mask = ~(page_size - 1); > unsigned int *vaddr = NULL; > > /** test mmap */ > if ( paddr & ~page_mask ) { > printf("Error : not algined %#lxx & %08x\n", paddr, ~page_mask > ); > return NULL; > } > > diagfd = open( DEVDIAG, O_RDWR | O_SYNC | O_DSYNC | O_RSYNC ); > if (diagfd < 0) > { > printf("Error : fail to open "DEVDIAG); > return NULL; > } > > > vaddr = (unsigned int*) mmap(NULL, size, PROT_READ, MAP_SHARED, > diagfd, paddr); > close(diagfd); > > return vaddr; > } > > unsigned int * mmap_mem(unsigned long paddr, uint32_t size) > { > int memfd; > unsigned int page_size = getpagesize(); > unsigned int page_mask = ~(page_size - 1); > unsigned int *vaddr = NULL; > > /** test mmap */ > if ( paddr & ~page_mask ) { > printf("Error : not algined %#lxx & %08x\n", paddr, ~page_mask > ); > return NULL; > } > > memfd = open(DEVMEM, O_RDWR | O_SYNC | O_DSYNC | O_RSYNC); > if (memfd < 0) > { > perror("Error : fail to open "DEVMEM); > return NULL; > } > > vaddr = (unsigned int*) mmap(NULL, size, PROT_READ, MAP_SHARED, > memfd, paddr); > close(memfd); > > return vaddr; > } > > int main(int argc, char **argv) > { > uint32_t size = get_size(); > unsigned long paddr = get_paddr(); > unsigned int *mem = mmap_mem(paddr, size); > unsigned int *map = mmap_memtest(paddr, size); > > printf("paddr = %#lx\n", paddr); > printf(" mem = %p\n", mem); > printf(" map = %p\n", map); > > if (map) > { > printf("map[0]= %x\n", map[0]); > printf("map[1]= %x\n", map[1]); > } > > if (mem) > { > printf("mem[0]= %x\n", mem[0]); > printf("mem[1]= %x\n", mem[1]); > } > > return 0; > } > ================================================================================= > > _______________________________________________ > Xen-users mailing list > Xen-users@xxxxxxxxxxxxxxxxxxx > http://lists.xensource.com/xen-users > -- Todd Deshane http://www.linkedin.com/in/deshantm http://www.xen.org/products/cloudxen.html http://runningxen.com/ _______________________________________________ Xen-users mailing list Xen-users@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-users
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |