diff mbox series

[25/36] xen/console: introduce handle_keypress_in_domain()

Message ID 20241126-vuart-ns8250-v1-v1-25-87b9a8375b7a@ford.com (mailing list archive)
State New
Headers show
Series Introduce NS8250 UART emulator | expand

Commit Message

Denis Mukhin via B4 Relay Nov. 26, 2024, 11:22 p.m. UTC
From: Denis Mukhin <dmukhin@ford.com>

With introduction of NS8250 emulator for x86, the logic of switching console
focus gets more convoluted: HVM domain w/ NS8205 must be able to receive the
physical console input for guest VM debugging.

Also, existing code does not honor `hardware_dom=` xen command line parameter
(hardware domain ID does _not_ necessarily starts from 0).

Introduce handle_keypress_in_domain() to account for all scenarios of console
input forwarding.

Signed-off-by: Denis Mukhin <dmukhin@ford.com>
---
 xen/drivers/char/console.c | 102 ++++++++++++++++++++++++++-------------------
 1 file changed, 59 insertions(+), 43 deletions(-)
diff mbox series

Patch

diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 6261bdb5a2ac1075bc89fa408c0fd6cfef380ae6..4439e00763631969767719053cdc81e67c2cda2c 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -570,54 +570,70 @@  static void console_init_owner(void)
     console_set_owner(domid);
 }
 
-static void __serial_rx(char c)
+static void handle_keypress_in_domain(struct domain *d, char c)
 {
-    switch ( console_owner )
+    int rc = 0;
+
+    /*
+     * Deliver input to the emulated UART.
+     */
+    if ( domain_has_vuart(d) )
     {
-    case DOMID_XEN:
-        return handle_keypress(c, false);
-
-    case 0:
-        /*
-         * Deliver input to the hardware domain buffer, unless it is
-         * already full.
-         */
-        if ( (serial_rx_prod - serial_rx_cons) != SERIAL_RX_SIZE )
-            serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
-
-        /*
-         * Always notify the hardware domain: prevents receive path from
-         * getting stuck.
-         */
-        send_global_virq(VIRQ_CONSOLE);
-        break;
-
-#ifdef CONFIG_SBSA_VUART_CONSOLE
-    default:
-    {
-        struct domain *d = rcu_lock_domain_by_id(console_owner);
-
-        /*
-         * If we have a properly initialized vpl011 console for the
-         * domain, without a full PV ring to Dom0 (in that case input
-         * comes from the PV ring), then send the character to it.
-         */
-        if ( d != NULL )
-            vpl011_rx_char_xen(d, c);
-        else
-            printk("Cannot send chars to Dom%d: no UART available\n",
-                   console_owner);
-
-        if ( d != NULL )
-            rcu_unlock_domain(d);
-
-        break;
-    }
+#if defined(CONFIG_SBSA_VUART_CONSOLE)
+        rc = vpl011_rx_char_xen(d, c);
 #endif
     }
+    /*
+     * Deliver input to the hardware domain buffer.
+     */
+    else if ( d == hardware_domain )
+    {
+        /*
+         * Deliver input to the PV shim console.
+         */
+        if ( consoled_is_enabled() )
+            rc = consoled_guest_tx(c);
+        else
+        {
+            /*
+             * Deliver input to the hardware domain buffer, unless it is
+             * already full.
+             */
+            if ( (serial_rx_prod - serial_rx_cons) != SERIAL_RX_SIZE )
+                serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod++)] = c;
 
-    if ( consoled_is_enabled() )
-        consoled_guest_tx(c);
+            /*
+             * Always notify the hardware domain: prevents receive path from
+             * getting stuck.
+             */
+            send_global_virq(VIRQ_CONSOLE);
+            rc = 0;
+        }
+    }
+    /*
+     * Deliver input to the PV shim console.
+     */
+    else if ( consoled_is_enabled() )
+        rc = consoled_guest_tx(c);
+
+    if ( rc )
+        printk(KERN_WARNING "console input domain %d: not ready: %d\n",
+               d->domain_id, rc);
+
+}
+
+static void __serial_rx(char c)
+{
+    struct domain *d;
+
+    d = rcu_lock_domain_console_owner();
+    if ( d != NULL )
+    {
+        handle_keypress_in_domain(d, c);
+        rcu_unlock_domain(d);
+    }
+    else
+        handle_keypress(c, false);
 }
 
 static void cf_check serial_rx(char c)