[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2] 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.

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxx>
---
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




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.