Skip to contentSkip to conversation

xen: paravirt framebuffer updates

PATCH New Jeremy Fitzhardinge 1 participant 6 messages May 23, 2008

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 xen: paravirt framebuffer updates

Hi Ingo,

This is a series from Markus Armbruster <[email protected]> which updates the Xen paravirtal framebuffer driver. Nothing very exciting.

The only non-Xen code touched by this series is in "xen: Enable console tty by default in domU if it's not a dummy", which adds a simple flag to kernel/printk.c to indicate that the preferrered console was set on the command line, which overrides any heuristics.

Thanks,
J

#1 lore raw

PATCH 1/1 xen: Enable console tty by default in domU if it's not a dummy

From: Markus Armbruster <[email protected]>

Without console= arguments on the kernel command line, the first console to register becomes enabled and the preferred console (the one behind /dev/console). This is normally tty (assuming CONFIG_VT_CONSOLE is enabled, which it commonly is).

This is okay as long tty is a useful console. But unless we have the PV framebuffer, and it is enabled for this domain, tty0 in domU is merely a dummy. In that case, we want the preferred console to be the Xen console hvc0, and we want it without having to fiddle with the kernel command line. Commit b8c2d3dfbc117dff26058fbac316b8acfc2cb5f7 did that for us.

Since we now have the PV framebuffer, we want to enable and prefer tty again, but only when PVFB is enabled. But even then we still want to enable the Xen console as well.

Problem: when tty registers, we can't yet know whether the PVFB is enabled. By the time we can know (xenstore is up), the console setup game is over.

Solution: enable console tty by default, but keep hvc as the preferred console. Change the preferred console to tty when PVFB probes successfully, unless we've been given console kernel parameters.

---
 arch/x86/xen/enlighten.c    |    4 +++-
 drivers/video/xen-fbfront.c |   25 +++++++++++++++++++++++++
 include/linux/console.h     |    2 ++
 kernel/printk.c             |    4 +++-
 4 files changed, 33 insertions(+), 2 deletions(-)
arch/x86/xen/enlighten.c +3 -1
@@ -1257,8 +1257,10 @@
 		? __pa(xen_start_info->mod_start) : 0;
 	boot_params.hdr.ramdisk_size = xen_start_info->mod_len;
 
-	if (!is_initial_xendomain())
+	if (!is_initial_xendomain()) {
+		add_preferred_console("tty", 0, NULL);
 		add_preferred_console("hvc", 0, NULL);
+	}
 
 	/* Start the world */
 	start_kernel();
drivers/video/xen-fbfront.c +25 -0
@@ -18,6 +18,7 @@
  * frame buffer.
  */
 
+#include <linux/console.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/fb.h>
@@ -48,6 +49,7 @@
 
 static u32 xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8;
 
+static void xenfb_make_preferred_console(void);
 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 *);
@@ -348,6 +350,7 @@
 	if (ret < 0)
 		goto error;
 
+	xenfb_make_preferred_console();
 	return 0;
 
  error_nomem:
@@ -356,6 +359,28 @@
  error:
 	xenfb_remove(dev);
 	return ret;
+}
+
+static __devinit void
+xenfb_make_preferred_console(void)
+{
+	struct console *c;
+
+	if (console_set_on_cmdline)
+		return;
+
+	acquire_console_sem();
+	for (c = console_drivers; c; c = c->next) {
+		if (!strcmp(c->name, "tty") && c->index == 0)
+			break;
+	}
+	release_console_sem();
+	if (c) {
+		unregister_console(c);
+		c->flags |= CON_CONSDEV;
+		c->flags &= ~CON_PRINTBUFFER; /* don't print again */
+		register_console(c);
+	}
 }
 
 static int xenfb_resume(struct xenbus_device *dev)
include/linux/console.h +2 -0
@@ -108,6 +108,8 @@
 	struct	 console *next;
 };
 
+extern int console_set_on_cmdline;
+
 extern int add_preferred_console(char *name, int idx, char *options);
 extern int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, char *options);
 extern void register_console(struct console *);
kernel/printk.c +3 -0
@@ -122,6 +122,8 @@
 static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
 static int selected_console = -1;
 static int preferred_console = -1;
+int console_set_on_cmdline;
+EXPORT_SYMBOL(console_set_on_cmdline);
 
 /* Flag: console code may call schedule() */
 static int console_may_schedule;
@@ -895,6 +897,7 @@
 	*s = 0;
 
 	__add_preferred_console(buf, idx, options, brl_options);
+	console_set_on_cmdline = 1;
 	return 1;
 }
 __setup("console=", console_setup);
#2 lore raw

PATCH 1/1 xen pvfb: Pointer z-axis (mouse wheel) support

In reply to Jeremy Fitzhardinge

From: Markus Armbruster <[email protected]>

Add z-axis motion to pointer events. Backward compatible, because there's space for the z-axis in union xenkbd_in_event, and old backends zero it.

Derived from
http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/57dfe0098000
http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/1edfea26a2a9
http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/c3ff0b26f664

---
 drivers/input/xen-kbdfront.c     |    8 +++++++-
 include/xen/interface/io/kbdif.h |    3 ++-
 2 files changed, 9 insertions(+), 2 deletions(-)
drivers/input/xen-kbdfront.c +7 -1
@@ -66,6 +66,9 @@
 		case XENKBD_TYPE_MOTION:
 			input_report_rel(dev, REL_X, event->motion.rel_x);
 			input_report_rel(dev, REL_Y, event->motion.rel_y);
