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

Re: [Xen-devel][RFC]Dynamic modes support for PV xenfb (included)



Pat Campbell <plc@xxxxxxxxxx> writes:

> Rehash following last round of comments
>
> What changed:
>  1. Reverted back to pd[] for mappings, removed all gntref code.
>  2. Added videoram vfb parameter so that admin can limit what a frontend
> can allocate
>  3. xenfb kernel parameters are used to set the built-in width and
> height to support
>      configure less X11. 
>           extra="xenfb.video=5,1024,768 "
>
> Unless I missed something I think this addresses all of the raised concerns.

Thanks!

> Thanks to all that have looked at this never ending RFC and commented.

PVFB took several interations to pass review into xen-unstable.  Took
us roughly five months.  I'm fairly confident that this won't drag on
for nearly as long.

> Pat
>
>
> diff -r e32fe4703ab6 drivers/xen/fbfront/xenfb.c
> --- a/drivers/xen/fbfront/xenfb.c     Tue Jan 29 11:53:33 2008 +0000
> +++ b/drivers/xen/fbfront/xenfb.c     Mon Feb 04 11:34:36 2008 -0700
> @@ -28,6 +28,7 @@
>  #include <asm/hypervisor.h>
>  #include <xen/evtchn.h>
>  #include <xen/interface/io/fbif.h>
> +#include <xen/interface/io/kbdif.h>
>  #include <xen/interface/io/protocols.h>
>  #include <xen/xenbus.h>
>  #include <linux/kthread.h>
> @@ -62,6 +63,13 @@ struct xenfb_info
>       struct xenfb_page       *page;
>       unsigned long           *mfns;
>       int                     update_wanted; /* XENFB_TYPE_UPDATE wanted */
> +     int                     feature_resize; /* Backend has resize feature */
> +     int                     resize_dpy;
> +     int                     xres, yres;     /* current resolution */

Aren't these redundant with fb_info->var.xres and .yres?  Whenever the
same thing is stored in multiple places, a little dwarf in the back of
my brain starts worrying about consistency, which I find kind of
distracting...

> +     int                     fb_size;        /* fb size in bytes */

Redundant with fb_info->fix.smem_len?

> +     int                     fb_width;       /* fb mem width in pixels */
> +     int                     fb_height;      /* fb mem height in pixels */

struct fb_var_screeninfo uses width and height for screen dimension in
mm.  Hmm.  Perhaps use max_xres and max_yres here?

But do we really need these?  The only use outside of xenfb_probe() is
in xenfb_check_var(), which could easily use fb_stride instead.

> +     int                     fb_stride;      /* fb stride in bytes */

Redundant with fb_info->fix.line_length?

>  
>       struct xenbus_device    *xbdev;
>  };
> @@ -129,20 +137,48 @@ struct xenfb_info
>   *
>   * Oh well, we wont be updating the writes to this page anytime soon.
>   */
> +enum {KPARAM_MEM, KPARAM_WIDTH, KPARAM_HEIGHT, KPARAM_CNT};
> +static int video[KPARAM_CNT] = {0};
> +static int video_cnt = 0;
> +module_param_array(video, int, &video_cnt, 0);
> +MODULE_PARM_DESC(video, 
> +             "Size of video memory in MB and width,height in pixels, default 
> = (2,800,600)");

As far as I can see, mem never changes.  width and height can change,
but never beyond the initial width.  Correct?

Perhaps somebody might want to specify a maximum width different from
the initial width.  I don't know.

> +
> +#define XENFB_WIDTH 800
> +#define XENFB_HEIGHT 600
> +#define XENFB_DEPTH 32
> +#define MB_ (1024*1024)
> +#define XENFB_PIXCLOCK  9025  /* Xorg "1280x1024" 110.80 to FB 
> 1000000/110.80 */ 

I appreciate the attempt to explain how you arrived at the pixel
clock, but it's still confusing.  And possibly wrong: the pixel clock
seems to be for 1280x1024, while the resolution is 800x600.

> +#define XENFB_DEFAULT_FB_LEN (XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8)
>  
>  static int xenfb_fps = 20;
> -static unsigned long xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * 
> XENFB_DEPTH / 8;
> +static unsigned long xenfb_mem_len = 0;

Is this variable still needed?  I suspect all its uses can easily be
replaced by struct xenfb's fb_size.

>  
>  static int xenfb_remove(struct xenbus_device *);
>  static void xenfb_init_shared_page(struct xenfb_info *);
>  static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info 
> *);
>  static void xenfb_disconnect_backend(struct xenfb_info *);
> +static void xenfb_refresh(struct xenfb_info *info, int x1, int y1, int w, 
> int h);

