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

[Xen-users] mmap in PV xen-4.0.1

To: xen-users@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-users] mmap in PV xen-4.0.1
From: Eric Camachat <eric.camachat@xxxxxxxxx>
Date: Tue, 9 Aug 2011 15:57:53 -0700
Delivery-date: Tue, 09 Aug 2011 16:04:13 -0700
Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; bh=eRJ832f5lE4SaILRaU6+3IVVcNjlj5KvR++OulAeP4I=; b=BXvfr8YYjGOmURlp0T8aii+4zpoFsPeLa4adjDzaM5YfuSotEum0Kp2Y065PnVyb0f q6hp1zHXGr/Kq5KWoyfZN9OvYn8ImWCNnRoQlGFcrIL/HGO/P60O/QuSB+NkRiViqn8p LOZzzn9ncUPO555FA7A6jnb2cjOnnRQFeC6V4=
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
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>
Sender: xen-users-bounces@xxxxxxxxxxxxxxxxxxx
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
Description: Text Data

Attachment: memtest-user.c
Description: Text Data

_______________________________________________
Xen-users mailing list
Xen-users@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-users
<Prev in Thread] Current Thread [Next in Thread>