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

[Xen-devel] Shared memory between a process in dom0 and a process in domU


  • To: "xen-devel@xxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxx>
  • From: Sébastien FREMAL [530784] <Sebastien.FREMAL@xxxxxxxxxxx>
  • Date: Wed, 24 Jul 2013 14:46:54 +0000
  • Accept-language: fr-BE, en-US
  • Delivery-date: Thu, 25 Jul 2013 08:05:15 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xen.org>
  • Thread-index: Ac6IfKNvRYYibhtPQH+hJvC2D3y9Nw==
  • Thread-topic: Shared memory between a process in dom0 and a process in domU

Hello,

I'm trying to share memory pages between a process executing in dom0 and a process executing in a domU. I work with xen 4.3 and linux 3.2 (it's necessary due to a compatibility issue). I succeeded in accessing pages from a process in dom0, but I'm encountering problems to access them from a domU. I tried two methods :
1) I allocate a vm area in which I put the pages identified by their grant references. This step works, but I don't find how to retrieve the pages in the mmap function to map them into user space. Here is the corresponding code (it's based on the xensocket code) :

if (!(x->buffer_area = alloc_vm_area(buffer_num_pages * PAGE_SIZE, NULL))) {
    DPRINTK("error: cannot allocate %d buffer pages\n", buffer_num_pages);
    goto err_unmap;
}

//x->buffer_addr is a pointer used to access more easily to x->buffer_area->addr
x->buffer_addr = (unsigned long)x->buffer_area->addr;

//we retrieve the first gref
grefp = &d->buffer_first_gref;
for (i = 0; i < buffer_num_pages; i++) {

    memset(&op, 0, sizeof(op));
    op.host_addr = x->buffer_addr + i * PAGE_SIZE;
    op.flags = GNTMAP_host_map;
    op.ref = *grefp;
    op.dom = x->otherend_id;

    rc = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
    if (rc == -ENOSYS) {
        goto err_unmap;
    }

    if (op.status) {
           DPRINTK("error: grant table mapping failed\n");
        goto err_unmap;
    }

    x->buffer_handles[i] = op.handle;
    grefp = (int *)(x->buffer_addr + i * PAGE_SIZE);
}

Now, the grefs are mapped and the data they contain is accessible from the module. I instantiated a mmap function to access them from a user process :

//I first tried to get the PFN of the page to map it with remap_pfn_range, but it doesn't work as vmalloc_to_pfn returns 0 and not the PFN
unsigned long pfn = vmalloc_to_pfn((void *)(x->buffer_addr+recv_offset*PAGE_SIZE));
if(pfn_valid(pfn)){
    printk(KERN_INFO "PFN is valide\n");
}

//I studied how gntdev worked and I realised it uses vm_insert_page, I then tried to retrieve the struct page instead of the PFN
struct page * shPage = vmalloc_to_page((void *)(x->buffer_addr+recv_offset*PAGE_SIZE));
if(shPage == NULL)
    printk(KERN_INFO "Page not found\n");

vma->vm_flags |= VM_RESERVED;

//This function fails with the error code -22 (invalid value)
int err = vm_insert_page(vma, vma->vm_start, shPage);
if (err)
    printk(KERN_INFO "Error while inserting a page\n");
else
    printk(KERN_INFO "Page inserted !!");

I don't understand why this method fails. vmalloc_to_page returns a struct page *, but the function page_count (called by vm_insert_page) fails when called for this page. Is there a subtlety specific to Xen to allow this operation to succeed ?

2) As the first method didn't succeed, I used what was done in gntdev (using pages instead of vm area to "mount" granted references) :

if((x->pages = kcalloc(buffer_num_pages, sizeof(x->pages[0]), GFP_KERNEL))==NULL){
    printk(KERN_INFO "No space left on device\n");
    goto err;
}

if(alloc_xenballooned_pages(buffer_num_pages, x->pages, false)){
    printk(KERN_INFO "No place anymore for ballooned pages");
    goto err;
}

//I did the test for 1 page only
for (i = 0; i < 1; i++) {
    memset(&op, 0, sizeof(op));
    //I succeed here to get the PFN and the kaddr corresponding with the page
    unsigned long pfn = page_to_pfn(x->pages[i]);
    gnttab_set_map_op(&op, (unsigned long) pfn_to_kaddr(pfn), GNTMAP_host_map, *grefp, x->otherend_id);
    rc = gnttab_map_refs(&op,NULL,x->pages+i, 1);
    if(rc){
        printk(KERN_INFO "Error while mapping ref\n");
        goto err_unmap;
    }
    else if (op.status) {
        DPRINTK("error: grant table mapping failed\n");
        goto err_unmap;
    }
    else
        printk(KERN_INFO "Page mapped\n");
}

I don't really know what happens here, but when gnttab_map_refs is called, the calling domU is rebooted and its ID is changed (from 1 to 2 i.e.).

Can someone please tell me what's wrong in my code ? I just have to get the right page in the first method to make it work.

Thank you.

Best regards,

Sebastien Fremal
_______________________________________________
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®.