Allow multiple dom0less domains to use the console_io hypercalls to print to the console. Handle them in a similar way to vpl011: only the domain which has focus can read from the console. All domains can write to the console but the ones without focus have a prefix. In this case the prefix is applied by using guest_printk instead of printk or console_puts which is what the original code was already doing.
Signed-off-by: Stefano Stabellini <[email protected]> --- Changes in v2: - fix code style - pbuf_idx/idx after ada53067083e - don't add extra \0 - clear input on console switch --- xen/drivers/char/console.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 2bdb4d5fb4..6c7a6592c5 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -576,6 +576,8 @@ static void console_switch_input(void) rcu_unlock_domain(d); console_rx = next_rx; + /* don't let the next dom read the previous dom's unread data */ + serial_rx_cons = serial_rx_prod; printk("*** Serial input to DOM%u", domid); break; } @@ -730,6 +732,7 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer, unsigned int flags = opt_console_to_ring ? CONSOLE_ALL : CONSOLE_DEFAULT; struct domain *cd = current->domain; + struct domain *input; while ( count > 0 ) { @@ -742,18 +745,28 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer, if ( copy_from_guest(kbuf, buffer, kcount) ) return -EFAULT; - if ( is_hardware_domain(cd) ) + input = console_get_domain(); + if ( input && cd == input ) { + struct domain_console *cons = cd->console; + + if ( cons->idx ) + { + console_send(cons->buf, cons->idx, flags); + cons->idx = 0; + } /* Use direct console output as it could be interactive */ nrspin_lock_irq(&console_lock); console_send(kbuf, kcount, flags); nrspin_unlock_irq(&console_lock); + console_put_domain(input); } else { char *kin = kbuf, *kout = kbuf, c; struct domain_console *cons = cd->console; + console_put_domain(input); /* Strip non-printable characters */ do { @@ -795,6 +808,7 @@ long do_console_io( { long rc; unsigned int idx, len; + struct domain *d; rc = xsm_console_io(XSM_OTHER, current->domain, cmd); if ( rc ) @@ -815,6 +829,13 @@ long do_console_io( if ( count > INT_MAX ) break; + d = console_get_domain(); + if ( d != current->domain ) + { + console_put_domain(d); + return 0; + } + rc = 0; while ( (serial_rx_cons != serial_rx_prod) && (rc < count) ) { @@ -826,12 +847,14 @@ long do_console_io( len = count - rc; if ( copy_to_guest_offset(buffer, rc, &serial_rx_ring[idx], len) ) { + console_put_domain(d); rc = -EFAULT; break; } rc += len; serial_rx_cons += len; } + console_put_domain(d); break; default: rc = -ENOSYS; -- 2.25.1
