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

[Xen-changelog] [xen-unstable] stubdom: make use of PVFB resize event



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1208337668 -3600
# Node ID 06242949ff569930bdb13f627fbb54ea13d8af08
# Parent  774e38a40d012d3cc92715237d6932bcf01bbd39
stubdom: make use of PVFB resize event
which with the offset support also permits to expose the VGA vram and
non-shared vram throught PVFB at the same time, switching between both
as appropriate.

Signed-off-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxxx>
---
 extras/mini-os/fbfront.c         |   98 ++++++++++++++----------
 extras/mini-os/include/fbfront.h |    3 
 extras/mini-os/kernel.c          |   15 +++
 tools/ioemu/hw/cirrus_vga.c      |    4 +
 tools/ioemu/hw/vga.c             |    6 -
 tools/ioemu/hw/xenfb.c           |  153 +++++++++++++++++++++++++++------------
 tools/ioemu/vl.h                 |    1 
 7 files changed, 186 insertions(+), 94 deletions(-)

diff -r 774e38a40d01 -r 06242949ff56 extras/mini-os/fbfront.c
--- a/extras/mini-os/fbfront.c  Wed Apr 16 10:07:49 2008 +0100
+++ b/extras/mini-os/fbfront.c  Wed Apr 16 10:21:08 2008 +0100
@@ -243,12 +243,12 @@ struct fbfront_dev {
     char *backend;
     int request_update;
 
-    char *data;
     int width;
     int height;
     int depth;
-    int line_length;
+    int stride;
     int mem_length;
+    int offset;
 };
 
 void fbfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
@@ -256,7 +256,7 @@ void fbfront_handler(evtchn_port_t port,
     wake_up(&fbfront_queue);
 }
 
-struct fbfront_dev *init_fbfront(char *nodename, void *data, int width, int 
height, int depth, int line_length, int mem_length)
+struct fbfront_dev *init_fbfront(char *nodename, unsigned long *mfns, int 
width, int height, int depth, int stride, int n)
 {
     xenbus_transaction_t xbt;
     char* err;
@@ -289,24 +289,17 @@ struct fbfront_dev *init_fbfront(char *n
     dev->width = s->width = width;
     dev->height = s->height = height;
     dev->depth = s->depth = depth;
-    dev->line_length = s->line_length = line_length;
-    dev->mem_length = s->mem_length = mem_length;
-
-    ASSERT(!((unsigned long)data & ~PAGE_MASK));
-    dev->data = data;
+    dev->stride = s->line_length = stride;
+    dev->mem_length = s->mem_length = n * PAGE_SIZE;
+    dev->offset = 0;
 
     const int max_pd = sizeof(s->pd) / sizeof(s->pd[0]);
     unsigned long mapped = 0;
 
-    for (i = 0; mapped < mem_length && i < max_pd; i++) {
+    for (i = 0; mapped < n && i < max_pd; i++) {
         unsigned long *pd = (unsigned long *) alloc_page();
-        for (j = 0; mapped < mem_length && j < PAGE_SIZE / sizeof(unsigned 
long); j++) {
-            /* Trigger CoW */
-            * ((char *)data + mapped) = 0;
-            barrier();
-            pd[j] = virtual_to_mfn((unsigned long) data + mapped);
-            mapped += PAGE_SIZE;
-        }
+        for (j = 0; mapped < n && j < PAGE_SIZE / sizeof(unsigned long); j++)
+            pd[j] = mfns[mapped++];
         for ( ; j < PAGE_SIZE / sizeof(unsigned long); j++)
             pd[j] = 0;
         s->pd[i] = virt_to_mfn(pd);
@@ -395,31 +388,11 @@ done:
     return dev;
 }
 
-void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int 
height)
+static void fbfront_out_event(struct fbfront_dev *dev, union xenfb_out_event 
*event)
 {
     struct xenfb_page *page = dev->page;
     uint32_t prod;
     DEFINE_WAIT(w);
-
-    if (dev->request_update <= 0)
-        return;
-
-    if (x < 0) {
-        width += x;
-        x = 0;
-    }
-    if (x + width > dev->width)
-        width = dev->width - x;
-
-    if (y < 0) {
-        height += y;
-        y = 0;
-    }
-    if (y + height > dev->height)
-        height = dev->height - y;
-
-    if (width <= 0 || height <= 0)
-        return;
 
     add_waiter(w, fbfront_queue);
     while (page->out_prod - page->out_cons == XENFB_OUT_RING_LEN)
@@ -428,14 +401,55 @@ void fbfront_update(struct fbfront_dev *
 
     prod = page->out_prod;
     mb(); /* ensure ring space available */
-    XENFB_OUT_RING_REF(page, prod).type = XENFB_TYPE_UPDATE;
-    XENFB_OUT_RING_REF(page, prod).update.x = x;
-    XENFB_OUT_RING_REF(page, prod).update.y = y;
-    XENFB_OUT_RING_REF(page, prod).update.width = width;
-    XENFB_OUT_RING_REF(page, prod).update.height = height;
+    XENFB_OUT_RING_REF(page, prod) = *event;
     wmb(); /* ensure ring contents visible */
     page->out_prod = prod + 1;
     notify_remote_via_evtchn(dev->evtchn);
+}
+
+void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int 
height)
+{
+    struct xenfb_update update;
+
+    if (dev->request_update <= 0)
+        return;
+
+    if (x < 0) {
+        width += x;
+        x = 0;
+    }
+    if (x + width > dev->width)
+        width = dev->width - x;
+
+    if (y < 0) {
+        height += y;
+        y = 0;
+    }
+    if (y + height > dev->height)
+        height = dev->height - y;
+
+    if (width <= 0 || height <= 0)
+        return;
+
+    update.type = XENFB_TYPE_UPDATE;
+    update.x = x;
+    update.y = y;
+    update.width = width;
+    update.height = height;
+    fbfront_out_event(dev, (union xenfb_out_event *) &update);
+}
+
+void fbfront_resize(struct fbfront_dev *dev, int width, int height, int 
stride, int depth, int offset)
+{
+    struct xenfb_resize resize;
+
+    resize.type = XENFB_TYPE_RESIZE;
+    dev->width  = resize.width = width;
+    dev->height = resize.height = height;
+    dev->stride = resize.stride = stride;
+    dev->depth  = resize.depth = depth;
+    dev->offset = resize.offset = offset;
+    fbfront_out_event(dev, (union xenfb_out_event *) &resize);
 }
 
 void shutdown_fbfront(struct fbfront_dev *dev)
diff -r 774e38a40d01 -r 06242949ff56 extras/mini-os/include/fbfront.h
--- a/extras/mini-os/include/fbfront.h  Wed Apr 16 10:07:49 2008 +0100
+++ b/extras/mini-os/include/fbfront.h  Wed Apr 16 10:21:08 2008 +0100
@@ -31,11 +31,12 @@ void shutdown_kbdfront(struct kbdfront_d
 void shutdown_kbdfront(struct kbdfront_dev *dev);
 
 
-struct fbfront_dev *init_fbfront(char *nodename, void *data, int width, int 
height, int depth, int line_length, int mem_length);
+struct fbfront_dev *init_fbfront(char *nodename, unsigned long *mfns, int 
width, int height, int depth, int stride, int n);
 #ifdef HAVE_LIBC
 int fbfront_open(struct fbfront_dev *dev);
 #endif
 
 void fbfront_update(struct fbfront_dev *dev, int x, int y, int width, int 
height);
+void fbfront_resize(struct fbfront_dev *dev, int width, int height, int 
stride, int depth, int offset);
 
 void shutdown_fbfront(struct fbfront_dev *dev);
diff -r 774e38a40d01 -r 06242949ff56 extras/mini-os/kernel.c
--- a/extras/mini-os/kernel.c   Wed Apr 16 10:07:49 2008 +0100
+++ b/extras/mini-os/kernel.c   Wed Apr 16 10:21:08 2008 +0100
@@ -297,9 +297,20 @@ static void fbfront_thread(void *p)
 {
     size_t line_length = WIDTH * (DEPTH / 8);
     size_t memsize = HEIGHT * line_length;
-
+    unsigned long *mfns;
+    int i, n = (memsize + PAGE_SIZE-1) / PAGE_SIZE;
+
+    memsize = n * PAGE_SIZE;
     fb = _xmalloc(memsize, PAGE_SIZE);
-    fb_dev = init_fbfront(NULL, fb, WIDTH, HEIGHT, DEPTH, line_length, 
memsize);
+    mfns = xmalloc_array(unsigned long, n);
+    for (i = 0; i < n; i++) {
+        /* trigger CoW */
+        ((char *) fb) [i * PAGE_SIZE] = 0;
+        barrier();
+        mfns[i] = virtual_to_mfn((char *) fb + i * PAGE_SIZE);
+    }
+    fb_dev = init_fbfront(NULL, mfns, WIDTH, HEIGHT, DEPTH, line_length, n);
+    xfree(mfns);
     if (!fb_dev) {
         xfree(fb);
         return;
diff -r 774e38a40d01 -r 06242949ff56 tools/ioemu/hw/cirrus_vga.c
--- a/tools/ioemu/hw/cirrus_vga.c       Wed Apr 16 10:07:49 2008 +0100
+++ b/tools/ioemu/hw/cirrus_vga.c       Wed Apr 16 10:21:08 2008 +0100
@@ -2595,6 +2595,10 @@ static void *set_vram_mapping(unsigned l
 
     memset(vram_pointer, 0, nr_extents * TARGET_PAGE_SIZE);
 
+#ifdef CONFIG_STUBDOM
+    xenfb_pv_display_start(vram_pointer);
+#endif
+
     free(extent_start);
 
     return vram_pointer;
diff -r 774e38a40d01 -r 06242949ff56 tools/ioemu/hw/vga.c
--- a/tools/ioemu/hw/vga.c      Wed Apr 16 10:07:49 2008 +0100
+++ b/tools/ioemu/hw/vga.c      Wed Apr 16 10:21:08 2008 +0100
@@ -2067,8 +2067,8 @@ void vga_common_init(VGAState *s, Displa
                                  & ~(TARGET_PAGE_SIZE - 1));
 
     /* Video RAM must be 128-bit aligned for SSE optimizations later */
-    s->vram_alloc = qemu_malloc(vga_ram_size + 15);
-    s->vram_ptr = (uint8_t *)((long)(s->vram_alloc + 15) & ~15L);
+    /* and page-aligned for PVFB memory sharing */
+    s->vram_ptr = s->vram_alloc = qemu_memalign(TARGET_PAGE_SIZE, 
vga_ram_size);
 
     s->vram_offset = vga_ram_offset;
     s->vram_size = vga_ram_size;
@@ -2210,7 +2210,7 @@ void *vga_update_vram(VGAState *s, void 
     }
 
     if (!vga_ram_base) {
-        vga_ram_base = qemu_malloc(vga_ram_size + TARGET_PAGE_SIZE + 1);
+        vga_ram_base = qemu_memalign(TARGET_PAGE_SIZE, vga_ram_size + 
TARGET_PAGE_SIZE + 1);
         if (!vga_ram_base) {
             fprintf(stderr, "reallocate error\n");
             return NULL;
diff -r 774e38a40d01 -r 06242949ff56 tools/ioemu/hw/xenfb.c
--- a/tools/ioemu/hw/xenfb.c    Wed Apr 16 10:07:49 2008 +0100
+++ b/tools/ioemu/hw/xenfb.c    Wed Apr 16 10:21:08 2008 +0100
@@ -1235,14 +1235,10 @@ static struct semaphore kbd_sem = __SEMA
 static struct semaphore kbd_sem = __SEMAPHORE_INITIALIZER(kbd_sem, 0);
 static struct kbdfront_dev *kbd_dev;
 static char *kbd_path, *fb_path;
+static void *vga_vram, *nonshared_vram;
+static DisplayState *xenfb_ds;
 
 static unsigned char linux2scancode[KEY_MAX + 1];
-
-#define WIDTH 1024
-#define HEIGHT 768
-#define DEPTH 32
-#define LINESIZE (1280 * (DEPTH / 8))
-#define MEMSIZE (LINESIZE * HEIGHT)
 
 int xenfb_connect_vkbd(const char *path)
 {
@@ -1256,33 +1252,73 @@ int xenfb_connect_vfb(const char *path)
     return 0;
 }
 
-static void xenfb_pv_update(DisplayState *s, int x, int y, int w, int h)
-{
-    struct fbfront_dev *fb_dev = s->opaque;
+static void xenfb_pv_update(DisplayState *ds, int x, int y, int w, int h)
+{
+    struct fbfront_dev *fb_dev = ds->opaque;
+    if (!fb_dev)
+        return;
     fbfront_update(fb_dev, x, y, w, h);
 }
 
-static void xenfb_pv_resize(DisplayState *s, int w, int h, int linesize)
-{
-    struct fbfront_dev *fb_dev = s->opaque;
-    fprintf(stderr,"resize to %dx%d required\n", w, h);
-    s->width = w;
-    s->height = h;
-    /* TODO: send resize event if supported */
-    memset(s->data, 0, MEMSIZE);
-    fbfront_update(fb_dev, 0, 0, WIDTH, HEIGHT);
+static void xenfb_pv_resize(DisplayState *ds, int w, int h, int linesize)
+{
+    struct fbfront_dev *fb_dev = ds->opaque;
+    fprintf(stderr,"resize to %dx%d, %d required\n", w, h, linesize);
+    ds->width = w;
+    ds->height = h;
+    if (!linesize)
+        ds->shared_buf = 0;
+    if (!ds->shared_buf)
+        linesize = w * 4;
+    ds->linesize = linesize;
+    if (!fb_dev)
+        return;
+    if (ds->shared_buf) {
+        ds->data = NULL;
+    } else {
+        ds->data = nonshared_vram;
+        fbfront_resize(fb_dev, w, h, linesize, ds->depth, VGA_RAM_SIZE);
+    }
 }
 
 static void xenfb_pv_colourdepth(DisplayState *ds, int depth)
 {
-    /* TODO: send redepth event if supported */
+    struct fbfront_dev *fb_dev = ds->opaque;
     static int lastdepth = -1;
+    if (!depth) {
+        ds->shared_buf = 0;
+        ds->depth = 32;
+    } else {
+        ds->shared_buf = 1;
+        ds->depth = depth;
+    }
     if (depth != lastdepth) {
         fprintf(stderr,"redepth to %d required\n", depth);
         lastdepth = depth;
+    } else return;
+    if (!fb_dev)
+        return;
+    if (ds->shared_buf) {
+        ds->data = NULL;
+    } else {
+        ds->data = nonshared_vram;
+        fbfront_resize(fb_dev, ds->width, ds->height, ds->linesize, ds->depth, 
VGA_RAM_SIZE);
     }
-    /* We can't redepth for now */
-    ds->depth = DEPTH;
+}
+
+static void xenfb_pv_setdata(DisplayState *ds, void *pixels)
+{
+    struct fbfront_dev *fb_dev = ds->opaque;
+    int offset = pixels - vga_vram;
+    ds->data = pixels;
+    if (!fb_dev)
+        return;
+    fbfront_resize(fb_dev, ds->width, ds->height, ds->linesize, ds->depth, 
offset);
+}
+
+static void xenfb_pv_refresh(DisplayState *ds)
+{
+    vga_hw_update();
 }
 
 static void xenfb_kbd_handler(void *opaque)
@@ -1373,13 +1409,6 @@ static void xenfb_kbd_handler(void *opaq
     }
 }
 
-static void xenfb_pv_refresh(DisplayState *ds)
-{
-    /* always request negociation */
-    ds->depth = -1;
-    vga_hw_update();
-}
-
 static void kbdfront_thread(void *p)
 {
     int scancode, keycode;
@@ -1399,40 +1428,72 @@ static void kbdfront_thread(void *p)
 
 int xenfb_pv_display_init(DisplayState *ds)
 {
-    void *data;
+    if (!fb_path || !kbd_path)
+        return -1;
+
+    create_thread("kbdfront", kbdfront_thread, (void*) kbd_path);
+
+    xenfb_ds = ds;
+
+    ds->data = nonshared_vram = qemu_memalign(PAGE_SIZE, VGA_RAM_SIZE);
+    memset(ds->data, 0, VGA_RAM_SIZE);
+    ds->depth = 32;
+    ds->bgr = 0;
+    ds->width = 640;
+    ds->height = 400;
+    ds->linesize = 640 * 4;
+    ds->dpy_update = xenfb_pv_update;
+    ds->dpy_resize = xenfb_pv_resize;
+    ds->dpy_colourdepth = xenfb_pv_colourdepth;
+    ds->dpy_setdata = xenfb_pv_setdata;
+    ds->dpy_refresh = xenfb_pv_refresh;
+    return 0;
+}
+
+int xenfb_pv_display_start(void *data)
+{
+    DisplayState *ds = xenfb_ds;
     struct fbfront_dev *fb_dev;
     int kbd_fd;
+    int offset = 0;
+    unsigned long *mfns;
+    int n = VGA_RAM_SIZE / PAGE_SIZE;
+    int i;
 
     if (!fb_path || !kbd_path)
-        return -1;
-
-    create_thread("kbdfront", kbdfront_thread, (void*) kbd_path);
-
-    data = qemu_memalign(PAGE_SIZE, VGA_RAM_SIZE);
-    fb_dev = init_fbfront(fb_path, data, WIDTH, HEIGHT, DEPTH, LINESIZE, 
MEMSIZE);
+        return 0;
+
+    vga_vram = data;
+    mfns = malloc(2 * n * sizeof(*mfns));
+    for (i = 0; i < n; i++)
+        mfns[i] = virtual_to_mfn(vga_vram + i * PAGE_SIZE);
+    for (i = 0; i < n; i++)
+        mfns[n + i] = virtual_to_mfn(nonshared_vram + i * PAGE_SIZE);
+
+    fb_dev = init_fbfront(fb_path, mfns, ds->width, ds->height, ds->depth, 
ds->linesize, 2 * n);
+    free(mfns);
     if (!fb_dev) {
         fprintf(stderr,"can't open frame buffer\n");
         exit(1);
     }
     free(fb_path);
 
+    if (ds->shared_buf) {
+        offset = (void*) ds->data - vga_vram;
+    } else {
+        offset = VGA_RAM_SIZE;
+        ds->data = nonshared_vram;
+    }
+    if (offset)
+        fbfront_resize(fb_dev, ds->width, ds->height, ds->linesize, ds->depth, 
offset);
+
     down(&kbd_sem);
     free(kbd_path);
 
     kbd_fd = kbdfront_open(kbd_dev);
     qemu_set_fd_handler(kbd_fd, xenfb_kbd_handler, NULL, ds);
 
-    ds->data = data;
-    ds->linesize = LINESIZE;
-    ds->depth = DEPTH;
-    ds->bgr = 0;
-    ds->width = WIDTH;
-    ds->height = HEIGHT;
-    ds->dpy_update = xenfb_pv_update;
-    ds->dpy_resize = xenfb_pv_resize;
-    ds->dpy_colourdepth = xenfb_pv_colourdepth;
-    ds->dpy_refresh = xenfb_pv_refresh;
-    ds->opaque = fb_dev;
+    xenfb_ds->opaque = fb_dev;
     return 0;
 }
 #endif
diff -r 774e38a40d01 -r 06242949ff56 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Wed Apr 16 10:07:49 2008 +0100
+++ b/tools/ioemu/vl.h  Wed Apr 16 10:21:08 2008 +0100
@@ -1545,6 +1545,7 @@ char *xenstore_vm_read(int domid, char *
 
 /* xenfb.c */
 int xenfb_pv_display_init(DisplayState *ds);
+int xenfb_pv_display_start(void *vram_start);
 int xenfb_connect_vkbd(const char *path);
 int xenfb_connect_vfb(const char *path);
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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