[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] Mapping granted pages in the user space of a domU



> -----Original Message-----
> From: xen-devel-bounces@xxxxxxxxxxxxx [mailto:xen-devel-
> bounces@xxxxxxxxxxxxx] On Behalf Of Sébastien FREMAL [530784]
> Sent: Wednesday, February 27, 2013 9:57 AM
> To: xen-devel@xxxxxxxxxxxxx
> Subject: [Xen-devel] Mapping granted pages in the user space of a domU
> 
> Hello,
> 
> I'm creating a communication channel between an application running in
> the dom0 and applications running in domU's. I mapped several pages of
> the kernel space of the dom0 in its user space (and this part works
> fine) and I granted the access to these pages to a domU. The module
> running in this domU successfuly retrieves these pages and their content
> but I don't find how to map the pages in the user space.
> 
> I already tried several possibilities I found on the web :
> 
> ========================================================================
> ==================================
> 
> The code of the module :
> 
> #undef __KERNEL__
> #define __KERNEL__
> 
> #undef MODULE
> #define MODULE
> 
> #include <xen/grant_table.h>
> #include <xen/page.h>
> #include <asm/xen/hypercall.h>
> #include <linux/gfp.h>
> #include <linux/module.h>
> #include <linux/vmalloc.h>
> #include <linux/kernel.h>
> #include <linux/init.h>
> #include <asm/page.h>
> #include <linux/delay.h>
> #include <linux/time.h>
> #include <linux/fs.h>
> #include <linux/cdev.h>
> 
> MODULE_LICENSE("GPL");
> 
> // internal data
> // length of the two memory areas
> enum{NUM_ALLOC = 1};
> enum{PAGES_PER_ALLOC = 4};
> 
> struct gnttab_map_grant_ref ops[NUM_ALLOC*PAGES_PER_ALLOC];
> struct gnttab_unmap_grant_ref unmap_ops[NUM_ALLOC*PAGES_PER_ALLOC];
> struct vm_struct * v_start;
> 
> static dev_t mmap_dev;
> static struct cdev mmap_cdev;
> 
> static int mmap_open(struct inode * inode, struct file *filp);
> static int mmap_release(struct inode * inode, struct file * filp);
> static int mmap_mmap(struct file * filp, struct vm_area_struct *vma);
> 
> static struct file_operations mmap_fops = {
>         .open = mmap_open,
>         .release = mmap_release,
>         .mmap = mmap_mmap,
>         .owner = THIS_MODULE,
> };
> 
> 
> static int mmap_open(struct inode *inode, struct file * filp){
>         printk(KERN_INFO "MMap_open invoked\n");
>         return 0;
> }
> 
> static int mmap_release(struct inode * inode, struct file * filp){
>         printk(KERN_INFO "MMap_release invoked\n");
>         return 0;
> }
> 
> struct mmap_info{
>       char * data;
>       int reference;
> };
> 
> static int mmap_mmap(struct file * filp, struct vm_area_struct * vma){
>         int ret;
>         size_t length = vma->vm_end - vma->vm_start;
>         size_t num_pages = length/PAGE_SIZE;
>         size_t i=0;;
> 
>         printk(KERN_INFO "Length : %lu, pages : %lu \n", length,
> length/PAGE_SIZE);
> 
>         if(length > NUM_ALLOC * PAGES_PER_ALLOC * PAGE_SIZE){
>                 printk("Request for a chunk of memory bigger than the
> available memory\n");
>                 return -EIO;
>         }
> 
>       for(i=0;i<num_pages;++i){
> 
>                 //FIRST ATTEMPT
>               if((ret = remap_pfn_range(vma,
>                                       vma->vm_start+i*PAGE_SIZE,
>                                       page_to_pfn(vmalloc_to_page(v_start-
> >addr+i*PAGE_SIZE)),
>                                       PAGE_SIZE,
>                                       vma->vm_page_prot))<0){
>                       printk(KERN_INFO "Error in remap_pfn_range");
>                       return ret;
>               }
> 
> /*
>                 //SECOND ATTEMPT
>               unsigned long mfn = PFN_DOWN(ops[i].dev_bus_addr);
>               if((ret=m2p_add_override(mfn, virt_to_page(vma-
> >vm_start+i*PAGE_SIZE), NULL))>0){
>                       printk(KERN_INFO "Overriding failed\n");
>                       return ret;
>               }
> 
>                 //THIRD ATTEMPT
>               struct mmap_info * info = (struct mmap_info *) filp-
> >private_data;
>               unsigned long mfn = PFN_DOWN(ops[i].dev_bus_addr);
>                 if((ret=m2p_add_override(mfn, virt_to_page(info-
> >data+i*PAGE_SIZE), NULL))>0){
>                         printk(KERN_INFO "Overriding failed\n");
>                         return ret;
>                 }
> 
>                 //FOURTH ATTEMPT
>                 if((ret = remap_vmalloc_range(vma, v_start->addr,
> 0))<0){
>                        printk(KERN_INFO "Error in remap_vmalloc_range");
>                        return ret;
>                 }
> */
>                 printk(KERN_INFO "Page %lu mapped\n", i);
>                 printk(KERN_INFO "Content : %d - %d\n", *((int
> *)ops[i].host_addr), *((int *) v_start->addr));
> 
>       }
> 
>         printk(KERN_INFO "MMaped\n");
> 
>         return 0;
> }
> 
> static int __init mapped_init(void){
>         int i, ret;
> 
>       printk(KERN_INFO "Using shared memory in Xen \n");
> 
>         if((ret = alloc_chrdev_region(&mmap_dev,0,1,"mmap"))<0){
>                 printk(KERN_INFO "Could not allocate major number for
> mmap\n");
>                 return ret;
>         }
> 
>         cdev_init(&mmap_cdev, &mmap_fops);
>         if((ret=cdev_add(&mmap_cdev, mmap_dev, 1))<0){
>                 printk(KERN_INFO "Could not allocate chrdev for
> mmap\n");
>                 unregister_chrdev_region(mmap_dev, 1);
>               return ret;
>       }
> 
>       v_start = alloc_vm_area(PAGE_SIZE*NUM_ALLOC*PAGES_PER_ALLOC,NULL);
> 
>         if(v_start==0){
>                 printk(KERN_INFO "Problem allocating vm area\n");
>                 return -EFAULT;
>         }
> 
>         for(i=0;i<NUM_ALLOC*PAGES_PER_ALLOC;++i){
>               ops[i].flags = GNTMAP_host_map;
>               ops[i].ref = 8+i;
>               ops[i].dom = 0;
>               ops[i].host_addr = (unsigned long)(((char*) v_start-
> >addr)+i*PAGE_SIZE);
>       }
> 
>         if(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, ops,
> NUM_ALLOC*PAGES_PER_ALLOC)){
>                       printk(KERN_INFO "Hypervisor map grant failed\n");
>                       free_vm_area(v_start);
>                       return -EFAULT;
>               }
> 
> 
>       for(i=0;i<NUM_ALLOC*PAGES_PER_ALLOC;++i){
>               if(ops[i].status){
>                       printk(KERN_INFO "Hyper map grant failed with status
> %d\n", ops[i].status);
>                       free_vm_area(v_start);
>                       return -EFAULT;
>               }
> 
>               unmap_ops[i].host_addr = ops[i].host_addr;
>               unmap_ops[i].handle = ops[i].handle;
> 
>               printk(KERN_INFO "Number : %d\n", *((int
> *)ops[i].host_addr));
>       }
> 
>         return 0;
> }
> 
> static int  __exit mapped_exit(void){
>       if(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap_ops,
> NUM_ALLOC*PAGES_PER_ALLOC))
>                       printk("Error in unmapping operation\n");
>         free_vm_area(v_start);
>       printk("Mapping module cleaned\n");
>       return 0;
> }
> 
> module_init(mapped_init)
> module_exit(mapped_exit)
> 
> 
> Mapping :
> 
> int main(void)
> {
>   int fd;
>   int *vadr;
> 
>   unsigned long len = getpagesize(), i;
> 
>   if ((fd=open("node", O_RDWR|O_SYNC))<0)
>   {
>       perror("open");
>       exit(-1);
>   }
> 
>   vadr = mmap(0, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
> 
>   if (vadr == MAP_FAILED)
>   {
>           perror("mmap");
>           exit(-1);
>   }
> 
>   for(i=0;i<len/sizeof(int);i+=(getpagesize()/sizeof(int))){
>           printf("%d\n",*(vadr+i));
>           vadr[i]=vadr[i]+1;
>   }
> 
>   close(fd);
>   return(0);
> 
> }
> 
> ========================================================================
> =================================
> 
> The first attempt doesn't indicate any error but I don't get the good
> page (I put the value "3" in the page but the application read the value
> 0).
> 
> The second attempt gives an error in the module :
> [   86.071090] WARNING: at /build/buildd/linux-
> 3.2.0/arch/x86/xen/p2m.c:696 m2p_add_override+0x7b/0x3c0()
> [   86.071093] m2p_add_override: pfn f73ed13ae not mapped
> [   86.071095] Modules linked in: shm13(O) lp parport
> [   86.071101] Pid: 1324, comm: fill Tainted: G           O 3.2.0-34-
> generic #53-Ubuntu
> [   86.071103] Call Trace:
> [   86.071110]  [<ffffffff81066f0f>] warn_slowpath_common+0x7f/0xc0
> [   86.071113]  [<ffffffff81067006>] warn_slowpath_fmt+0x46/0x50
> [   86.071116]  [<ffffffff8100b62b>] m2p_add_override+0x7b/0x3c0
> [   86.071121]  [<ffffffff8164328c>] ? printk+0x51/0x53
> [   86.071126]  [<ffffffffa0019116>] mmap_mmap+0xd6/0x128 [shm13]
> [   86.071129]  [<ffffffff810064fe>] ? xen_pmd_val+0xe/0x10
> [   86.071134]  [<ffffffff811437e9>] mmap_region+0x369/0x4f0
> [   86.071137]  [<ffffffff8113dde8>] ? handle_mm_fault+0x1f8/0x350
> [   86.071140]  [<ffffffff81143cb8>] do_mmap_pgoff+0x348/0x360
> [   86.071143]  [<ffffffff81143d96>] sys_mmap_pgoff+0xc6/0x230
> [   86.071148]  [<ffffffff81017b12>] sys_mmap+0x22/0x30
> [   86.071153]  [<ffffffff816643c2>] system_call_fastpath+0x16/0x1b
> [   86.071155] ---[ end trace ea7792ae1c43717f ]---
> 
> The third attempt gives me the same error in the module :
> [  105.337927] WARNING: at /build/buildd/linux-
> 3.2.0/arch/x86/xen/p2m.c:696 m2p_add_override+0x7b/0x3c0()
> [  105.337929] m2p_add_override: pfn f78bba24c not mapped
> [  105.337931] Modules linked in: shm13(O) lp parport
> [  105.337937] Pid: 1201, comm: fill Tainted: G           O 3.2.0-34-
> generic #53-Ubuntu
> [  105.337939] Call Trace:
> [  105.337946]  [<ffffffff81066f0f>] warn_slowpath_common+0x7f/0xc0
> [  105.337949]  [<ffffffff81067006>] warn_slowpath_fmt+0x46/0x50
> [  105.337952]  [<ffffffff8100b62b>] m2p_add_override+0x7b/0x3c0
> [  105.337958]  [<ffffffff8164328c>] ? printk+0x51/0x53
> [  105.337962]  [<ffffffffa0019116>] mmap_mmap+0xd6/0x128 [shm13]
> [  105.337965]  [<ffffffff810064fe>] ? xen_pmd_val+0xe/0x10
> [  105.337970]  [<ffffffff811437e9>] mmap_region+0x369/0x4f0
> [  105.337973]  [<ffffffff8113dde8>] ? handle_mm_fault+0x1f8/0x350
> [  105.337976]  [<ffffffff81143cb8>] do_mmap_pgoff+0x348/0x360
> [  105.337979]  [<ffffffff81143d96>] sys_mmap_pgoff+0xc6/0x230
> [  105.337984]  [<ffffffff81017b12>] sys_mmap+0x22/0x30
> [  105.337989]  [<ffffffff816643c2>] system_call_fastpath+0x16/0x1b
> [  105.337991] ---[ end trace 33b54c96a0c2933b ]---
> 
> The fourth attempt results in an error in the function called by the
> module :
> [   96.621242] Error in remap_vmalloc_range
> 
> I don't really know what to do to make it works, but I know than such a
> communication channel is possible as people have already done it before.
> 
> Does someone know what is my mistake and how to correct it please ?
> 
> Best regards,
> 
> Sébastien Frémal

It sounds like you are trying to do something like what libvchan already
does. You should take a look at that library - it is in the xen tree
under tools/libvchan

Ross

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.