Style nitpick: long line.  The parameter names don't buy us much in a
forward declaration.

> +
> +static void xenfb_send_event(struct xenfb_info *info,
> +             union xenfb_out_event *event)
> +{
> +     __u32 prod;
> +
> +     prod = info->page->out_prod;
> +     /* caller ensures !xenfb_queue_full() */
> +     mb();                   /* ensure ring space available */
> +     XENFB_OUT_RING_REF(info->page, prod) = *event;
> +     wmb();                  /* ensure ring contents visible */
> +     info->page->out_prod = prod + 1;
> +
> +     notify_remote_via_irq(info->irq);
> +}
>  
>  static void xenfb_do_update(struct xenfb_info *info,
>                           int x, int y, int w, int h)
>  {
>       union xenfb_out_event event;
> -     __u32 prod;
>  
>       event.type = XENFB_TYPE_UPDATE;
>       event.update.x = x;
> @@ -150,14 +186,19 @@ static void xenfb_do_update(struct xenfb
>       event.update.width = w;
>       event.update.height = h;
>  
> -     prod = info->page->out_prod;
> -     /* caller ensures !xenfb_queue_full() */

I'd keep this comment here, and also copy it to xenfb_do_resize().

> -     mb();                   /* ensure ring space available */
> -     XENFB_OUT_RING_REF(info->page, prod) = event;
> -     wmb();                  /* ensure ring contents visible */
> -     info->page->out_prod = prod + 1;
> -
> -     notify_remote_via_irq(info->irq);
> +     xenfb_send_event(info, &event);
> +}
> +
> +static void xenfb_do_resize(struct xenfb_info *info)
> +{
> +     union xenfb_out_event event;
> +
> +     event.type = XENFB_TYPE_RESIZE;
> +     event.resize.width = info->xres;
> +     event.resize.height = info->yres;
> +     event.resize.stride = info->fb_stride;

I'm not sure the stride changes on resize (see below), but it's
probably a good idea to put it in the protocol.

I think you better set event.resize.depth = XENFB_DEPTH here.

> +
> +     xenfb_send_event(info, &event);
>  }
>  
>  static int xenfb_queue_full(struct xenfb_info *info)
> @@ -209,6 +250,16 @@ static void xenfb_update_screen(struct x
>       xenfb_do_update(info, x1, y1, x2 - x1, y2 - y1);
>  }
>  
> +static void xenfb_resize_screen(struct xenfb_info *info)
> +{
> +     if (xenfb_queue_full(info))
> +             return;
> +
> +     info->resize_dpy = 0;
> +     xenfb_do_resize(info);
> +     xenfb_refresh(info, 0, 0, info->xres, info->yres);

Hmm, ugly.  See next comment.

> +}
> +
>  static int xenfb_thread(void *data)
>  {
>       struct xenfb_info *info = data;
> @@ -217,6 +268,9 @@ static int xenfb_thread(void *data)
>               if (info->dirty) {
>                       info->dirty = 0;
>                       xenfb_update_screen(info);
> +             }
> +             if (info->resize_dpy) {
> +                     xenfb_resize_screen(info);
>               }

Both screen resizes and dirtying don't go to the backend immediately.
Instead, they accumulate in struct xenfb_info (dirty rectangle and
resize_dpy flag) until they get pushed by xenfb_thread().

The way things work, a resize triggers three events:

1. The update event for the dirty rectangle.  In theory, the dirty
rectangle could be clean, but I expect it to be quite dirty in
practice, as user space typically redraws everything right after a
resize.

2. The resize event.

3. Another update event, because xenfb_resize_screen() dirties the
whole screen.  This event is delayed until the next iteration of
xenfb_thread()'s loop.

I'd rather do it like this: decree that resize events count as whole
screen updates.  Make xenfb_resize_screen() clear the dirty rectangle
(optional, saves an update event).  Test resize_dpy before dirty.

Also: you access resize_dpy, xres, yres and fb_stride from multiple
threads without synchronization.  I fear that's not safe.  Don't you
have to protect them with a spinlock, like dirty_lock protects the
dirty rectangle?  Could reuse dirty_lock, I guess.

>               wait_event_interruptible(info->wq,
>                       kthread_should_stop() || info->dirty);
> @@ -413,6 +467,47 @@ static int xenfb_mmap(struct fb_info *fb
>       return 0;
>  }
>  
> +static int
> +xenfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
> +{
> +     struct xenfb_info *xenfb_info;
> +
> +     xenfb_info = info->par;
> +
> +     if (!xenfb_info->feature_resize) {
> +             if (var->xres == XENFB_WIDTH && var->yres == XENFB_HEIGHT
> +                             && var->bits_per_pixel == 
> xenfb_info->page->depth) {

Avoidable long line due to excessive indentation.

> +                     return 0;
> +             }
> +             return -EINVAL;
> +     }
> +     if (var->bits_per_pixel == xenfb_info->page->depth && 
> +                     xenfb_info->fb_width >= var->xres && 
> +                     xenfb_mem_len >= (var->xres * var->yres * 
> (xenfb_info->page->depth / 8))) {

Ditto.

Please put all var-> terms on the left hand side, and all xenfb_ terms
on the right hand side.  My poor little mind finds that easier to
understand than mixing left and right.

> +             var->xres_virtual = var->xres;
> +             var->yres_virtual = var->yres;

Stupid question: what about var->pixclock?  Does one clock fit all, or
does somebody else update it, or should we recompute it?

> +             return 0;
> +     }
> +     return -EINVAL;
> +}
> +
> +static int xenfb_set_par(struct fb_info *info)
> +{
> +     struct xenfb_info *xenfb_info;
> +
> +     xenfb_info = info->par;
> +
> +     if (xenfb_info->xres != info->var.xres || 
> +                     xenfb_info->yres != info->var.yres) {
> +             xenfb_info->resize_dpy = 1;
> +             xenfb_info->xres = info->var.xres_virtual = info->var.xres;
> +             xenfb_info->yres = info->var.yres_virtual = info->var.yres;
> +             info->fix.line_length = xenfb_info->fb_stride;

I'm not sure we're supposed to touch info->fix.  Is it necessary?  I
can't see fb_stride change on resize.

> +             xenkbd_set_ptr_geometry(xenfb_info->xres, xenfb_info->yres);
> +     }
> +     return 0;
> +}
> +
>  static struct fb_ops xenfb_fb_ops = {
>       .owner          = THIS_MODULE,
>       .fb_setcolreg   = xenfb_setcolreg,
> @@ -420,6 +515,8 @@ static struct fb_ops xenfb_fb_ops = {
>       .fb_copyarea    = xenfb_copyarea,
>       .fb_imageblit   = xenfb_imageblit,
>       .fb_mmap        = xenfb_mmap,
> +     .fb_check_var   = xenfb_check_var,
> +     .fb_set_par     = xenfb_set_par,
>  };
>  
>  static irqreturn_t xenfb_event_handler(int rq, void *dev_id,
> @@ -450,6 +547,8 @@ static int __devinit xenfb_probe(struct 
>  {
>       struct xenfb_info *info;
>       struct fb_info *fb_info;
> +     int fb_size;
> +     int val;
>       int ret;
>  
>       info = kzalloc(sizeof(*info), GFP_KERNEL);
> @@ -457,6 +556,32 @@ static int __devinit xenfb_probe(struct 
>               xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
>               return -ENOMEM;
>       }

All right, what do you do here:

> +
> +     info->fb_width = info->xres = XENFB_WIDTH;
> +     info->fb_height = info->yres = XENFB_HEIGHT;
> +     fb_size = XENFB_DEFAULT_FB_LEN;

Start with defaults.

> +
> +     if (xenbus_scanf(XBT_NIL, dev->otherend, "videoram", "%d", &val) == 1) {

If domain config limits videoram...

> +             if (val * MB_ >= XENFB_DEFAULT_FB_LEN) {

... and the limit is below the default,

> +                     video[KPARAM_MEM] = val;
> +                     fb_size = val * MB_;

then store it in video[KPARAM_MEM].

Note that it will only get used when kernel parameter video supplied
all values (see right below).

> +             }
> +     }
> +
> +     if (video_cnt == KPARAM_CNT && (video[KPARAM_MEM] * MB_) >= 
> XENFB_DEFAULT_FB_LEN) {

If kernel parameter video supplied all values, and the memory value is
above the default,

> +             fb_size = video[KPARAM_MEM] * MB_;

then use it instead of the default,

else silently ignore the memory value.

> +             if (video[KPARAM_WIDTH] * video[KPARAM_HEIGHT] * XENFB_DEPTH/8 
> < fb_size) {

If kernel parameter video supplied all values, and the width and
height values fit the memory value we actually use,

> +                     info->fb_width = info->xres = video[KPARAM_WIDTH];
> +                     info->fb_height = info->yres = video[KPARAM_HEIGHT];
> +             }

then use them instead of the defaults,

else silently ignore them.

> +     }

Isn't this too complicated?

Why do you ignore memory sizes below the default (both xenstore and
kernel parameters)?  I'd trust the system administrator here.  If he
asks for a 320x200 rope to hang himself, just give it to him.

Ignoring kernel parameters silently isn't very nice.

I suspect this would be easier if you initialized video[] with the
defaults.  Then reduce memory for xenstore's videoram.  Then check
width & height against memory, and reduce until they fit.

> +
> +     info->fb_size = fb_size;
> +     info->fb_stride = info->fb_width * (XENFB_DEPTH / 8);
> +     xenfb_mem_len = info->fb_size;
> +
> +     xenkbd_set_ptr_geometry(info->fb_width, info->fb_height);
> +
>       dev->dev.driver_data = info;
>       info->xbdev = dev;
>       info->irq = -1;
> @@ -504,9 +629,10 @@ static int __devinit xenfb_probe(struct 
>       fb_info->screen_base = info->fb;
>  
>       fb_info->fbops = &xenfb_fb_ops;
> -     fb_info->var.xres_virtual = fb_info->var.xres = info->page->width;
> -     fb_info->var.yres_virtual = fb_info->var.yres = info->page->height;
> +     fb_info->var.xres_virtual = fb_info->var.xres = info->xres;
> +     fb_info->var.yres_virtual = fb_info->var.yres = info->yres;
>       fb_info->var.bits_per_pixel = info->page->depth;
> +     fb_info->var.pixclock = XENFB_PIXCLOCK;
>  
>       fb_info->var.red = (struct fb_bitfield){16, 8, 0};
>       fb_info->var.green = (struct fb_bitfield){8, 8, 0};
> @@ -572,6 +698,8 @@ static int xenfb_resume(struct xenbus_de
>  
>       xenfb_disconnect_backend(info);
>       xenfb_init_shared_page(info);
> +     if (info->xres != XENFB_WIDTH || info->yres != XENFB_HEIGHT)
> +             info->resize_dpy = 1;

Still needs a comment :)

>       return xenfb_connect_backend(dev, info);
>  }
>  
> @@ -600,6 +728,7 @@ static void xenfb_init_shared_page(struc
>  static void xenfb_init_shared_page(struct xenfb_info *info)
>  {
>       int i;
> +     int epd = PAGE_SIZE/sizeof(info->mfns[0]);
>  
>       for (i = 0; i < info->nr_pages; i++)
>               info->pages[i] = vmalloc_to_page(info->fb + i * PAGE_SIZE);
> @@ -607,12 +736,13 @@ static void xenfb_init_shared_page(struc
>       for (i = 0; i < info->nr_pages; i++)
>               info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
>  
> -     info->page->pd[0] = vmalloc_to_mfn(info->mfns);
> -     info->page->pd[1] = 0;
> -     info->page->width = XENFB_WIDTH;
> -     info->page->height = XENFB_HEIGHT;
> +     for (i = 0; i * epd < info->nr_pages; i++) 
> +                     info->page->pd[i] = vmalloc_to_mfn(&info->mfns[i * 
> epd]);

Indented one tab too much.

> +
> +     info->page->width = info->xres;
> +     info->page->height = info->yres;
>       info->page->depth = XENFB_DEPTH;
> -     info->page->line_length = (info->page->depth / 8) * info->page->width;
> +     info->page->line_length = info->fb_stride;
>       info->page->mem_length = xenfb_mem_len;
>       info->page->in_cons = info->page->in_prod = 0;
>       info->page->out_cons = info->page->out_prod = 0;
> @@ -710,6 +840,11 @@ static void xenfb_backend_changed(struct
>                       val = 0;
>               if (val)
>                       info->update_wanted = 1;
> +
> +             if (xenbus_scanf(XBT_NIL, dev->otherend, 
> +                                     "feature-resize", "%d", &val) < 0)
> +                     val = 0;
> +             info->feature_resize = val;
>               break;
>  
>       case XenbusStateClosing:
> diff -r e32fe4703ab6 drivers/xen/fbfront/xenkbd.c
> --- a/drivers/xen/fbfront/xenkbd.c    Tue Jan 29 11:53:33 2008 +0000
> +++ b/drivers/xen/fbfront/xenkbd.c    Mon Feb 04 08:41:35 2008 -0700
> @@ -40,6 +40,10 @@ static int xenkbd_remove(struct xenbus_d
>  static int xenkbd_remove(struct xenbus_device *);
>  static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info 
> *);
>  static void xenkbd_disconnect_backend(struct xenkbd_info *);
> +
> +static int max_abs_xres;
> +static int max_abs_yres;
> +static struct input_dev *mouse_ptr;

Can't have more than one device.  How ugly.

>  /*
>   * Note: if you need to send out events, see xenfb_do_update() for how
> @@ -163,8 +167,8 @@ int __devinit xenkbd_probe(struct xenbus
>       for (i = BTN_LEFT; i <= BTN_TASK; i++)
>               set_bit(i, ptr->keybit);
>       ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
> -     input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
> -     input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
> +     input_set_abs_params(ptr, ABS_X, 0, max_abs_xres, 0, 0);
> +     input_set_abs_params(ptr, ABS_Y, 0, max_abs_yres, 0, 0);
>  
>       ret = input_register_device(ptr);
>       if (ret) {
> @@ -172,7 +176,7 @@ int __devinit xenkbd_probe(struct xenbus
>               xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
>               goto error;
>       }
> -     info->ptr = ptr;
> +     mouse_ptr = info->ptr = ptr;
>  
>       ret = xenkbd_connect_backend(dev, info);
>       if (ret < 0)
> @@ -338,6 +342,18 @@ static void __exit xenkbd_cleanup(void)
>       return xenbus_unregister_driver(&xenkbd);
>  }
>  
> +void xenkbd_set_ptr_geometry(int xres, int yres)
> +{
> +     max_abs_xres = xres;
> +     max_abs_yres = yres;
> +     if (mouse_ptr) {

Race condition: if this gets executed after xenkbd_probe() read
max_abs_xres, max_abs_yres, but before it set mouse_ptr, the geometry
update gets lost.

I fear you need proper synchronization instead of a hack...

> +             input_set_abs_params(mouse_ptr, ABS_X, 0, max_abs_xres, 0, 0);
> +             input_set_abs_params(mouse_ptr, ABS_Y, 0, max_abs_yres, 0, 0);
> +             input_event(mouse_ptr, EV_SYN, SYN_CONFIG, 0);
> +     }
> +}
> +EXPORT_SYMBOL(xenkbd_set_ptr_geometry);
> +
>  module_init(xenkbd_init);
>  module_exit(xenkbd_cleanup);
>  
> diff -r e32fe4703ab6 include/xen/interface/io/fbif.h
> --- a/include/xen/interface/io/fbif.h Tue Jan 29 11:53:33 2008 +0000
> +++ b/include/xen/interface/io/fbif.h Mon Feb 04 08:53:20 2008 -0700
> @@ -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;   /* future */

"future" isn't so helpful.  What about "bits per pixel"?  If the
backend can deal with that already.  If not, I'd comment "reserved for
future use".

> +};
> +
>  #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,21 +125,13 @@ 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.
> - */
> -#ifdef __KERNEL__
> -#define XENFB_WIDTH 800
> -#define XENFB_HEIGHT 600
> -#define XENFB_DEPTH 32
> -#endif
>  
>  #endif
>  
> diff -r e32fe4703ab6 include/xen/interface/io/kbdif.h
> --- a/include/xen/interface/io/kbdif.h        Tue Jan 29 11:53:33 2008 +0000
> +++ b/include/xen/interface/io/kbdif.h        Fri Feb 01 11:54:37 2008 -0700
> @@ -119,6 +119,10 @@ struct xenkbd_page
>      uint32_t out_cons, out_prod;
>  };
>  
> +#ifdef __KERNEL__
> +void xenkbd_set_ptr_geometry(int xres, int yres);
> +#endif
> +
>  #endif
>  
>  /*
> diff -r 1b013d10c6d1 tools/ioemu/hw/xenfb.c
> --- a/tools/ioemu/hw/xenfb.c  Mon Jan 28 10:37:08 2008 +0000
> +++ b/tools/ioemu/hw/xenfb.c  Mon Feb 04 07:30:36 2008 -0700
> @@ -264,6 +264,9 @@ struct xenfb *xenfb_new(int domid, Displ
>       xenfb->ds = ds;
>       xenfb_device_set_domain(&xenfb->fb, domid);
>       xenfb_device_set_domain(&xenfb->kbd, domid);
> +
> +     /* Indicate we have the frame buffer resize feature */
> +     xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "feature-resize", "1");

Did you take care of the synchronization problem I pointed out here:

    Subject: Re: [Xen-devel][PATCH][IOEMU] Dynamic modes support for PV xenfb 
(2 of 2)
    From: Markus Armbruster <armbru@xxxxxxxxxx>
    Date: Thu, 10 Jan 2008 11:18:41 +0100
    Message-ID: <87ejcqhtku.fsf@xxxxxxxxxxxxxxxxx>
    http://lists.xensource.com/archives/html/xen-devel/2008-01/msg00229.html

?

Discussion starts at

    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?

>  
>       fprintf(stderr, "FB: Waiting for KBD backend creation\n");
>       xenfb_wait_for_backend(&xenfb->kbd, xenfb_backend_created_kbd);
> @@ -510,6 +513,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 +681,7 @@ static int xenfb_read_frontend_fb_config
>  static int xenfb_read_frontend_fb_config(struct xenfb *xenfb) {
>       struct xenfb_page *fb_page;
>       int val;
> +     int videoram = 0;
>  
>          if (xenfb_xs_scanf1(xenfb->xsh, xenfb->fb.otherend, "feature-update",
>                              "%d", &val) < 0)

The diffs are a bit easier to read if you use tabs like the rest of
the file.

> @@ -686,14 +696,22 @@ 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;

Indentation inconsistent with the rest of the file.  Please stick to 8
per level.

> +        }
>          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)
> diff -r 1b013d10c6d1 tools/python/xen/xend/server/vfbif.py
> --- a/tools/python/xen/xend/server/vfbif.py   Mon Jan 28 10:37:08 2008 +0000
> +++ b/tools/python/xen/xend/server/vfbif.py   Mon Feb 04 08:32:10 2008 -0700
> @@ -6,7 +6,7 @@ import os
>  import os
>  
>  CONFIG_ENTRIES = ['type', 'vncdisplay', 'vnclisten', 'vncpasswd', 
> 'vncunused',
> -                  'display', 'xauthority', 'keymap',
> +                  'videoram', 'display', 'xauthority', 'keymap',
>                    'uuid', 'location', 'protocol']
>  
>  class VfbifController(DevController):
> diff -r 1b013d10c6d1 tools/python/xen/xm/create.py
> --- a/tools/python/xen/xm/create.py   Mon Jan 28 10:37:08 2008 +0000
> +++ b/tools/python/xen/xm/create.py   Mon Feb 04 09:19:41 2008 -0700
> @@ -490,6 +490,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?""")
> @@ -620,7 +624,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"):
> diff -r 1b013d10c6d1 xen/include/public/io/fbif.h
[Copy of include/xen/interface/io/fbif.h we already saw, snipp]

_______________________________________________
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®.