diff -r 6ed4368b4a9e xen/common/sysctl.c --- a/xen/common/sysctl.c Sun Oct 15 09:53:20 2006 +0100 +++ b/xen/common/sysctl.c Wed Oct 11 11:37:27 2006 +0900 @@ -50,7 +50,8 @@ long do_sysctl(XEN_GUEST_HANDLE(xen_sysc ret = read_console_ring( guest_handle_cast(op->u.readconsole.buffer, char), &op->u.readconsole.count, - op->u.readconsole.clear); + op->u.readconsole.clear, + &op->u.readconsole.cindex); if ( copy_to_guest(u_sysctl, op, 1) ) ret = -EFAULT; } diff -r 6ed4368b4a9e xen/drivers/char/console.c --- a/xen/drivers/char/console.c Sun Oct 15 09:53:20 2006 +0100 +++ b/xen/drivers/char/console.c Wed Oct 11 11:37:27 2006 +0900 @@ -66,13 +66,16 @@ static void putchar_console_ring(int c) conringc = conringp - CONRING_SIZE; } -long read_console_ring(XEN_GUEST_HANDLE(char) str, u32 *pcount, int clear) +long read_console_ring(XEN_GUEST_HANDLE(char) str, u32 *pcount, int clear, u32 *pcindex) { unsigned int idx, len, max, sofar, c; unsigned long flags; max = *pcount; sofar = 0; + + if ( clear < 0 ) + goto readbyindex; c = conringc; while ( (c != conringp) && (sofar < max) ) @@ -100,6 +103,36 @@ long read_console_ring(XEN_GUEST_HANDLE( } *pcount = sofar; + return 0; + +readbyindex: + c = *pcindex; + if ( conringp < c ) + { + *pcindex = conringp - CONRING_SIZE; + *pcount = sofar; + return 0; + } + + if (((conringp - c) > CONRING_SIZE) || (conringp < c)) + c = conringp - CONRING_SIZE; + + while ( (c != conringp) && (sofar < max) ) + { + idx = CONRING_IDX_MASK(c); + len = conringp - c; + if ( (idx + len) > CONRING_SIZE ) + len = CONRING_SIZE - idx; + if ( (sofar + len) > max ) + len = max - sofar; + if ( copy_to_guest_offset(str, sofar, &conring[idx], len) ) + return -EFAULT; + sofar += len; + c += len; + } + + *pcindex = c; + *pcount = sofar; return 0; } diff -r 6ed4368b4a9e xen/include/public/sysctl.h --- a/xen/include/public/sysctl.h Sun Oct 15 09:53:20 2006 +0100 +++ b/xen/include/public/sysctl.h Fri Oct 20 21:35:15 2006 +0900 @@ -24,10 +24,12 @@ #define XEN_SYSCTL_readconsole 1 struct xen_sysctl_readconsole { /* IN variables. */ - uint32_t clear; /* Non-zero -> clear after reading. */ + int32_t clear; /* Greater-than-zero -> clear after reading. */ + /* Less-than-zero -> use caller index. */ XEN_GUEST_HANDLE(char) buffer; /* Buffer start */ /* IN/OUT variables. */ uint32_t count; /* In: Buffer size; Out: Used buffer size */ + uint32_t cindex; /* In: Consumer index; Out: Next index */ }; typedef struct xen_sysctl_readconsole xen_sysctl_readconsole_t; DEFINE_XEN_GUEST_HANDLE(xen_sysctl_readconsole_t); diff -r 6ed4368b4a9e xen/include/xen/console.h --- a/xen/include/xen/console.h Sun Oct 15 09:53:20 2006 +0100 +++ b/xen/include/xen/console.h Wed Oct 11 11:37:27 2006 +0900 @@ -13,7 +13,7 @@ void set_printk_prefix(const char *prefix); -long read_console_ring(XEN_GUEST_HANDLE(char), u32 *, int); +long read_console_ring(XEN_GUEST_HANDLE(char), u32 *, int, u32 *); void init_console(void); void console_endboot(void);