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

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


  • To: "xen-devel@xxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxx>
  • From: Sébastien FREMAL [530784] <Sebastien.FREMAL@xxxxxxxxxxx>
  • Date: Wed, 27 Feb 2013 14:57:02 +0000
  • Accept-language: fr-BE, en-US
  • Delivery-date: Wed, 27 Feb 2013 15:00:40 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xen.org>
  • Thread-index: Ac4U+rNhA2odNNBcQhaaDbwWLNFuig==
  • Thread-topic: 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
_______________________________________________
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®.