[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2/3] xen-fbfront: Use grant references when requested
From: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx> The current version of the Xen framebuffer API passes MFNs directly to the backend driver, which requires the backend to have full access to this domain's memory. Add a parameter in xenbus to request the use of grant entries instead, which are slightly slower to map but provide inter-domain isolation. Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx> --- drivers/video/xen-fbfront.c | 73 +++++++++++++++++++++++++++++++++--------- 1 files changed, 57 insertions(+), 16 deletions(-) diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c index 341c919..bb99bbd 100644 --- a/drivers/video/xen-fbfront.c +++ b/drivers/video/xen-fbfront.c @@ -11,13 +11,6 @@ * more details. */ -/* - * TODO: - * - * Switch to grant tables when they become capable of dealing with the - * frame buffer. - */ - #include <linux/console.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -32,6 +25,8 @@ #include <xen/xen.h> #include <xen/events.h> #include <xen/page.h> +#include <xen/grant_table.h> +#include <xen/interface/grant_table.h> #include <xen/interface/io/fbif.h> #include <xen/interface/io/protocols.h> #include <xen/xenbus.h> @@ -46,6 +41,7 @@ struct xenfb_info { int irq; struct xenfb_page *page; unsigned long *mfns; + int page_gref; int update_wanted; /* XENFB_TYPE_UPDATE wanted */ int feature_resize; /* XENFB_TYPE_RESIZE ok */ struct xenfb_resize resize; /* protected by resize_lock */ @@ -65,7 +61,7 @@ MODULE_PARM_DESC(video, static void xenfb_make_preferred_console(void); static int xenfb_remove(struct xenbus_device *); -static void xenfb_init_shared_page(struct xenfb_info *, struct fb_info *); +static void xenfb_init_shared_page(struct xenbus_device *, struct xenfb_info *, struct fb_info *); static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *); static void xenfb_disconnect_backend(struct xenfb_info *); @@ -474,7 +470,7 @@ static int __devinit xenfb_probe(struct xenbus_device *dev, fb_info->fbdefio = &xenfb_defio; fb_deferred_io_init(fb_info); - xenfb_init_shared_page(info, fb_info); + xenfb_init_shared_page(dev, info, fb_info); ret = xenfb_connect_backend(dev, info); if (ret < 0) @@ -528,7 +524,7 @@ static int xenfb_resume(struct xenbus_device *dev) struct xenfb_info *info = dev_get_drvdata(&dev->dev); xenfb_disconnect_backend(info); - xenfb_init_shared_page(info, info->fb_info); + xenfb_init_shared_page(dev, info, info->fb_info); return xenfb_connect_backend(dev, info); } @@ -556,17 +552,58 @@ static unsigned long vmalloc_to_mfn(void *address) return pfn_to_mfn(vmalloc_to_pfn(address)); } -static void xenfb_init_shared_page(struct xenfb_info *info, +static void xenfb_init_shared_page(struct xenbus_device *dev, + struct xenfb_info *info, struct fb_info *fb_info) { - int i; int epd = PAGE_SIZE / sizeof(info->mfns[0]); + int be_id = dev->otherend_id; + int i, ref; + unsigned long mfn; + grant_ref_t gref_head; + int allpages = info->nr_pages + ((info->nr_pages + epd - 1) / epd) + 1; + + int grants = 0; + xenbus_scanf(XBT_NIL, dev->otherend, "use-grants", "%d", &grants); + + if (grants) { + int err = gnttab_alloc_grant_references(allpages, &gref_head); + if (err < 0) { + xenbus_dev_fatal(dev, err, "fbdev grant refs"); + info->page_gref = -ENOSPC; + } else { + ref = gnttab_claim_grant_reference(&gref_head); + mfn = virt_to_mfn(info->page); + BUG_ON(ref == -ENOSPC); + gnttab_grant_foreign_access_ref(ref, be_id, mfn, 0); + info->page_gref = ref; + } + } else + info->page_gref = -ENOENT; for (i = 0; i < info->nr_pages; i++) - info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE); + { + mfn = vmalloc_to_mfn(info->fb + i * PAGE_SIZE); + if (grants) { + ref = gnttab_claim_grant_reference(&gref_head); + BUG_ON(ref == -ENOSPC); + gnttab_grant_foreign_access_ref(ref, be_id, mfn, 1); + info->mfns[i] = ref; + } else + info->mfns[i] = mfn; + } for (i = 0; i * epd < info->nr_pages; i++) - info->page->pd[i] = vmalloc_to_mfn(&info->mfns[i * epd]); + { + mfn = vmalloc_to_mfn(&info->mfns[i * epd]); + if (grants) { + ref = gnttab_claim_grant_reference(&gref_head); + BUG_ON(ref == -ENOSPC); + gnttab_grant_foreign_access_ref(ref, be_id, mfn, 1); + info->page->pd[i] = ref; + } else + info->page->pd[i] = mfn; + } info->page->width = fb_info->var.xres; info->page->height = fb_info->var.yres; @@ -601,8 +638,12 @@ static int xenfb_connect_backend(struct xenbus_device *dev, xenbus_dev_fatal(dev, ret, "starting transaction"); return ret; } - ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", - virt_to_mfn(info->page)); + if (info->page_gref < 0) + ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", + virt_to_mfn(info->page)); + else + ret = xenbus_printf(xbt, dev->nodename, "page-gref", "%u", + info->page_gref); if (ret) goto error_xenbus; ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", -- 1.7.3.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |