|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v3] xen/console: handle multiple domains using console_io hypercalls
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.
When switching focus using Ctrl-AAA, discard any unread data in the
input buffer. Input is read quickly and the user would be aware of it
being slow or stuck as they use Ctrl-AAA to switch focus domain.
In that situation, it is to be expected that the unread input is lost.
The domain writes are buffered when the domain is not in focus. Push out
the buffer when the domain enters focus.
Add the console_lock around serial_rx_cons modifications to protect it
against concurrent writes to it.
Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxx>
---
Changes in v3:
- move serial_rx_cons before printk
- call console_put_domain earlier on CONSOLEIO_read
- take console_lock earlier
- add console_lock around serial_rx_cons modifications
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 | 30 +++++++++++++++++++++++++++---
1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 2bdb4d5fb4..58c32f22ef 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -577,6 +577,10 @@ static void console_switch_input(void)
console_rx = next_rx;
printk("*** Serial input to DOM%u", domid);
+ /* Don't let the next dom read the previous dom's unread data. */
+ nrspin_lock_irq(&console_lock);
+ serial_rx_cons = serial_rx_prod;
+ nrspin_unlock_irq(&console_lock);
break;
}
}
@@ -730,6 +734,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 +747,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 )
{
- /* Use direct console output as it could be interactive */
+ struct domain_console *cons = cd->console;
+
nrspin_lock_irq(&console_lock);
+ if ( cons->idx )
+ {
+ console_send(cons->buf, cons->idx, flags);
+ cons->idx = 0;
+ }
+ /* Use direct console output as it could be interactive */
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 +810,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 +831,11 @@ long do_console_io(
if ( count > INT_MAX )
break;
+ d = console_get_domain();
+ console_put_domain(d);
+ if ( d != current->domain )
+ return 0;
+
rc = 0;
while ( (serial_rx_cons != serial_rx_prod) && (rc < count) )
{
@@ -830,7 +851,10 @@ long do_console_io(
break;
}
rc += len;
- serial_rx_cons += len;
+ nrspin_lock_irq(&console_lock);
+ if ( serial_rx_cons != serial_rx_prod )
+ serial_rx_cons += len;
+ nrspin_unlock_irq(&console_lock);
}
break;
default:
--
2.25.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |