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
|