[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] mmap in PV xen-4.0.1
Hi, 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; } ================================================================================= Attachment:
memtest-module.c Attachment:
memtest-user.c _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |