Index: xen-3.2-testing/tools/ioemu/hw/xenfb.c =================================================================== --- xen-3.2-testing.orig/tools/ioemu/hw/xenfb.c +++ xen-3.2-testing/tools/ioemu/hw/xenfb.c @@ -510,6 +510,12 @@ static void xenfb_on_fb_event(struct xen } xenfb_guest_copy(xenfb, x, y, w, h); break; + case XENFB_TYPE_RESIZE: + xenfb->width = event->resize.width; + xenfb->height = event->resize.height; + xenfb->row_stride = event->resize.stride; + dpy_resize(xenfb->ds, xenfb->width, xenfb->height); + break; } } mb(); /* ensure we're done with ring contents */ @@ -672,6 +678,7 @@ static void xenfb_dispatch_store(void *o static int xenfb_read_frontend_fb_config(struct xenfb *xenfb) { struct xenfb_page *fb_page; int val; + int videoram; if (xenfb_xs_scanf1(xenfb->xsh, xenfb->fb.otherend, "feature-update", "%d", &val) < 0) @@ -686,19 +693,34 @@ static int xenfb_read_frontend_fb_config xenfb->protocol[0] = '\0'; xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "request-update", "1"); - /* TODO check for permitted ranges */ + if (xenfb_xs_scanf1(xenfb->xsh, xenfb->fb.nodename, "videoram", "%d", &videoram) < 0) + videoram = 0; + videoram = videoram * 1024 * 1024; + fb_page = xenfb->fb.page; xenfb->depth = fb_page->depth; xenfb->width = fb_page->width; xenfb->height = fb_page->height; - /* TODO check for consistency with the above */ xenfb->fb_len = fb_page->mem_length; xenfb->row_stride = fb_page->line_length; + /* Protect against hostile frontend, limit fb_len to configured */ + if (videoram && xenfb->fb_len > videoram) { + xenfb->fb_len = videoram; + if (xenfb->row_stride * xenfb->height > xenfb->fb_len) + xenfb->height = xenfb->fb_len / xenfb->row_stride; + } fprintf(stderr, "Framebuffer depth %d width %d height %d line %d\n", fb_page->depth, fb_page->width, fb_page->height, fb_page->line_length); if (xenfb_map_fb(xenfb, xenfb->fb.otherend_id) < 0) return -1; + /* Indicate we have the frame buffer resize feature */ + xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "feature-resize", "1"); + + /* Tell kbd the screen res */ + xenfb_xs_printf(xenfb->xsh, xenfb->kbd.nodename, "width", "%d", xenfb->width); + xenfb_xs_printf(xenfb->xsh, xenfb->kbd.nodename, "height", "%d", xenfb->height); + if (xenfb_switch_state(&xenfb->fb, XenbusStateConnected)) return -1; if (xenfb_switch_state(&xenfb->kbd, XenbusStateConnected)) Index: xen-3.2-testing/xen/include/public/io/fbif.h =================================================================== --- xen-3.2-testing.orig/xen/include/public/io/fbif.h +++ xen-3.2-testing/xen/include/public/io/fbif.h @@ -50,12 +50,28 @@ struct xenfb_update int32_t height; /* rect height */ }; +/* + * Framebuffer resize notification event + * Capable backend sets feature-resize in xenstore. + */ +#define XENFB_TYPE_RESIZE 3 + +struct xenfb_resize +{ + uint8_t type; /* XENFB_TYPE_RESIZE */ + int32_t width; /* width in pixels */ + int32_t height; /* height in pixels */ + int32_t stride; /* stride in bytes */ + int32_t depth; /* depth in bits */ +}; + #define XENFB_OUT_EVENT_SIZE 40 union xenfb_out_event { uint8_t type; struct xenfb_update update; + struct xenfb_resize resize; char pad[XENFB_OUT_EVENT_SIZE]; }; @@ -109,15 +125,17 @@ struct xenfb_page * Each directory page holds PAGE_SIZE / sizeof(*pd) * framebuffer pages, and can thus map up to PAGE_SIZE * * PAGE_SIZE / sizeof(*pd) bytes. With PAGE_SIZE == 4096 and - * sizeof(unsigned long) == 4, that's 4 Megs. Two directory - * pages should be enough for a while. + * sizeof(unsigned long) == 4/8, that's 4 Megs 32 bit and 2 Megs + * 64 bit. 256 directories give enough room for a 512 Meg + * framebuffer with a max resolution of 12,800x10,240. Should + * be enough for a while with room leftover for expansion. */ - unsigned long pd[2]; + unsigned long pd[256]; }; /* - * Wart: xenkbd needs to know resolution. Put it here until a better - * solution is found, but don't leak it to the backend. + * Wart: xenkbd needs to know default resolution. Put it here until a + * better solution is found, but don't leak it to the backend. */ #ifdef __KERNEL__ #define XENFB_WIDTH 800 Index: xen-3.2-testing/tools/python/xen/xend/server/vfbif.py =================================================================== --- xen-3.2-testing.orig/tools/python/xen/xend/server/vfbif.py +++ xen-3.2-testing/tools/python/xen/xend/server/vfbif.py @@ -6,7 +6,7 @@ import xen.xend import os CONFIG_ENTRIES = ['type', 'vncdisplay', 'vnclisten', 'vncpasswd', 'vncunused', - 'display', 'xauthority', 'keymap', + 'videoram', 'display', 'xauthority', 'keymap', 'uuid', 'location', 'protocol'] class VfbifController(DevController): Index: xen-3.2-testing/tools/python/xen/xm/create.py =================================================================== --- xen-3.2-testing.orig/tools/python/xen/xm/create.py +++ xen-3.2-testing/tools/python/xen/xm/create.py @@ -496,6 +496,10 @@ gopts.var('vncunused', val='', use="""Try to find an unused port for the VNC server. Only valid when vnc=1.""") +gopts.var('videoram', val='', + fn=set_value, default=None, + use="""Amount of videoram PV guest can allocate for frame buffer.""") + gopts.var('sdl', val='', fn=set_value, default=None, use="""Should the device model use SDL?""") @@ -631,7 +635,7 @@ def configure_vfbs(config_devs, vals): d['type'] = 'sdl' for (k,v) in d.iteritems(): if not k in [ 'vnclisten', 'vncunused', 'vncdisplay', 'display', - 'xauthority', 'type', 'vncpasswd' ]: + 'videoram', 'xauthority', 'type', 'vncpasswd' ]: err("configuration option %s unknown to vfbs" % k) config.append([k,v]) if not d.has_key("keymap"):