+			if (event->motion.rel_z)
+				input_report_rel(dev, REL_WHEEL,
+						 -event->motion.rel_z);
 			break;
 		case XENKBD_TYPE_KEY:
 			dev = NULL;
@@ -84,6 +87,9 @@
 		case XENKBD_TYPE_POS:
 			input_report_abs(dev, ABS_X, event->pos.abs_x);
 			input_report_abs(dev, ABS_Y, event->pos.abs_y);
+			if (event->pos.rel_z)
+				input_report_rel(dev, REL_WHEEL,
+						 -event->pos.rel_z);
 			break;
 		}
 		if (dev)
@@ -152,7 +158,7 @@
 	ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
 	for (i = BTN_LEFT; i <= BTN_TASK; i++)
 		set_bit(i, ptr->keybit);
-	ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+	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);
 
include/xen/interface/io/kbdif.h +2 -0
@@ -49,6 +49,7 @@
 	uint8_t type;		/* XENKBD_TYPE_MOTION */
 	int32_t rel_x;		/* relative X motion */
 	int32_t rel_y;		/* relative Y motion */
+	int32_t rel_z;		/* relative Z motion (wheel) */
 };
 
 struct xenkbd_key {
@@ -61,6 +62,7 @@
 	uint8_t type;		/* XENKBD_TYPE_POS */
 	int32_t abs_x;		/* absolute X position (in FB pixels) */
 	int32_t abs_y;		/* absolute Y position (in FB pixels) */
+	int32_t rel_z;		/* relative Z motion (wheel) */
 };
 
 #define XENKBD_IN_EVENT_SIZE 40
#3 lore raw

PATCH 1/1 xen pvfb: Module aliases to support module autoloading

In reply to Jeremy Fitzhardinge

From: Markus Armbruster <[email protected]>

These are mostly for completeness and consistency with the other frontends, as PVFB is typically compiled in rather than a module.

Derived from
http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/5e294e29a43e

While there, add module descriptions.

---
 drivers/input/xen-kbdfront.c |    2 ++
 drivers/video/xen-fbfront.c  |    3 ++-
 2 files changed, 4 insertions(+), 1 deletion(-)
drivers/input/xen-kbdfront.c +2 -0
@@ -343,4 +343,6 @@
 module_init(xenkbd_init);
 module_exit(xenkbd_cleanup);
 
+MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("xen:vkbd");
drivers/video/xen-fbfront.c +2 -0
@@ -572,4 +572,6 @@
 module_init(xenfb_init);
 module_exit(xenfb_cleanup);
 
+MODULE_DESCRIPTION("Xen virtual framebuffer device frontend");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("xen:vfb");
#4 lore raw

PATCH 1/1 xen pvfb: Zero unused bytes in events sent to backend

In reply to Jeremy Fitzhardinge

From: Markus Armbruster <[email protected]>

This isn't a security flaw (the backend can see all our memory anyway). But it's the right thing to do all the same.

---
 drivers/video/xen-fbfront.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/video/xen-fbfront.c +1 -0
@@ -61,6 +61,7 @@
 	union xenfb_out_event event;
 	u32 prod;
 
+	memset(&event, 0, sizeof(event));
 	event.type = XENFB_TYPE_UPDATE;
 	event.update.x = x;
 	event.update.y = y;
#5 lore raw

PATCH 1/1 xen pvfb: Dynamic mode support (screen resizing)

In reply to Jeremy Fitzhardinge

From: Markus Armbruster <[email protected]>

The pvfb backend indicates dynamic mode support by creating node feature_resize with a non-zero value in its xenstore directory. xen-fbfront sends a resize notification event on mode change. Fully backwards compatible both ways.

Framebuffer size and initial resolution can be controlled through kernel parameter xen_fbfront.video. The backend enforces a separate size limit, which it advertises in node videoram in its xenstore directory.

xen-kbdfront gets the maximum screen resolution from nodes width and height in the backend's xenstore directory instead of hardcoding it.

Additional goodie: support for larger framebuffers (512M on a 64-bit system with 4K pages).

Changing the number of bits per pixels dynamically is not supported, yet.

Ported from
http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/92f7b3144f41
http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/bfc040135633

---
 drivers/input/xen-kbdfront.c    |   10 ++
 drivers/video/xen-fbfront.c     |  183 ++++++++++++++++++++++++++++++++-------
 include/xen/interface/io/fbif.h |   30 +++++-
 3 files changed, 188 insertions(+), 35 deletions(-)
drivers/input/xen-kbdfront.c +10 -0
@@ -300,6 +300,16 @@
 		 */
 		if (dev->state != XenbusStateConnected)
 			goto InitWait; /* no InitWait seen yet, fudge it */
+
+		/* Set input abs params to match backend screen res */
+		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+				 "width", "%d", &val) > 0)
+			input_set_abs_params(info->ptr, ABS_X, 0, val, 0, 0);
+
+		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+				 "height", "%d", &val) > 0)
+			input_set_abs_params(info->ptr, ABS_Y, 0, val, 0, 0);
+
 		break;
 
 	case XenbusStateClosing:
drivers/video/xen-fbfront.c +154 -29

304 lines not on this page · raw message

include/xen/interface/io/fbif.h +24 -5
@@ -49,11 +49,27 @@
 	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 */
+	int32_t offset;		/* start offset within framebuffer */
+};
+
 #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];
 };
 
@@ -105,15 +121,18 @@
 	 * 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