WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-users

Re: [Xen-users] mmap in PV xen-4.0.1

To: Eric Camachat <eric.camachat@xxxxxxxxx>
Subject: Re: [Xen-users] mmap in PV xen-4.0.1
From: Todd Deshane <todd.deshane@xxxxxxx>
Date: Tue, 9 Aug 2011 23:53:09 -0400
Cc: xen-users@xxxxxxxxxxxxxxxxxxx
Delivery-date: Tue, 09 Aug 2011 20:54:52 -0700
Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:from:date :x-google-sender-auth:message-id:subject:to:cc:content-type :content-transfer-encoding; bh=vdQ6GTi4oytPbPPDeDjRvy+9ipxYIUg4PAHSL/GfN1A=; b=IGlX+CVod4/1kgbnJM3flzbSMT5RTLgeMGK9bX6uADIZtclZ9zv9VC7tt9g5ctKCn7 qKZG3KXuKPb6haIHqrU9/eU/tJy9DZk2r3LYP6v1ZsBiOH0ekw6ygTf3zhXJURXV+Wtb F7hjjgwXnKVzH0sjHzI94G7Bi9u9q+eR76+zY=
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <CACeEFf77eOLLNgsJwEYdzeiuxm+qDcO2zs09FK-Waas0sxcwLQ@xxxxxxxxxxxxxx>
List-help: <mailto:xen-users-request@lists.xensource.com?subject=help>
List-id: Xen user discussion <xen-users.lists.xensource.com>
List-post: <mailto:xen-users@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-users>, <mailto:xen-users-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-users>, <mailto:xen-users-request@lists.xensource.com?subject=unsubscribe>
References: <CACeEFf77eOLLNgsJwEYdzeiuxm+qDcO2zs09FK-Waas0sxcwLQ@xxxxxxxxxxxxxx>
Sender: xen-users-bounces@xxxxxxxxxxxxxxxxxxx
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

<Prev in Thread] Current Thread [Next in Thread>