diff mbox series

[RFC,12/12] xue: allow driving the reset of XHCI by a domain while Xen uses DbC

Message ID 2f7660330861b1c6db9520332bee20388178c162.1654486751.git-series.marmarek@invisiblethingslab.com (mailing list archive)
State Superseded
Headers show
Series Add Xue - console over USB 3 Debug Capability | expand

Commit Message

Marek Marczykowski-Górecki June 6, 2022, 3:40 a.m. UTC
That's possible, because the capability was designed specifically to
allow separate driver handle it, in parallel to unmodified xhci driver
(separate set of registers, pretending the port is "disconnected" for
the main xhci driver etc). It works with Linux dom0, although requires
an awful hack - re-enabling bus mastering behind dom0's backs.
Linux driver does similar thing - see
drivers/usb/early/xhci-dbc.c:xdbc_handle_events().

To avoid Linux messing with the DbC, mark this MMIO area as read-only.

Signed-off-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
---
 xen/drivers/char/xue.c | 13 +++++++------
 xen/include/xue.h      | 10 ++++++++++
 2 files changed, 17 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/xen/drivers/char/xue.c b/xen/drivers/char/xue.c
index ff62b868e906..437ed6468630 100644
--- a/xen/drivers/char/xue.c
+++ b/xen/drivers/char/xue.c
@@ -27,6 +27,7 @@ 
 #include <xen/timer.h>
 #include <xen/param.h>
 #include <xen/iommu.h>
+#include <xen/rangeset.h>
 #include <xue.h>
 
 #define XUE_POLL_INTERVAL 100 /* us */
@@ -71,12 +72,12 @@  static void __init cf_check xue_uart_init_postirq(struct serial_port *port)
     init_timer(&uart->timer, xue_uart_poll, port, 0);
     set_timer(&uart->timer, NOW() + MILLISECS(1));
 
-    if ( pci_ro_device(0, (uart->xue.xhc_cf8 >> 16) & 0xff,
-                          (uart->xue.xhc_cf8 >> 8) & 0xff) )
-            printk(XENLOG_INFO "Could not mark config space of %02x:%02x.%u read-only.\n",
-                   (uart->xue.xhc_cf8 >> 16) & 0xff,
-                   (uart->xue.xhc_cf8 >> 11) & 0x1f,
-                   (uart->xue.xhc_cf8 >> 8) & 0x0f);
+#ifdef CONFIG_X86
+    if ( rangeset_add_range(mmio_ro_ranges,
+                PFN_DOWN(uart->xue.xhc_mmio_phys + uart->xue.xhc_dbc_offset),
+                PFN_UP(uart->xue.xhc_mmio_phys + uart->xue.xhc_dbc_offset + sizeof(*uart->xue.dbc_reg)) - 1) )
+        printk(XENLOG_INFO "Error while adding MMIO range of device to mmio_ro_ranges\n");
+#endif
 }
 
 static int cf_check xue_uart_tx_ready(struct serial_port *port)
diff --git a/xen/include/xue.h b/xen/include/xue.h
index b1f304958679..87b821429fd8 100644
--- a/xen/include/xue.h
+++ b/xen/include/xue.h
@@ -1818,6 +1818,7 @@  static inline void xue_flush(struct xue *xue, struct xue_trb_ring *trb,
 {
     struct xue_dbc_reg *reg = xue->dbc_reg;
     uint32_t db = (reg->db & 0xFFFF00FF) | (trb->db << 8);
+    uint32_t cmd;
 
     if (xue->open && !(reg->ctrl & (1UL << XUE_CTRL_DCE))) {
         if (!xue_init_dbc(xue)) {
@@ -1829,6 +1830,15 @@  static inline void xue_flush(struct xue *xue, struct xue_trb_ring *trb,
         xue_enable_dbc(xue);
     }
 
+    /* Re-enable bus mastering, if dom0 (or other) disabled it in the meantime. */
+    cmd = xue_pci_read(xue, xue->xhc_cf8, 1);
+#define XUE_XHCI_CMD_REQUIRED (PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER)
+    if ((cmd & XUE_XHCI_CMD_REQUIRED) != XUE_XHCI_CMD_REQUIRED) {
+        cmd |= XUE_XHCI_CMD_REQUIRED;
+        xue_pci_write(xue, xue->xhc_cf8, 1, cmd);
+    }
+#undef XUE_XHCI_CMD_REQUIRED
+
     xue_pop_events(xue);
 
     if (!(reg->ctrl & (1UL << XUE_CTRL_DCR))) {