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

Re: [Xen-devel][PATCH][IOEMU] Dynamic modes support for PV xenfb (2 of 2)


  • To: <xen-devel@xxxxxxxxxxxxxxxxxxx>
  • From: "Pat Campbell" <plc@xxxxxxxxxx>
  • Date: Fri, 11 Jan 2008 08:15:22 -0700
  • Delivery-date: Fri, 11 Jan 2008 07:15:54 -0800
  • List-id: Xen developer discussion <xen-devel.lists.xensource.com>

>>> 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


 


Rackspace

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