>>> On Thu, Jan 10, 2008 at 3:18 AM, in message
<87ejcqhtku.fsf@xxxxxxxxxxxxxxxxx>, Markus Armbruster <armbru@xxxxxxxxxx>
wrote:
> "Pat Campbell" <plc@xxxxxxxxxx> writes:
>
>> Attached patch adds multiple frame buffer size support to the xenfb PV
>> backend QEMU xenfb. Backend sets feature- resize and handles the
>> resize frame buffer event.
>>
>> Corresponding frontend LINUX patch is required for functionality but this
>> patch is not dependent on it, preserving backwards compatibility.
>>
>> Please apply to tip of xen- unstable
>>
>> Signed- off- by: Pat Campbell <plc@xxxxxxxxxx>
>>
>>
>>
>>
>>
>>
>>
>>
>> diff - r 2491691e3e69 tools/ioemu/hw/xenfb.c
>> --- a/tools/ioemu/hw/xenfb.c Sat Dec 29 17:57:47 2007 +0000
>> +++ b/tools/ioemu/hw/xenfb.c Mon Jan 07 12:38:25 2008 - 0700
>> @@ - 53,6 +53,7 @@ struct xenfb {
>> int abs_pointer_wanted; /* Whether guest supports absolute pointer */
>> int button_state; /* Last seen pointer button state */
>> char protocol[64]; /* frontend protocol */
>> + int fixevdev_abs; /* Descale abs pos so evdev scales properly */
>> };
>>
>> /* Functions for frontend/backend state machine*/
>> @@ - 233,6 +234,7 @@ struct xenfb *xenfb_new(int domid, Displ
>> struct xenfb *xenfb = qemu_malloc(sizeof(struct xenfb));
>> int serrno;
>> int i;
>> + int val;
>>
>> if (xenfb == NULL)
>> return NULL;
>> @@ - 264,6 +266,19 @@ struct xenfb *xenfb_new(int domid, Displ
>> xenfb- >ds = ds;
>> xenfb_device_set_domain(&xenfb- >fb, domid);
>> xenfb_device_set_domain(&xenfb- >kbd, domid);
>> +
>> + /* See if we need to fix abs ptr for guests evdev */
>> + if (xenfb_xs_scanf1(xenfb- >xsh, xenfb- >fb.nodename, "vnc-
>> fixevdev- abs",
>> + "%d", &val) < 0)
>> + val = 0;
>> + xenfb- >fixevdev_abs = val;
>> +
>> + /* Indicate we have the frame buffer resize feature if resizable
>> allowed */
>> + if (xenfb_xs_scanf1(xenfb- >xsh, xenfb- >fb.nodename,
>> "vncresizable- pvfb",
>> + "%d", &val) < 0)
>> + val = 0;
>> + if (val)
>> + xenfb_xs_printf(xenfb- >xsh, xenfb- >fb.nodename,
>> "xenfb- feature- resize", "1");
>
> You pass configuration parameters vnc- fixevdev- abs and
> vncresizable- pvfb through xenstore. The others are on the qemu
> command line. I'm not fond of configuring qemu through xenstore, but
> I guess it's the simplest solution here.
Dan suggested I use kernel parameters for these instead of xenstore.
Going to remove these and go that route. Also solves the init/connect
problem you pointed out below.
>
> The name xenfb- feature- resize doesn't match existing names
> request- update, feature- update, request- abs- pointer,
> feature- abs- pointer. Suggest to call it feature- resize.
Ok
>
> How's the transmission of feature- resize synchronized? The backend
> writes it right when it initializes. The frontend reads it on device
> probe. What ensures that the backend completes initialization before
> the frontend starts probing?
I guess it wasn't.
feature-resize is now set in state 'Connected' like request-update. kernel
parameter 'xenfb.dynamicModes' is tested in the probe function to determine
framebuffer memory allocation size.
>
> Have a look at the device initialization event diagram at
> http://wiki.xensource.com/xenwiki/XenSplitDrivers:
>
> Xenbus Xenbus
> Hotplug Backend Frontend
> ------- ------- --------
>
> Initialising Initialising
> | |
> |<--- start---- + |
> | | |
> | InitWait |
> | | write
> | | ring/
> write | channel
> physdets-------- >| details
> | |
> |<--------------------- Initialised
> | |
> write |
> physdets |
> | |
> Connected---------------------- >|
> | |
> | Connected
> | |
>
> For xenfb, this becomes:
>
> xenfb xenfb
> Backend Frontend
> ------- --------
>
> Initialising Initialising
> | |
> | |
> | |
> InitWait |
> | write
> | page- ref, event- channel
> | protocol, feature- update
> | |
> |<--------------------- Initialised
> | |
> read |
> page- ref, event- channel |
> protocol, feature- update |
> write |
> request- update |
> | |
> Connected---------------------- >|
> | |
> | read
> | request- update
> | |
> | Connected
> | |
>
> Your patches add:
>
> xenfb xenfb
> Backend Frontend
> ------- --------
>
> write read
> feature- resize feature- resize
> | |
> Initialising Initialising
> | |
> ... ...
>
> Here's a design that would fit more naturally into the protocol: make
> the frontend advertise feature- resize, and the backend request-
> resize,
> just like feature- update / request- update.
>
> The trouble with that is that the frontend knows doesn't know whether
> to do resize until it goes to state Connected. Complicates
> framebuffer allocation. It's allocated in xenfb_probe() for a reason:
> it's easy to handle failed allocations there, just fail the probe.
>
> Relatively easy way out: allocate the full framebuffer in probe,
> attempt to downsize it when going to Connected.
>
> By the way, the feature negotiation only covers whether the frontend
> is permitted to resize, not acceptable resolutions.
True. Acceptable resolutions are what fits within a 5MB framebuffer
and has a width no greater than 1280.
>
> What if the frontend resizes to a resolution the backend can't accept?
> The backend has no way to tell the frontend not to do that. Would we
> end up with a defunct display and no way for the user to fix it?
I don't think this is a possible issue. Frontend code limits the size of
the frame buffer to 5MB with a max horizontal scanline length of
1280. The backend VNC server should be able to handle that without
any problems.
>
> What happens when a malicious frontend resizes to a resolution that
> makes pd[] extend beyond the end of the shared page? Nothing new
> really, the current backend has the same problem with the initial
> resolution, I think.
Can't do that either. Maximum frame buffer size of 5MB fits within
the 3 page descriptors.
>
>>
>> fprintf(stderr, "FB: Waiting for KBD backend creation\n");
>> xenfb_wait_for_backend(&xenfb- >kbd, xenfb_backend_created_kbd);
>> @@ - 510,6 +525,11 @@ 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;
>> + dpy_resize(xenfb- >ds, xenfb- >width, xenfb-
>> >height);
>> + break;
>> }
>> }
>> mb(); /* ensure we're done with ring contents */
>> @@ - 605,11 +625,22 @@ static int xenfb_send_motion(struct xenf
>> return xenfb_kbd_event(xenfb, &event);
>> }
>>
>> +/* Descale abs pos for older evdev_drv without AbsoluteScreen option */
>> +static inline int xenfb_descale_for_evdev(float fb_width, float
> screen_width, float pos)
>
> This is used both for width and height, despite the parameter names.
> Suggest something like limit and max_limit.
>
>> +{
>> + return(((fb_width/screen_width) * pos) + 0.5);
>
> Style nitpick:
>
> return (fb_width/screen_width) * pos + 0.5;
>
>> +}
>> +
I have removed the whole scale code. I have arbitarily decided that if
a VM wishes to use dynamic modes and absolute mouse positioning it
should have an updated X evdev driver like what is in Fedora8 or
OpenSuSE 10.3
virt-manager with mouse grab works as good as it alway has.
>> /* Send an absolute mouse movement event */
>> static int xenfb_send_position(struct xenfb *xenfb, int abs_x, int abs_y,
> int abs_z)
>> {
>> union xenkbd_in_event event;
>>
>> + if (xenfb- >fixevdev_abs) {
>> + struct xenfb_page *page = xenfb- >fb.page;
>> + abs_x = xenfb_descale_for_evdev(page- >width, xenfb-
>> >width, abs_x);
>> + abs_y = xenfb_descale_for_evdev(page- >height, xenfb-
>> >height, abs_y);
>> + }
>> memset(&event, 0, XENKBD_IN_EVENT_SIZE);
>> event.type = XENKBD_TYPE_POS;
>> event.pos.abs_x = abs_x;
>> diff - r 2491691e3e69 tools/python/xen/xend/server/vfbif.py
>> --- a/tools/python/xen/xend/server/vfbif.py Sat Dec 29 17:57:47
>> 2007 +0000
>> +++ b/tools/python/xen/xend/server/vfbif.py Sun Jan 06 12:35:21 2008 -
>> 0700
>> @@ - 7,7 +7,8 @@ import os
>>
>> CONFIG_ENTRIES = ['type', 'vncdisplay', 'vnclisten', 'vncpasswd',
> 'vncunused',
>> 'display', 'xauthority', 'keymap',
>> - 'uuid', 'location', 'protocol']
>> + 'uuid', 'location', 'protocol',
>> + 'vncresizable- pvfb', 'vnc- fixevdev- abs' ]
>>
>> class VfbifController(DevController):
>> """Virtual frame buffer controller. Handles all vfb devices for a
> domain.
>> diff - r 2491691e3e69 tools/python/xen/xm/create.py
>> --- a/tools/python/xen/xm/create.py Sat Dec 29 17:57:47 2007 +0000
>> +++ b/tools/python/xen/xm/create.py Sun Jan 06 12:34:38 2008 - 0700
>> @@ - 485,6 +485,14 @@ gopts.var('vnclisten', val='',
>> fn=set_value, default=None,
>> use="""Address for VNC server to listen on.""")
>>
>> +gopts.var('vncresizable- pvfb', val='no|yes',
>> + fn=set_bool, default=0,
>> + use="""Allow resizable VNC PVFB if supported.""")
>> +
>> +gopts.var('vnc- fixevdev- abs', val='no|yes',
>> + fn=set_bool, default=0,
>> + use="""Correct resizable abs pointer positioning for evdev.""")
>> +
>> gopts.var('vncunused', val='',
>> fn=set_bool, default=1,
>> use="""Try to find an unused port for the VNC server.
>> @@ - 620,7 +628,8 @@ 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' ]:
>> + 'xauthority', 'type', 'vncpasswd',
>> + 'vncresizable- pvfb', 'vnc- fixevdev-
>> abs' ]:
>> err("configuration option %s unknown to vfbs" % k)
>> config.append([k,v])
>> if not d.has_key("keymap"):
>> diff - r 2491691e3e69 xen/include/public/io/fbif.h
>> --- a/xen/include/public/io/fbif.h Sat Dec 29 17:57:47 2007 +0000
>> +++ b/xen/include/public/io/fbif.h Sat Jan 05 11:10:07 2008 - 0700
>> @@ - 50,12 +50,26 @@ 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; /* xres */
>
> Commenting one snappy- short identifier with another one seems rather
> pointless to me :)
>
> If you insist on a comment, what about: x- resolution in pixels.
Ok
>
>> + int32_t height; /* yres */
>> +};
>> +
>> #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];
>> };
>>
>> @@ - 111,8 +125,12 @@ struct xenfb_page
>> * 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.
>> + *
>> + * Increased to 3 to support 1280x1024 resolution on a 64bit system
>> + * (1280*1024*4)/PAGE_SIZE = 1280 pages required
>> + * PAGE_SIZE/64bit long = 512 pages per page directory
>
> Please update the comment instead of appending to it.
>
>> */
>> - unsigned long pd[2];
>> + unsigned long pd[3];
>
> Extending pd[] is safe, because:
>
> * Current backends compute the length of pd[] from the size of the
> framebuffer. However, when protocol is not set, they rely on pd[1]
> == 0 to make 32- on- 64 work.
>
> * Old frontends don't set the protocol and use only pd[0]. They set
> pd[1] to 0.
>
> * Current frontends set the protocol and use pd[0..1]. Unused parts
> of the shared page are 0, including pd[2].
>
> * Your frontend additionally uses pd[2], but only when the backend
> agreed to it.
>
This has changed slightly with the use of dynamicMode module parameter.
Now using pd[2] if the vm was configured for it.
>> };
>>
>> /*
Thanks for your feedback
Will send updated patch when I have incorporated your suggestions
Pat
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|