aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/drivers/char/console.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index d97170c641..9e1adb50f7 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -264,6 +264,49 @@ static void sercon_puts(const char *s)
serial_puts(sercon_handle, s);
}
+static void dump_console_ring_key(unsigned char key)
+{
+ uint32_t idx, len, sofar, c;
+ unsigned int order;
+ char *buf;
+
+ printk("'%c' pressed -> dumping console ring buffer (dmesg)\n", key);
+
+ /* create a buffer in which we'll copy the ring in the correct
+ order and NUL terminate */
+ order = get_order_from_bytes(conring_size + 1);
+ buf = alloc_xenheap_pages(order, 0);
+ if ( buf == NULL )
+ {
+ printk("unable to allocate memory!\n");
+ return;
+ }
+
+ c = conringc;
+ sofar = 0;
+ while ( (c != conringp) )
+ {
+ idx = CONRING_IDX_MASK(c);
+ len = conringp - c;
+ if ( (idx + len) > conring_size )
+ len = conring_size - idx;
+ memcpy(buf + sofar, &conring[idx], len);
+ sofar += len;
+ c += len;
+ }
+ buf[sofar] = '\0';
+
+ sercon_puts(buf);
+ vga_puts(buf);
+
+ free_xenheap_pages(buf, order);
+}
+
+static struct keyhandler dump_console_ring_keyhandler = {
+ .u.fn = dump_console_ring_key,
+ .desc = "synchronously dump console ring buffer (dmesg)"
+};
+
/* CTRL-<switch_char> switches input direction between Xen and DOM0. */
#define switch_code (opt_conswitch[0]-'a'+1)
static int __read_mostly xen_rx = 1; /* FALSE => serial input passed to domain 0. */
@@ -661,6 +704,8 @@ void __init console_endboot(void)
if ( opt_conswitch[1] == 'x' )
xen_rx = !xen_rx;
+ register_keyhandler('w', &dump_console_ring_keyhandler);
+
/* Serial input is directed to DOM0 by default. */
switch_serial_input();
}