From patchwork Mon Jun 6 03:40:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= X-Patchwork-Id: 12869923 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0D984C433EF for ; Mon, 6 Jun 2022 03:41:15 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.342165.567240 (Exim 4.92) (envelope-from ) id 1ny3bl-0006fR-Cz; Mon, 06 Jun 2022 03:40:49 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 342165.567240; Mon, 06 Jun 2022 03:40:49 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bl-0006fI-9p; Mon, 06 Jun 2022 03:40:49 +0000 Received: by outflank-mailman (input) for mailman id 342165; Mon, 06 Jun 2022 03:40:47 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bj-0006AI-HQ for xen-devel@lists.xenproject.org; Mon, 06 Jun 2022 03:40:47 +0000 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 713c33db-e54a-11ec-b605-df0040e90b76; Mon, 06 Jun 2022 05:40:43 +0200 (CEST) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 07A8A5C0145; Sun, 5 Jun 2022 23:40:43 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Sun, 05 Jun 2022 23:40:43 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 5 Jun 2022 23:40:41 -0400 (EDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 713c33db-e54a-11ec-b605-df0040e90b76 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= invisiblethingslab.com; h=cc:cc:content-transfer-encoding:date :date:from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to; s=fm1; t= 1654486842; x=1654573242; bh=CFmNRn1sKegjaekfi5r4EENRtjIFuajMleR bsmOlPR0=; b=h6ZiwRe3juzDkGKl8KWuU+hxR2Ws/Rh2huRnP+phOkHQ9Wcff9n xHd76tdGUgNh2kcVj9yzcN5odBCxzqLEp4Z6OZZghw2tWTFYScOq9DW+K3qTynd0 hpjsxzR+Se4vr91gGL5+Lfe5PjLV4pqy2iESd8lTMDNn2zkBC1ZsAIyQjPEE31/B kJQEC5JBsKC0MHGnmoFbzvQNWKpm5kuf9Yq99VqjdP/dHhf7hiGwG9axDHnYXhc3 0yUtxLrcF9HmhrrKmcR1CqM4/xj0GW+bSc6e8I1lwDENSMPL0qASELDpMp8VymDi GD/zPVmrQbNDPo8paH+SxemYcirTsa/DwQg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm2; t=1654486842; x=1654573242; bh=CFmNRn1sKegja ekfi5r4EENRtjIFuajMleRbsmOlPR0=; b=xmBpL7b7zH4+lQwmBHNOuKui+jOGZ jDRScHF9h/ElsH6EhcygzZwXkAC3jr5UXEsUMQ+D9j2Ik2e4/4OiLGpjWy9HRicR m71MlHZdWAEhSnj1Fykllyz5SzHtML/+yQObhW47kTQDsKoZN+8HdflE8U2NrcTX Byka9OtxHSsddFpQXdFO0kJArlLLP60HCdRdCYe8tpXEaJWxKRhOqx4f13X27fcz 2Hz6EwqSs2XQ5h4ixOStL70p5WphEDxVzyWzmMtSyI3+xz050UaETZa9G+Jof2Rn pQigHW/+V+zYPXvJYCBanaXmf2NFFQwzeooAF+6wsfkyW7cNS2gpcvogg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedruddtuddgjeefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhgggfestdekredtredtjeenucfhrhhomhepofgrrhgv khcuofgrrhgtiiihkhhofihskhhiqdfikphrvggtkhhiuceomhgrrhhmrghrvghksehinh hvihhsihgslhgvthhhihhnghhslhgrsgdrtghomheqnecuggftrfgrthhtvghrnhephedt keekieeffeekieevgfffjeejhfehtdelveehjefhieduveethedtueduudfhnecuffhomh grihhnpehgnhhurdhorhhgnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehm rghilhhfrhhomhepmhgrrhhmrghrvghksehinhhvihhsihgslhgvthhhihhnghhslhgrsg drtghomh X-ME-Proxy: Feedback-ID: i1568416f:Fastmail From: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= To: xen-devel@lists.xenproject.org Cc: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= , Jan Beulich , Andrew Cooper , =?utf-8?q?Roger_Pau_Monn=C3=A9?= , Wei Liu , George Dunlap , Julien Grall , Stefano Stabellini Subject: [RFC PATCH 01/12] drivers/char: Add support for Xue USB3 debugger Date: Mon, 6 Jun 2022 05:40:13 +0200 Message-Id: <8d45d05dae0b5a2aa62120c7ff62295319a74478.1654486751.git-series.marmarek@invisiblethingslab.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: References: MIME-Version: 1.0 From: Connor Davis Xue is a cross-platform USB 3 debugger that drives the Debug Capability (DbC) of xHCI-compliant host controllers. This patch implements the operations needed for xue to initialize the host controller's DbC and communicate with it. It also implements a struct uart_driver that uses xue as a backend. Note that only target -> host communication is supported for now. To use Xue as a console, add 'console=dbgp dbgp=xue' to the command line. --- xen/arch/x86/include/asm/fixmap.h | 4 +- xen/arch/x86/setup.c | 5 +- xen/drivers/char/Makefile | 1 +- xen/drivers/char/xue.c | 156 +++- xen/include/xue.h | 1855 ++++++++++++++++++++++++++++++- 5 files changed, 2021 insertions(+) create mode 100644 xen/drivers/char/xue.c create mode 100644 xen/include/xue.h diff --git a/xen/arch/x86/include/asm/fixmap.h b/xen/arch/x86/include/asm/fixmap.h index 20746afd0a2a..bc39ffe896b1 100644 --- a/xen/arch/x86/include/asm/fixmap.h +++ b/xen/arch/x86/include/asm/fixmap.h @@ -25,6 +25,8 @@ #include #include +#define MAX_XHCI_PAGES 16 + /* * Here we define all the compile-time 'special' virtual * addresses. The point is to have a constant address at @@ -43,6 +45,8 @@ enum fixed_addresses { FIX_COM_BEGIN, FIX_COM_END, FIX_EHCI_DBGP, + FIX_XHCI_BEGIN, + FIX_XHCI_END = FIX_XHCI_BEGIN + MAX_XHCI_PAGES - 1, #ifdef CONFIG_XEN_GUEST FIX_PV_CONSOLE, FIX_XEN_SHARED_INFO, diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 53a73010e029..8fda7107da25 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -56,6 +56,8 @@ #include #include +#include + /* opt_nosmp: If true, secondary processors are ignored. */ static bool __initdata opt_nosmp; boolean_param("nosmp", opt_nosmp); @@ -852,6 +854,8 @@ static struct domain *__init create_dom0(const module_t *image, /* How much of the directmap is prebuilt at compile time. */ #define PREBUILT_MAP_LIMIT (1 << L2_PAGETABLE_SHIFT) +void __init xue_uart_init(void); + void __init noreturn __start_xen(unsigned long mbi_p) { char *memmap_type = NULL; @@ -946,6 +950,7 @@ void __init noreturn __start_xen(unsigned long mbi_p) ns16550.irq = 3; ns16550_init(1, &ns16550); ehci_dbgp_init(); + xue_uart_init(); console_init_preirq(); if ( pvh_boot ) diff --git a/xen/drivers/char/Makefile b/xen/drivers/char/Makefile index 14e67cf072d7..292d1bbd78d3 100644 --- a/xen/drivers/char/Makefile +++ b/xen/drivers/char/Makefile @@ -11,5 +11,6 @@ obj-$(CONFIG_HAS_EHCI) += ehci-dbgp.o obj-$(CONFIG_HAS_IMX_LPUART) += imx-lpuart.o obj-$(CONFIG_ARM) += arm-uart.o obj-y += serial.o +obj-y += xue.o obj-$(CONFIG_XEN_GUEST) += xen_pv_console.o obj-$(CONFIG_PV_SHIM) += consoled.o diff --git a/xen/drivers/char/xue.c b/xen/drivers/char/xue.c new file mode 100644 index 000000000000..8aefae482b71 --- /dev/null +++ b/xen/drivers/char/xue.c @@ -0,0 +1,156 @@ +/* + * drivers/char/xue.c + * + * Xen port for the xue debugger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see . + * + * Copyright (c) 2019 Assured Information Security. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define XUE_POLL_INTERVAL 100 /* us */ + +struct xue_uart { + struct xue xue; + struct timer timer; + spinlock_t *lock; +}; + +static struct xue_uart xue_uart; +static struct xue_ops xue_ops; + +static void xue_uart_poll(void *data) +{ + struct serial_port *port = data; + struct xue_uart *uart = port->uart; + struct xue *xue = &uart->xue; + unsigned long flags = 0; + + if ( spin_trylock_irqsave(&port->tx_lock, flags) ) + { + xue_flush(xue, &xue->dbc_oring, &xue->dbc_owork); + spin_unlock_irqrestore(&port->tx_lock, flags); + } + + serial_tx_interrupt(port, guest_cpu_user_regs()); + set_timer(&uart->timer, NOW() + MICROSECS(XUE_POLL_INTERVAL)); +} + +static void __init xue_uart_init_preirq(struct serial_port *port) +{ + struct xue_uart *uart = port->uart; + uart->lock = &port->tx_lock; +} + +static void __init xue_uart_init_postirq(struct serial_port *port) +{ + struct xue_uart *uart = port->uart; + + serial_async_transmit(port); + init_timer(&uart->timer, xue_uart_poll, port, 0); + set_timer(&uart->timer, NOW() + MILLISECS(1)); +} + +static int xue_uart_tx_ready(struct serial_port *port) +{ + struct xue_uart *uart = port->uart; + struct xue *xue = &uart->xue; + + return XUE_WORK_RING_CAP - xue_work_ring_size(&xue->dbc_owork); +} + +static void xue_uart_putc(struct serial_port *port, char c) +{ + struct xue_uart *uart = port->uart; + xue_putc(&uart->xue, c); +} + +static inline void xue_uart_flush(struct serial_port *port) +{ + s_time_t goal; + struct xue_uart *uart = port->uart; + struct xue *xue = &uart->xue; + + xue_flush(xue, &xue->dbc_oring, &xue->dbc_owork); + + goal = NOW() + MICROSECS(XUE_POLL_INTERVAL); + if ( uart->timer.expires > goal ) + set_timer(&uart->timer, goal); +} + +static struct uart_driver xue_uart_driver = { + .init_preirq = xue_uart_init_preirq, + .init_postirq = xue_uart_init_postirq, + .endboot = NULL, + .suspend = NULL, + .resume = NULL, + .tx_ready = xue_uart_tx_ready, + .putc = xue_uart_putc, + .flush = xue_uart_flush, + .getc = NULL +}; + +static struct xue_trb evt_trb[XUE_TRB_RING_CAP] __aligned(XUE_PAGE_SIZE); +static struct xue_trb out_trb[XUE_TRB_RING_CAP] __aligned(XUE_PAGE_SIZE); +static struct xue_trb in_trb[XUE_TRB_RING_CAP] __aligned(XUE_PAGE_SIZE); +static struct xue_erst_segment erst __aligned(64); +static struct xue_dbc_ctx ctx __aligned(64); +static uint8_t wrk_buf[XUE_WORK_RING_CAP] __aligned(XUE_PAGE_SIZE); +static char str_buf[XUE_PAGE_SIZE] __aligned(64); +static char __initdata opt_dbgp[30]; + +string_param("dbgp", opt_dbgp); + +void __init xue_uart_init(void) +{ + struct xue_uart *uart = &xue_uart; + struct xue *xue = &uart->xue; + + if ( strncmp(opt_dbgp, "xue", 3) ) + return; + + memset(xue, 0, sizeof(*xue)); + memset(&xue_ops, 0, sizeof(xue_ops)); + + xue->dbc_ctx = &ctx; + xue->dbc_erst = &erst; + xue->dbc_ering.trb = evt_trb; + xue->dbc_oring.trb = out_trb; + xue->dbc_iring.trb = in_trb; + xue->dbc_owork.buf = wrk_buf; + xue->dbc_str = str_buf; + + xue->dma_allocated = 1; + xue->sysid = xue_sysid_xen; + xue_open(xue, &xue_ops, NULL); + + serial_register_uart(SERHND_DBGP, &xue_uart_driver, &xue_uart); +} + +void xue_uart_dump(void) +{ + struct xue_uart *uart = &xue_uart; + struct xue *xue = &uart->xue; + + xue_dump(xue); +} diff --git a/xen/include/xue.h b/xen/include/xue.h new file mode 100644 index 000000000000..66f7d66447f3 --- /dev/null +++ b/xen/include/xue.h @@ -0,0 +1,1855 @@ +/* + * Copyright (C) 2019 Assured Information Security, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef XUE_H +#define XUE_H + +/* @cond */ + +#define XUE_PAGE_SIZE 4096ULL + +/* Supported xHC PCI configurations */ +#define XUE_XHC_CLASSC 0xC0330ULL +#define XUE_XHC_VEN_INTEL 0x8086ULL +#define XUE_XHC_DEV_Z370 0xA2AFULL +#define XUE_XHC_DEV_Z390 0xA36DULL +#define XUE_XHC_DEV_WILDCAT_POINT 0x9CB1ULL +#define XUE_XHC_DEV_SUNRISE_POINT 0x9D2FULL +#define XUE_XHC_DEV_CANNON_POINT 0x9DEDULL + +/* DbC idVendor and idProduct */ +#define XUE_DBC_VENDOR 0x1D6B +#define XUE_DBC_PRODUCT 0x0010 +#define XUE_DBC_PROTOCOL 0x0000 + +/* DCCTRL fields */ +#define XUE_CTRL_DCR 0 +#define XUE_CTRL_HOT 2 +#define XUE_CTRL_HIT 3 +#define XUE_CTRL_DRC 4 +#define XUE_CTRL_DCE 31 + +/* DCPORTSC fields */ +#define XUE_PSC_PED 1 +#define XUE_PSC_CSC 17 +#define XUE_PSC_PRC 21 +#define XUE_PSC_PLC 22 +#define XUE_PSC_CEC 23 + +#define XUE_PSC_ACK_MASK \ + ((1UL << XUE_PSC_CSC) | (1UL << XUE_PSC_PRC) | (1UL << XUE_PSC_PLC) | \ + (1UL << XUE_PSC_CEC)) + +static inline int known_xhc(uint32_t dev_ven) +{ + switch (dev_ven) { + case (XUE_XHC_DEV_Z370 << 16) | XUE_XHC_VEN_INTEL: + case (XUE_XHC_DEV_Z390 << 16) | XUE_XHC_VEN_INTEL: + case (XUE_XHC_DEV_WILDCAT_POINT << 16) | XUE_XHC_VEN_INTEL: + case (XUE_XHC_DEV_SUNRISE_POINT << 16) | XUE_XHC_VEN_INTEL: + case (XUE_XHC_DEV_CANNON_POINT << 16) | XUE_XHC_VEN_INTEL: + return 1; + default: + return 0; + } +} + +/* Xue system id */ +enum { + xue_sysid_linux, + xue_sysid_windows, + xue_sysid_efi, + xue_sysid_xen, + xue_sysid_test +}; + +/* Userspace testing */ +#if defined(XUE_TEST) +#include +#include + +#define xue_debug(...) printf("xue debug: " __VA_ARGS__) +#define xue_alert(...) printf("xue alert: " __VA_ARGS__) +#define xue_error(...) printf("xue error: " __VA_ARGS__) +#define XUE_SYSID xue_sysid_test + +extern "C" { +static inline int xue_sys_init(void *) { return 1; } +static inline void xue_sys_sfence(void *) {} +static inline void xue_sys_lfence(void *) {} +static inline void xue_sys_pause(void *) {} +static inline void xue_sys_clflush(void *, void *) {} +static inline void *xue_sys_map_xhc(void *, uint64_t, uint64_t) { return NULL; } +static inline void xue_sys_unmap_xhc(void *sys, void *, uint64_t) {} +static inline void *xue_sys_alloc_dma(void *, uint64_t) { return NULL; } +static inline void xue_sys_free_dma(void *sys, void *, uint64_t) {} +static inline void xue_sys_outd(void *sys, uint32_t, uint32_t) {} +static inline uint32_t xue_sys_ind(void *, uint32_t) { return 0; } +static inline uint64_t xue_sys_virt_to_dma(void *, const void *virt) +{ + return (uint64_t)virt; +} +} + +#endif + +/* Bareflank VMM */ +#if defined(VMM) +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static_assert(XUE_PAGE_SIZE == BAREFLANK_PAGE_SIZE); + +#define xue_printf(...) \ + do { \ + char buf[256] { 0 }; \ + snprintf(buf, 256, __VA_ARGS__); \ + for (int i = 0; i < 256; i++) { \ + if (buf[i]) { \ + bfvmm::DEFAULT_COM_DRIVER::instance()->write(buf[i]); \ + } else { \ + break; \ + } \ + } \ + } while (0) + +#define xue_debug(...) xue_printf("xue debug: " __VA_ARGS__) +#define xue_alert(...) xue_printf("xue alert: " __VA_ARGS__) +#define xue_error(...) xue_printf("xue error: " __VA_ARGS__) + +#ifdef __cplusplus +extern "C" { +#endif + +static inline int xue_sys_init(void *) { return 1; } +static inline void xue_sys_sfence(void *) { ::intel_x64::wmb(); } +static inline void xue_sys_lfence(void *) { ::intel_x64::rmb(); } +static inline void xue_sys_pause(void *) { _pause(); } +static inline void xue_sys_clflush(void *, void *ptr) { _clflush(ptr); } + +static inline uint64_t xue_sys_virt_to_dma(void *sys, const void *virt) +{ + (void)sys; + return g_mm->virtptr_to_physint((void *)virt); +} + +static inline void *xue_sys_alloc_dma(void *sys, uint64_t order) +{ + (void)sys; + return g_mm->alloc(XUE_PAGE_SIZE << order); +} + +static inline void xue_sys_free_dma(void *sys, void *addr, uint64_t order) +{ + (void)sys; + (void)order; + + g_mm->free(addr); +} + +static inline void *xue_sys_map_xhc(void *sys, uint64_t phys, uint64_t count) +{ + (void)sys; + + void *virt = g_mm->alloc_map(count); + + for (uint64_t i = 0U; i < count; i += XUE_PAGE_SIZE) { + using attr_t = bfvmm::x64::cr3::mmap::attr_type; + using mem_t = bfvmm::x64::cr3::mmap::memory_type; + + g_cr3->map_4k((uint64_t)virt + i, phys + i, attr_t::read_write, + mem_t::uncacheable); + } + + return virt; +} + +static inline void xue_sys_unmap_xhc(void *sys, void *virt, uint64_t count) +{ + (void)sys; + + for (uint64_t i = 0U; i < count; i += XUE_PAGE_SIZE) { + g_cr3->unmap((uint64_t)virt + i); + } + + g_mm->free_map(virt); +} + +static inline void xue_sys_outd(void *sys, uint32_t port, uint32_t data) +{ + (void)sys; + _outd(port, data); +} + +static inline uint32_t xue_sys_ind(void *sys, uint32_t port) +{ + (void)sys; + return _ind(port); +} + +#ifdef __cplusplus +} +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Linux driver */ +#if defined(MODULE) && defined(__linux__) +#include +#include +#include +#include +#include + +#define xue_debug(...) printk(KERN_DEBUG "xue debug: " __VA_ARGS__) +#define xue_alert(...) printk(KERN_ALERT "xue alert: " __VA_ARGS__) +#define xue_error(...) printk(KERN_ERR "xue error: " __VA_ARGS__) +#define XUE_SYSID xue_sysid_linux + +static inline int xue_sys_init(void *sys) { return 1; } +static inline void xue_sys_sfence(void *sys) { wmb(); } +static inline void xue_sys_lfence(void *sys) { rmb(); } +static inline void xue_sys_clflush(void *sys, void *ptr) { clflush(ptr); } + +static inline void xue_sys_pause(void *sys) +{ + (void)sys; + __asm volatile("pause" ::: "memory"); +} + +static inline void *xue_sys_alloc_dma(void *sys, uint64_t order) +{ + return (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order); +} + +static inline void xue_sys_free_dma(void *sys, void *addr, uint64_t order) +{ + free_pages((unsigned long)addr, order); +} + +static inline void *xue_sys_map_xhc(void *sys, uint64_t phys, uint64_t count) +{ + return ioremap(phys, (long unsigned int)count); +} + +static inline void xue_sys_unmap_xhc(void *sys, void *virt, uint64_t count) +{ + (void)count; + iounmap((volatile void *)virt); +} + +static inline void xue_sys_outd(void *sys, uint32_t port, uint32_t data) +{ + outl(data, port); +} + +static inline uint32_t xue_sys_ind(void *sys, uint32_t port) +{ + return inl((int32_t)port); +} + +static inline uint64_t xue_sys_virt_to_dma(void *sys, const void *virt) +{ + return virt_to_phys((volatile void *)virt); +} + +#endif + +/* Windows driver */ +#if defined(_WIN32) +#include +typedef INT8 int8_t; +typedef INT16 int16_t; +typedef INT32 int32_t; +typedef INT64 int64_t; +typedef UINT8 uint8_t; +typedef UINT16 uint16_t; +typedef UINT32 uint32_t; +typedef UINT64 uint64_t; +typedef UINT_PTR uintptr_t; +typedef INT_PTR intptr_t; + +#define XUE_SYSID xue_sysid_windows + +#define xue_debug(...) \ + DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, \ + "xue debug: " __VA_ARGS__) +#define xue_alert(...) \ + DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, \ + "xue alert: " __VA_ARGS__) +#define xue_error(...) \ + DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, \ + "xue error: " __VA_ARGS__) + +static inline int xue_sys_init(void *sys) +{ + (void)sys; + + xue_error("Xue cannot be used from windows drivers"); + return 0; +} + +static inline void xue_sys_sfence(void *sys) +{ + (void)sys; + xue_error("Xue cannot be used from windows drivers"); +} + +static inline void xue_sys_lfence(void *sys) +{ + (void)sys; + xue_error("Xue cannot be used from windows drivers"); +} + +static inline void xue_sys_pause(void *sys) +{ + (void)sys; + xue_error("Xue cannot be used from windows drivers"); +} + +static inline void *xue_sys_alloc_dma(void *sys, uint64_t order) +{ + (void)sys; + (void)order; + + xue_error("Xue cannot be used from windows drivers"); + return NULL; +} + +static inline void xue_sys_free_dma(void *sys, void *addr, uint64_t order) +{ + (void)sys; + (void)addr; + (void)order; + + xue_error("Xue cannot be used from windows drivers"); +} + +static inline void *xue_sys_map_xhc(void *sys, uint64_t phys, uint64_t count) +{ + (void)sys; + (void)phys; + (void)count; + + xue_error("Xue cannot be used from windows drivers"); + return NULL; +} + +static inline void xue_sys_unmap_xhc(void *sys, void *virt, uint64_t count) +{ + (void)sys; + (void)virt; + (void)count; + + xue_error("Xue cannot be used from windows drivers"); +} + +static inline void xue_sys_outd(void *sys, uint32_t port, uint32_t data) +{ + (void)sys; + (void)port; + (void)data; + + xue_error("Xue cannot be used from windows drivers"); +} + +static inline uint32_t xue_sys_ind(void *sys, uint32_t port) +{ + (void)sys; + (void)port; + + xue_error("Xue cannot be used from windows drivers"); + return 0U; +} + +static inline uint64_t xue_sys_virt_to_dma(void *sys, const void *virt) +{ + (void)sys; + (void)virt; + + xue_error("Xue cannot be used from windows drivers"); + return 0U; +} + +#endif + +/* UEFI driver (based on gnuefi) */ +#if defined(EFI) +#include + +#define xue_debug(...) Print(L"xue debug: " __VA_ARGS__) +#define xue_alert(...) Print(L"xue alert: " __VA_ARGS__) +#define xue_error(...) Print(L"xue error: " __VA_ARGS__) +#define XUE_SYSID xue_sysid_efi + +/* NOTE: see xue_alloc_dma for the number of buffers created by alloc_dma */ +#define XUE_DMA_DESC_CAP 7 + +struct xue_efi_dma { + UINTN pages; + EFI_PHYSICAL_ADDRESS dma_addr; + VOID *cpu_addr; + VOID *mapping; +}; + +struct xue_efi { + EFI_HANDLE img_hand; + EFI_HANDLE pci_hand; + EFI_PCI_IO *pci_io; + struct xue_efi_dma dma_desc[XUE_DMA_DESC_CAP]; +}; + +static inline int xue_sys_init(void *sys) +{ + EFI_STATUS rc; + EFI_HANDLE *hand; + UINTN nr_hand; + UINTN i; + + struct xue_efi *efi = (struct xue_efi *)sys; + ZeroMem((VOID *)&efi->dma_desc, sizeof(efi->dma_desc)); + + rc = LibLocateHandle(ByProtocol, &PciIoProtocol, NULL, &nr_hand, &hand); + if (EFI_ERROR(rc)) { + xue_error("LocateHandle failed: 0x%llx\n", rc); + return 0; + } + + for (i = 0; i < nr_hand; i++) { + UINT32 dev_ven; + EFI_PCI_IO *pci_io = NULL; + + rc = gBS->OpenProtocol(hand[i], &PciIoProtocol, (VOID **)&pci_io, + efi->img_hand, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(rc)) { + continue; + } + + rc = pci_io->Pci.Read(pci_io, EfiPciIoWidthUint32, 0, 1, &dev_ven); + if (EFI_ERROR(rc)) { + gBS->CloseProtocol(hand[i], &PciIoProtocol, efi->img_hand, NULL); + continue; + } + + if (known_xhc(dev_ven)) { + efi->pci_hand = hand[i]; + efi->pci_io = pci_io; + return 1; + } + } + + xue_error("Failed to open PCI_IO_PROTOCOL on any known xHC\n"); + return 0; +} + +static inline void *xue_sys_alloc_dma(void *sys, uint64_t order) +{ + const EFI_ALLOCATE_TYPE atype = AllocateAnyPages; + const EFI_MEMORY_TYPE mtype = EfiRuntimeServicesData; + const UINTN attrs = EFI_PCI_ATTRIBUTE_MEMORY_CACHED; + const UINTN pages = 1UL << order; + + struct xue_efi_dma *dma = NULL; + struct xue_efi *efi = (struct xue_efi *)sys; + EFI_PCI_IO *pci = efi->pci_io; + EFI_STATUS rc = 0; + VOID *addr = NULL; + UINTN i = 0; + + for (; i < XUE_DMA_DESC_CAP; i++) { + dma = &efi->dma_desc[i]; + if (!dma->cpu_addr) { + break; + } + dma = NULL; + } + + if (!dma) { + xue_error("Out of DMA descriptors\n"); + return NULL; + } + + rc = pci->AllocateBuffer(pci, atype, mtype, pages, &addr, attrs); + if (EFI_ERROR(rc)) { + xue_error("AllocateBuffer failed: 0x%llx\n", rc); + return NULL; + } + + dma->pages = pages; + dma->cpu_addr = addr; + + return addr; +} + +static inline void xue_sys_free_dma(void *sys, void *addr, uint64_t order) +{ + (void)order; + + struct xue_efi_dma *dma = NULL; + struct xue_efi *efi = (struct xue_efi *)sys; + EFI_PCI_IO *pci = efi->pci_io; + EFI_STATUS rc = 0; + UINTN i = 0; + + for (; i < XUE_DMA_DESC_CAP; i++) { + dma = &efi->dma_desc[i]; + if (dma->cpu_addr == addr) { + break; + } + dma = NULL; + } + + if (!dma) { + return; + } + + if (dma->mapping) { + rc = pci->Unmap(pci, dma->mapping); + if (EFI_ERROR(rc)) { + xue_error("pci->Unmap failed: 0x%llx\n", rc); + } + } + + rc = pci->FreeBuffer(pci, dma->pages, addr); + if (EFI_ERROR(rc)) { + xue_error("FreeBuffer failed: 0x%llx\n", rc); + } + + ZeroMem((VOID *)dma, sizeof(*dma)); +} + +static inline uint64_t xue_sys_virt_to_dma(void *sys, const void *virt) +{ + UINTN i = 0; + UINTN offset = 0; + UINTN needed = 0; + UINTN mapped = 0; + struct xue_efi *efi = (struct xue_efi *)sys; + struct xue_efi_dma *dma = NULL; + EFI_PHYSICAL_ADDRESS dma_addr = 0; + EFI_PCI_IO *pci = efi->pci_io; + EFI_STATUS rc = 0; + VOID *mapping = NULL; + + for (; i < XUE_DMA_DESC_CAP; i++) { + dma = &efi->dma_desc[i]; + UINTN p = 0; + + for (; p < dma->pages; p++) { + UINTN addr = (UINTN)dma->cpu_addr + (p * XUE_PAGE_SIZE); + if ((UINTN)virt == addr) { + offset = addr - (UINTN)dma->cpu_addr; + goto found; + } + } + + dma = NULL; + } + + if (!dma) { + xue_error("CPU addr 0x%llx not found in DMA descriptor\n", virt); + return 0; + } + +found: + if (dma->dma_addr && dma->mapping) { + return dma->dma_addr + offset; + } + + needed = dma->pages << EFI_PAGE_SHIFT; + mapped = needed; + rc = pci->Map(pci, EfiPciIoOperationBusMasterCommonBuffer, (void *)virt, + &mapped, &dma_addr, &mapping); + if (EFI_ERROR(rc) || mapped != needed) { + xue_error("pci->Map failed: rc: 0x%llx, mapped: %llu, needed: %llu\n", + rc, mapped, needed); + return 0; + } + + dma->dma_addr = dma_addr; + dma->mapping = mapping; + + if ((const void *)dma_addr != virt) { + xue_alert("Non-identity DMA mapping: dma: 0x%llx cpu: 0x%llx\n", + dma_addr, virt); + } + + return dma_addr; +} + +static inline void xue_sys_outd(void *sys, uint32_t port, uint32_t val) +{ + (void)sys; + + __asm volatile("movq %0, %%rdx\n\t" + "movq %1, %%rax\n\t" + "outl %%eax, %%dx\n\t" + : + : "g"((uint64_t)port), "g"((uint64_t)val)); +} + +static inline uint32_t xue_sys_ind(void *sys, uint32_t port) +{ + (void)sys; + uint32_t ret; + + __asm volatile("xorq %%rax, %%rax\n\t" + "movq %1, %%rdx\n\t" + "inl %%dx, %%eax\n\t" + : "=a"(ret) + : "g"((uint64_t)port)); + return ret; +} + +static inline void *xue_sys_map_xhc(void *sys, uint64_t phys, uint64_t count) +{ + (void)sys; + (void)count; + + return (void *)phys; +} + +static inline void xue_sys_unmap_xhc(void *sys, void *virt, uint64_t count) +{ + (void)sys; + (void)virt; + (void)count; +} + +static inline void xue_sys_sfence(void *sys) +{ + (void)sys; + __asm volatile("sfence" ::: "memory"); +} + +static inline void xue_sys_lfence(void *sys) +{ + (void)sys; + __asm volatile("lfence" ::: "memory"); +} + +static inline void xue_sys_pause(void *sys) +{ + (void)sys; + __asm volatile("pause" ::: "memory"); +} + +static inline void xue_sys_clflush(void *sys, void *ptr) +{ + (void)sys; + __asm volatile("clflush %0" : "+m"(*(volatile char *)ptr)); +} + +#endif + +#if defined(__XEN__) && !defined(VMM) + +#include +#include +#include +#include + +#define xue_debug(...) printk("xue debug: " __VA_ARGS__) +#define xue_alert(...) printk("xue alert: " __VA_ARGS__) +#define xue_error(...) printk("xue error: " __VA_ARGS__) +#define XUE_SYSID xue_sysid_xen + +static inline int xue_sys_init(void *sys) { return 1; } +static inline void xue_sys_sfence(void *sys) { wmb(); } +static inline void xue_sys_lfence(void *sys) { rmb(); } +static inline void xue_sys_unmap_xhc(void *sys, void *virt, uint64_t count) {} +static inline void xue_sys_free_dma(void *sys, void *addr, uint64_t order) {} + +static inline void xue_sys_pause(void *sys) +{ + (void)sys; + __asm volatile("pause" ::: "memory"); +} + +static inline void xue_sys_clflush(void *sys, void *ptr) +{ + (void)sys; + __asm volatile("clflush %0" : "+m"(*(volatile char *)ptr)); +} + +static inline void *xue_sys_alloc_dma(void *sys, uint64_t order) +{ + return NULL; +} + +static inline uint32_t xue_sys_ind(void *sys, uint32_t port) +{ + return inl(port); +} + +static inline void xue_sys_outd(void *sys, uint32_t port, uint32_t data) +{ + outl(data, port); +} + +static inline uint64_t xue_sys_virt_to_dma(void *sys, const void *virt) +{ + return virt_to_maddr(virt); +} + +static void *xue_sys_map_xhc(void *sys, uint64_t phys, uint64_t size) +{ + size_t i; + + if (size != MAX_XHCI_PAGES * XUE_PAGE_SIZE) { + return NULL; + } + + for (i = FIX_XHCI_END; i >= FIX_XHCI_BEGIN; i--) { + set_fixmap_nocache(i, phys); + phys += XUE_PAGE_SIZE; + } + + /* + * The fixmap grows downward, so the lowest virt is + * at the highest index + */ + return fix_to_virt(FIX_XHCI_END); +} + +#endif + +/****************************************************************************** + * TRB ring (summarized from the manual): + * + * TRB rings are circular queues of TRBs shared between the xHC and the driver. + * Each ring has one producer and one consumer. The DbC has one event + * ring and two transfer rings; one IN and one OUT. + * + * The DbC hardware is the producer on the event ring, and + * xue is the consumer. This means that event TRBs are read-only from + * the xue. + * + * OTOH, xue is the producer of transfer TRBs on the two transfer + * rings, so xue enqueues transfers, and the hardware dequeues + * them. The dequeue pointer of a transfer ring is read by + * xue by examining the latest transfer event TRB on the event ring. The + * transfer event TRB contains the address of the transfer TRB that generated + * the event. + * + * To make each transfer ring circular, the last TRB must be a link TRB, which + * points to the beginning of the next queue. Note that this implementation + * does not support multiple segments, so each link TRB points back to the + * beginning of its own segment. + ******************************************************************************/ + +/* TRB types */ +enum { + xue_trb_norm = 1, + xue_trb_link = 6, + xue_trb_tfre = 32, + xue_trb_psce = 34 +}; + +/* TRB completion codes */ +enum { xue_trb_cc_success = 1, xue_trb_cc_trb_err = 5 }; + +/* DbC endpoint types */ +enum { xue_ep_bulk_out = 2, xue_ep_bulk_in = 6 }; + +/* DMA/MMIO structures */ +#pragma pack(push, 1) +struct xue_trb { + uint64_t params; + uint32_t status; + uint32_t ctrl; +}; + +struct xue_erst_segment { + uint64_t base; + uint16_t size; + uint8_t rsvdz[6]; +}; + +#define XUE_CTX_SIZE 16 +#define XUE_CTX_BYTES (XUE_CTX_SIZE * 4) + +struct xue_dbc_ctx { + uint32_t info[XUE_CTX_SIZE]; + uint32_t ep_out[XUE_CTX_SIZE]; + uint32_t ep_in[XUE_CTX_SIZE]; +}; + +struct xue_dbc_reg { + uint32_t id; + uint32_t db; + uint32_t erstsz; + uint32_t rsvdz; + uint64_t erstba; + uint64_t erdp; + uint32_t ctrl; + uint32_t st; + uint32_t portsc; + uint32_t rsvdp; + uint64_t cp; + uint32_t ddi1; + uint32_t ddi2; +}; +#pragma pack(pop) + +#define XUE_TRB_MAX_TFR (XUE_PAGE_SIZE << 4) +#define XUE_TRB_PER_PAGE (XUE_PAGE_SIZE / sizeof(struct xue_trb)) + +/* Defines the size in bytes of TRB rings as 2^XUE_TRB_RING_ORDER * 4096 */ +#ifndef XUE_TRB_RING_ORDER +#define XUE_TRB_RING_ORDER 4 +#endif +#define XUE_TRB_RING_CAP (XUE_TRB_PER_PAGE * (1ULL << XUE_TRB_RING_ORDER)) +#define XUE_TRB_RING_BYTES (XUE_TRB_RING_CAP * sizeof(struct xue_trb)) +#define XUE_TRB_RING_MASK (XUE_TRB_RING_BYTES - 1U) + +struct xue_trb_ring { + struct xue_trb *trb; /* Array of TRBs */ + uint32_t enq; /* The offset of the enqueue ptr */ + uint32_t deq; /* The offset of the dequeue ptr */ + uint8_t cyc; /* Cycle state toggled on each wrap-around */ + uint8_t db; /* Doorbell target */ +}; + +#define XUE_DB_OUT 0x0 +#define XUE_DB_IN 0x1 +#define XUE_DB_INVAL 0xFF + +/* Defines the size in bytes of work rings as 2^XUE_WORK_RING_ORDER * 4096 */ +#ifndef XUE_WORK_RING_ORDER +#define XUE_WORK_RING_ORDER 3 +#endif +#define XUE_WORK_RING_CAP (XUE_PAGE_SIZE * (1ULL << XUE_WORK_RING_ORDER)) +#define XUE_WORK_RING_BYTES XUE_WORK_RING_CAP + +#if XUE_WORK_RING_CAP > XUE_TRB_MAX_TFR +#error "XUE_WORK_RING_ORDER must be at most 4" +#endif + +struct xue_work_ring { + uint8_t *buf; + uint32_t enq; + uint32_t deq; + uint64_t dma; +}; + +/* @endcond */ + +/** + * Set of system-specific operations required by xue to initialize and + * control the DbC. An instance of this structure must be passed to + * xue_open. Any field that is NULL will default to the xue_sys_* + * implementation defined for the target platform. Any non-NULL field will + * simply be called. + */ +struct xue_ops { + /** + * Perform system-specific init operations + * + * @param sys a pointer to a system-specific data structure + * @return != 0 iff successful + */ + int (*init)(void *sys); + + /** + * Allocate pages for read/write DMA + * + * @param sys a pointer to a system-specific data structure + * @param order allocate 2^order pages + * @return a cpu-relative virtual address for accessing the DMA buffer + */ + void *(*alloc_dma)(void *sys, uint64_t order); + + /** + * Free pages previously allocated with alloc_dma + * + * @param sys a pointer to a system-specific data structure + * @param addr the cpu-relative address of the DMA range to free + * @param order the order of the set of pages to free + */ + void (*free_dma)(void *sys, void *addr, uint64_t order); + + /** + * Map in the xHC MMIO region as uncacheable memory + * + * @param sys a pointer to a system-specific data structure + * @param phys the value from the xHC's BAR + * @param size the number of bytes to map in + * @return the mapped virtual address + */ + void *(*map_xhc)(void *sys, uint64_t phys, uint64_t size); + + /** + * Unmap xHC MMIO region + * + * @param sys a pointer to a system-specific data structure + * @param virt the MMIO address to unmap + */ + void (*unmap_xhc)(void *sys, void *virt, uint64_t size); + + /** + * Write 32 bits to IO port + * + * @param sys a pointer to a system-specific data structure + * @param port the port to write to + * @param data the data to write + */ + void (*outd)(void *sys, uint32_t port, uint32_t data); + + /** + * Read 32 bits from IO port + * + * @param sys a pointer to a system-specific data structure + * @param port the port to read from + * @return the data read from the port + */ + uint32_t (*ind)(void *sys, uint32_t port); + + /** + * Translate a virtual address to a DMA address + * + * @param sys a pointer to a system-specific data structure + * @param virt the address returned from a previous alloc_dma call + * @return the resulting bus-relative DMA address + */ + uint64_t (*virt_to_dma)(void *sys, const void *virt); + + /** + * Perform a write memory barrier + * @param sys a pointer to a system-specific data structure + */ + void (*sfence)(void *sys); + + /** + * Perform a read memory barrier + * @param sys a pointer to a system-specific data structure + */ + void (*lfence)(void *sys); + + /** + * Pause CPU execution + * @param sys a pointer to a system-specific data structure + */ + void (*pause)(void *sys); + + /** + * Flush the cache line at the given address + * @param sys a pointer to a system-specific data structure + * @param ptr the address to flush + */ + void (*clflush)(void *sys, void *ptr); +}; + +/* @cond */ + +struct xue { + struct xue_ops *ops; + void *sys; + + struct xue_dbc_reg *dbc_reg; + struct xue_dbc_ctx *dbc_ctx; + struct xue_erst_segment *dbc_erst; + struct xue_trb_ring dbc_ering; + struct xue_trb_ring dbc_oring; + struct xue_trb_ring dbc_iring; + struct xue_work_ring dbc_owork; + char *dbc_str; + + uint32_t xhc_cf8; + uint64_t xhc_mmio_phys; + uint64_t xhc_mmio_size; + uint64_t xhc_dbc_offset; + void *xhc_mmio; + + int dma_allocated; + int open; + int sysid; +}; + +static inline void *xue_mset(void *dest, int c, uint64_t size) +{ + uint64_t i; + char *d = (char *)dest; + + for (i = 0; i < size; i++) { + d[i] = (char)c; + } + + return dest; +} + +static inline void *xue_mcpy(void *dest, const void *src, uint64_t size) +{ + uint64_t i; + char *d = (char *)dest; + const char *s = (const char *)src; + + for (i = 0; i < size; i++) { + d[i] = s[i]; + } + + return dest; +} + +static inline void xue_flush_range(struct xue *xue, void *ptr, uint32_t bytes) +{ + uint32_t i; + + const uint32_t clshft = 6; + const uint32_t clsize = (1UL << clshft); + const uint32_t clmask = clsize - 1; + + uint32_t lines = (bytes >> clshft); + lines += (bytes & clmask) != 0; + + for (i = 0; i < lines; i++) { + xue->ops->clflush(xue->sys, (void *)((uint64_t)ptr + (i * clsize))); + } +} + +static inline uint32_t xue_pci_read(struct xue *xue, uint32_t cf8, uint32_t reg) +{ + void *sys = xue->sys; + uint32_t addr = (cf8 & 0xFFFFFF03UL) | (reg << 2); + + xue->ops->outd(sys, 0xCF8, addr); + return xue->ops->ind(sys, 0xCFC); +} + +static inline void xue_pci_write(struct xue *xue, uint32_t cf8, uint32_t reg, + uint32_t val) +{ + void *sys = xue->sys; + uint32_t addr = (cf8 & 0xFFFFFF03UL) | (reg << 2); + + xue->ops->outd(sys, 0xCF8, addr); + xue->ops->outd(sys, 0xCFC, val); +} + +static inline int xue_init_xhc(struct xue *xue) +{ + uint32_t bar0; + uint64_t bar1; + uint64_t devfn; + + struct xue_ops *ops = xue->ops; + void *sys = xue->sys; + xue->xhc_cf8 = 0; + + /* + * Search PCI bus 0 for the xHC. All the host controllers supported so far + * are part of the chipset and are on bus 0. + */ + for (devfn = 0; devfn < 256; devfn++) { + uint32_t dev = (devfn & 0xF8) >> 3; + uint32_t fun = devfn & 0x07; + uint32_t cf8 = (1UL << 31) | (dev << 11) | (fun << 8); + uint32_t hdr = (xue_pci_read(xue, cf8, 3) & 0xFF0000U) >> 16; + + if (hdr == 0 || hdr == 0x80) { + if ((xue_pci_read(xue, cf8, 2) >> 8) == XUE_XHC_CLASSC) { + xue->xhc_cf8 = cf8; + break; + } + } + } + + if (!xue->xhc_cf8) { + xue_error("Compatible xHC not found on bus 0\n"); + return 0; + } + + /* ...we found it, so parse the BAR and map the registers */ + bar0 = xue_pci_read(xue, xue->xhc_cf8, 4); + bar1 = xue_pci_read(xue, xue->xhc_cf8, 5); + + /* IO BARs not allowed; BAR must be 64-bit */ + if ((bar0 & 0x1) != 0 || ((bar0 & 0x6) >> 1) != 2) { + return 0; + } + + xue_pci_write(xue, xue->xhc_cf8, 4, 0xFFFFFFFF); + xue->xhc_mmio_size = ~(xue_pci_read(xue, xue->xhc_cf8, 4) & 0xFFFFFFF0) + 1; + xue_pci_write(xue, xue->xhc_cf8, 4, bar0); + + xue->xhc_mmio_phys = (bar0 & 0xFFFFFFF0) | (bar1 << 32); + xue->xhc_mmio = ops->map_xhc(sys, xue->xhc_mmio_phys, xue->xhc_mmio_size); + + return xue->xhc_mmio != NULL; +} + +/** + * The first register of the debug capability is found by traversing the + * host controller's capability list (xcap) until a capability + * with ID = 0xA is found. The xHCI capability list begins at address + * mmio + (HCCPARAMS1[31:16] << 2) + */ +static inline struct xue_dbc_reg *xue_find_dbc(struct xue *xue) +{ + uint32_t *xcap; + uint32_t next; + uint32_t id; + uint8_t *mmio = (uint8_t *)xue->xhc_mmio; + uint32_t *hccp1 = (uint32_t *)(mmio + 0x10); + const uint32_t DBC_ID = 0xA; + + /** + * Paranoid check against a zero value. The spec mandates that + * at least one "supported protocol" capability must be implemented, + * so this should always be false. + */ + if ((*hccp1 & 0xFFFF0000) == 0) { + return NULL; + } + + xcap = (uint32_t *)(mmio + (((*hccp1 & 0xFFFF0000) >> 16) << 2)); + next = (*xcap & 0xFF00) >> 8; + id = *xcap & 0xFF; + + /** + * Table 7-1 states that 'next' is relative to + * the current value of xcap and is a dword offset. + */ + while (id != DBC_ID && next) { + xcap += next; + id = *xcap & 0xFF; + next = (*xcap & 0xFF00) >> 8; + } + + if (id != DBC_ID) { + return NULL; + } + + xue->xhc_dbc_offset = (uint64_t)xcap - (uint64_t)mmio; + return (struct xue_dbc_reg *)xcap; +} + +/** + * Fields with the same interpretation for every TRB type (section 4.11.1). + * These are the fields defined in the TRB template, minus the ENT bit. That + * bit is the toggle cycle bit in link TRBs, so it shouldn't be in the + * template. + */ +static inline uint32_t xue_trb_cyc(const struct xue_trb *trb) +{ + return trb->ctrl & 0x1; +} + +static inline uint32_t xue_trb_type(const struct xue_trb *trb) +{ + return (trb->ctrl & 0xFC00) >> 10; +} + +static inline void xue_trb_set_cyc(struct xue_trb *trb, uint32_t c) +{ + trb->ctrl &= ~0x1UL; + trb->ctrl |= c; +} + +static inline void xue_trb_set_type(struct xue_trb *trb, uint32_t t) +{ + trb->ctrl &= ~0xFC00UL; + trb->ctrl |= (t << 10); +} + +/* Fields for normal TRBs */ +static inline void xue_trb_norm_set_buf(struct xue_trb *trb, uint64_t addr) +{ + trb->params = addr; +} + +static inline void xue_trb_norm_set_len(struct xue_trb *trb, uint32_t len) +{ + trb->status &= ~0x1FFFFUL; + trb->status |= len; +} + +static inline void xue_trb_norm_set_ioc(struct xue_trb *trb) +{ + trb->ctrl |= 0x20; +} + +/** + * Fields for Transfer Event TRBs (see section 6.4.2.1). Note that event + * TRBs are read-only from software + */ +static inline uint64_t xue_trb_tfre_ptr(const struct xue_trb *trb) +{ + return trb->params; +} + +static inline uint32_t xue_trb_tfre_cc(const struct xue_trb *trb) +{ + return trb->status >> 24; +} + +/* Fields for link TRBs (section 6.4.4.1) */ +static inline void xue_trb_link_set_rsp(struct xue_trb *trb, uint64_t rsp) +{ + trb->params = rsp; +} + +static inline void xue_trb_link_set_tc(struct xue_trb *trb) +{ + trb->ctrl |= 0x2; +} + +static inline void xue_trb_ring_init(const struct xue *xue, + struct xue_trb_ring *ring, int producer, + int doorbell) +{ + xue_mset(ring->trb, 0, XUE_TRB_RING_CAP * sizeof(ring->trb[0])); + + ring->enq = 0; + ring->deq = 0; + ring->cyc = 1; + ring->db = (uint8_t)doorbell; + + /* + * Producer implies transfer ring, so we have to place a + * link TRB at the end that points back to trb[0] + */ + if (producer) { + struct xue_trb *trb = &ring->trb[XUE_TRB_RING_CAP - 1]; + xue_trb_set_type(trb, xue_trb_link); + xue_trb_link_set_tc(trb); + xue_trb_link_set_rsp(trb, xue->ops->virt_to_dma(xue->sys, ring->trb)); + } +} + +static inline int xue_trb_ring_full(const struct xue_trb_ring *ring) +{ + return ((ring->enq + 1) & (XUE_TRB_RING_CAP - 1)) == ring->deq; +} + +static inline int xue_work_ring_full(const struct xue_work_ring *ring) +{ + return ((ring->enq + 1) & (XUE_WORK_RING_CAP - 1)) == ring->deq; +} + +static inline uint64_t xue_work_ring_size(const struct xue_work_ring *ring) +{ + if (ring->enq >= ring->deq) { + return ring->enq - ring->deq; + } + + return XUE_WORK_RING_CAP - ring->deq + ring->enq; +} + +static inline void xue_push_trb(struct xue *xue, struct xue_trb_ring *ring, + uint64_t dma, uint64_t len) +{ + struct xue_trb trb; + + if (ring->enq == XUE_TRB_RING_CAP - 1) { + /* + * We have to make sure the xHC processes the link TRB in order + * for wrap-around to work properly. We do this by marking the + * xHC as owner of the link TRB by setting the TRB's cycle bit + * (just like with normal TRBs). + */ + struct xue_trb *link = &ring->trb[ring->enq]; + xue_trb_set_cyc(link, ring->cyc); + + ring->enq = 0; + ring->cyc ^= 1; + } + + trb.params = 0; + trb.status = 0; + trb.ctrl = 0; + + xue_trb_set_type(&trb, xue_trb_norm); + xue_trb_set_cyc(&trb, ring->cyc); + + xue_trb_norm_set_buf(&trb, dma); + xue_trb_norm_set_len(&trb, (uint32_t)len); + xue_trb_norm_set_ioc(&trb); + + ring->trb[ring->enq++] = trb; + xue_flush_range(xue, &ring->trb[ring->enq - 1], sizeof(trb)); +} + +static inline int64_t xue_push_work(struct xue *xue, struct xue_work_ring *ring, + const char *buf, int64_t len) +{ + int64_t i = 0; + uint32_t start = ring->enq; + uint32_t end = 0; + + while (!xue_work_ring_full(ring) && i < len) { + ring->buf[ring->enq] = buf[i++]; + ring->enq = (ring->enq + 1) & (XUE_WORK_RING_CAP - 1); + } + + end = ring->enq; + + if (end > start) { + xue_flush_range(xue, &ring->buf[start], end - start); + } else if (i > 0) { + xue_flush_range(xue, &ring->buf[start], XUE_WORK_RING_CAP - start); + xue_flush_range(xue, &ring->buf[0], end); + } + + return i; +} + +/* + * Note that if IN transfer support is added, then this + * will need to be changed; it assumes an OUT transfer ring only + */ +static inline void xue_pop_events(struct xue *xue) +{ + const int trb_shift = 4; + + void *sys = xue->sys; + struct xue_ops *ops = xue->ops; + struct xue_dbc_reg *reg = xue->dbc_reg; + struct xue_trb_ring *er = &xue->dbc_ering; + struct xue_trb_ring *tr = &xue->dbc_oring; + struct xue_trb *event = &er->trb[er->deq]; + uint64_t erdp = reg->erdp; + + ops->lfence(sys); + + while (xue_trb_cyc(event) == er->cyc) { + switch (xue_trb_type(event)) { + case xue_trb_tfre: + if (xue_trb_tfre_cc(event) != xue_trb_cc_success) { + xue_alert("tfre error cc: %u\n", xue_trb_tfre_cc(event)); + break; + } + tr->deq = + (xue_trb_tfre_ptr(event) & XUE_TRB_RING_MASK) >> trb_shift; + break; + case xue_trb_psce: + reg->portsc |= (XUE_PSC_ACK_MASK & reg->portsc); + break; + default: + break; + } + + er->cyc = (er->deq == XUE_TRB_RING_CAP - 1) ? er->cyc ^ 1 : er->cyc; + er->deq = (er->deq + 1) & (XUE_TRB_RING_CAP - 1); + event = &er->trb[er->deq]; + } + + erdp &= ~XUE_TRB_RING_MASK; + erdp |= (er->deq << trb_shift); + ops->sfence(sys); + reg->erdp = erdp; +} + +/** + * xue_init_ep + * + * Initializes the endpoint as specified in sections 7.6.3.2 and 7.6.9.2. + * Each endpoint is Bulk, so the MaxPStreams, LSA, HID, CErr, FE, + * Interval, Mult, and Max ESIT Payload fields are all 0. + * + * Max packet size: 1024 + * Max burst size: debug mbs (from dbc_reg->ctrl register) + * EP type: 2 for OUT bulk, 6 for IN bulk + * TR dequeue ptr: physical base address of transfer ring + * Avg TRB length: software defined (see 4.14.1.1 for suggested defaults) + */ +static inline void xue_init_ep(uint32_t *ep, uint64_t mbs, uint32_t type, + uint64_t ring_dma) +{ + xue_mset(ep, 0, XUE_CTX_BYTES); + + ep[1] = (1024 << 16) | ((uint32_t)mbs << 8) | (type << 3); + ep[2] = (ring_dma & 0xFFFFFFFF) | 1; + ep[3] = ring_dma >> 32; + ep[4] = 3 * 1024; +} + +/* Initialize the DbC info with USB string descriptor addresses */ +static inline void xue_init_strings(struct xue *xue, uint32_t *info) +{ + uint64_t *sda; + + /* clang-format off */ + const char strings[] = { + 6, 3, 9, 0, 4, 0, + 8, 3, 'A', 0, 'I', 0, 'S', 0, + 30, 3, 'X', 0, 'u', 0, 'e', 0, ' ', 0, + 'D', 0, 'b', 0, 'C', 0, ' ', 0, + 'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, + 4, 3, '0', 0 + }; + /* clang-format on */ + + xue_mcpy(xue->dbc_str, strings, sizeof(strings)); + + sda = (uint64_t *)&info[0]; + sda[0] = xue->ops->virt_to_dma(xue->sys, xue->dbc_str); + sda[1] = sda[0] + 6; + sda[2] = sda[0] + 6 + 8; + sda[3] = sda[0] + 6 + 8 + 30; + info[8] = (4 << 24) | (30 << 16) | (8 << 8) | 6; +} + +static inline void xue_dump(struct xue *xue) +{ + struct xue_ops *op = xue->ops; + struct xue_dbc_reg *r = xue->dbc_reg; + + xue_debug("XUE DUMP:\n"); + xue_debug(" ctrl: 0x%x stat: 0x%x psc: 0x%x\n", r->ctrl, r->st, + r->portsc); + xue_debug(" id: 0x%x, db: 0x%x\n", r->id, r->db); +#if defined(__XEN__) || defined(VMM) + xue_debug(" erstsz: %u, erstba: 0x%lx\n", r->erstsz, r->erstba); + xue_debug(" erdp: 0x%lx, cp: 0x%lx\n", r->erdp, r->cp); +#else + xue_debug(" erstsz: %u, erstba: 0x%llx\n", r->erstsz, r->erstba); + xue_debug(" erdp: 0x%llx, cp: 0x%llx\n", r->erdp, r->cp); +#endif + xue_debug(" ddi1: 0x%x, ddi2: 0x%x\n", r->ddi1, r->ddi2); + xue_debug(" erstba == virt_to_dma(erst): %d\n", + r->erstba == op->virt_to_dma(xue->sys, xue->dbc_erst)); + xue_debug(" erdp == virt_to_dma(erst[0].base): %d\n", + r->erdp == xue->dbc_erst[0].base); + xue_debug(" cp == virt_to_dma(ctx): %d\n", + r->cp == op->virt_to_dma(xue->sys, xue->dbc_ctx)); +} + +static inline void xue_enable_dbc(struct xue *xue) +{ + void *sys = xue->sys; + struct xue_ops *ops = xue->ops; + struct xue_dbc_reg *reg = xue->dbc_reg; + + ops->sfence(sys); + reg->ctrl |= (1UL << XUE_CTRL_DCE); + ops->sfence(sys); + + while ((reg->ctrl & (1UL << XUE_CTRL_DCE)) == 0) { + ops->pause(sys); + } + + ops->sfence(sys); + reg->portsc |= (1UL << XUE_PSC_PED); + ops->sfence(sys); + + /* + * TODO: + * + * There is a slight difference in behavior between enabling the DbC from + * pre and post-EFI. From post-EFI, if the cable is connected when the DbC + * is enabled, the host automatically enumerates the DbC. Pre-EFI, you + * have to plug the cable in after the DCE bit is set on some systems + * for it to enumerate. + * + * I suspect the difference is due to the state of the port prior to + * initializing the DbC. Section 4.19.1.2.4.2 seems like a good place to + * start a deeper investigation into this. + */ + if (xue->sysid == xue_sysid_efi) { + xue_debug("Please insert the debug cable to continue...\n"); + } + + while ((reg->ctrl & (1UL << XUE_CTRL_DCR)) == 0) { + ops->pause(sys); + } +} + +static inline void xue_disable_dbc(struct xue *xue) +{ + void *sys = xue->sys; + struct xue_ops *ops = xue->ops; + struct xue_dbc_reg *reg = xue->dbc_reg; + + reg->portsc &= ~(1UL << XUE_PSC_PED); + ops->sfence(sys); + reg->ctrl &= ~(1UL << XUE_CTRL_DCE); + + while (reg->ctrl & (1UL << XUE_CTRL_DCE)) { + ops->pause(sys); + } +} + +static inline int xue_init_dbc(struct xue *xue) +{ + uint64_t erdp = 0; + uint64_t out = 0; + uint64_t in = 0; + uint64_t mbs = 0; + struct xue_ops *op = xue->ops; + struct xue_dbc_reg *reg = xue_find_dbc(xue); + + if (!reg) { + return 0; + } + + xue->dbc_reg = reg; + xue_disable_dbc(xue); + + xue_trb_ring_init(xue, &xue->dbc_ering, 0, XUE_DB_INVAL); + xue_trb_ring_init(xue, &xue->dbc_oring, 1, XUE_DB_OUT); + xue_trb_ring_init(xue, &xue->dbc_iring, 1, XUE_DB_IN); + + erdp = op->virt_to_dma(xue->sys, xue->dbc_ering.trb); + if (!erdp) { + return 0; + } + + xue_mset(xue->dbc_erst, 0, sizeof(*xue->dbc_erst)); + xue->dbc_erst->base = erdp; + xue->dbc_erst->size = XUE_TRB_RING_CAP; + + mbs = (reg->ctrl & 0xFF0000) >> 16; + out = op->virt_to_dma(xue->sys, xue->dbc_oring.trb); + in = op->virt_to_dma(xue->sys, xue->dbc_iring.trb); + + xue_mset(xue->dbc_ctx, 0, sizeof(*xue->dbc_ctx)); + xue_init_strings(xue, xue->dbc_ctx->info); + xue_init_ep(xue->dbc_ctx->ep_out, mbs, xue_ep_bulk_out, out); + xue_init_ep(xue->dbc_ctx->ep_in, mbs, xue_ep_bulk_in, in); + + reg->erstsz = 1; + reg->erstba = op->virt_to_dma(xue->sys, xue->dbc_erst); + reg->erdp = erdp; + reg->cp = op->virt_to_dma(xue->sys, xue->dbc_ctx); + reg->ddi1 = (XUE_DBC_VENDOR << 16) | XUE_DBC_PROTOCOL; + reg->ddi2 = XUE_DBC_PRODUCT; + + xue_flush_range(xue, xue->dbc_ctx, sizeof(*xue->dbc_ctx)); + xue_flush_range(xue, xue->dbc_erst, sizeof(*xue->dbc_erst)); + xue_flush_range(xue, xue->dbc_ering.trb, XUE_TRB_RING_BYTES); + xue_flush_range(xue, xue->dbc_oring.trb, XUE_TRB_RING_BYTES); + xue_flush_range(xue, xue->dbc_iring.trb, XUE_TRB_RING_BYTES); + xue_flush_range(xue, xue->dbc_owork.buf, XUE_WORK_RING_BYTES); + + return 1; +} + +static inline void xue_free(struct xue *xue) +{ + void *sys = xue->sys; + struct xue_ops *ops = xue->ops; + + if (!ops->free_dma) { + return; + } + + ops->free_dma(sys, xue->dbc_str, 0); + ops->free_dma(sys, xue->dbc_owork.buf, XUE_WORK_RING_ORDER); + ops->free_dma(sys, xue->dbc_iring.trb, XUE_TRB_RING_ORDER); + ops->free_dma(sys, xue->dbc_oring.trb, XUE_TRB_RING_ORDER); + ops->free_dma(sys, xue->dbc_ering.trb, XUE_TRB_RING_ORDER); + ops->free_dma(sys, xue->dbc_erst, 0); + ops->free_dma(sys, xue->dbc_ctx, 0); + xue->dma_allocated = 0; + + ops->unmap_xhc(sys, xue->xhc_mmio, xue->xhc_mmio_size); +} + +static inline int xue_alloc(struct xue *xue) +{ + void *sys = xue->sys; + struct xue_ops *ops = xue->ops; + + if (xue->dma_allocated) { + return 1; + } + + if (!ops->alloc_dma) { + return 1; + } else if (!ops->free_dma) { + return 0; + } + + xue->dbc_ctx = (struct xue_dbc_ctx *)ops->alloc_dma(sys, 0); + if (!xue->dbc_ctx) { + return 0; + } + + xue->dbc_erst = (struct xue_erst_segment *)ops->alloc_dma(sys, 0); + if (!xue->dbc_erst) { + goto free_ctx; + } + + xue->dbc_ering.trb = + (struct xue_trb *)ops->alloc_dma(sys, XUE_TRB_RING_ORDER); + if (!xue->dbc_ering.trb) { + goto free_erst; + } + + xue->dbc_oring.trb = + (struct xue_trb *)ops->alloc_dma(sys, XUE_TRB_RING_ORDER); + if (!xue->dbc_oring.trb) { + goto free_etrb; + } + + xue->dbc_iring.trb = + (struct xue_trb *)ops->alloc_dma(sys, XUE_TRB_RING_ORDER); + if (!xue->dbc_iring.trb) { + goto free_otrb; + } + + xue->dbc_owork.buf = (uint8_t *)ops->alloc_dma(sys, XUE_WORK_RING_ORDER); + if (!xue->dbc_owork.buf) { + goto free_itrb; + } + + xue->dbc_str = (char *)ops->alloc_dma(sys, 0); + if (!xue->dbc_str) { + goto free_owrk; + } + + xue->dma_allocated = 1; + return 1; + +free_owrk: + ops->free_dma(sys, xue->dbc_owork.buf, XUE_WORK_RING_ORDER); +free_itrb: + ops->free_dma(sys, xue->dbc_iring.trb, XUE_TRB_RING_ORDER); +free_otrb: + ops->free_dma(sys, xue->dbc_oring.trb, XUE_TRB_RING_ORDER); +free_etrb: + ops->free_dma(sys, xue->dbc_ering.trb, XUE_TRB_RING_ORDER); +free_erst: + ops->free_dma(sys, xue->dbc_erst, 0); +free_ctx: + ops->free_dma(sys, xue->dbc_ctx, 0); + + return 0; +} + +#define xue_set_op(op) \ + do { \ + if (!ops->op) { \ + ops->op = xue_sys_##op; \ + } \ + } while (0) + +static inline void xue_init_ops(struct xue *xue, struct xue_ops *ops) +{ + xue_set_op(init); + xue_set_op(alloc_dma); + xue_set_op(free_dma); + xue_set_op(map_xhc); + xue_set_op(unmap_xhc); + xue_set_op(outd); + xue_set_op(ind); + xue_set_op(virt_to_dma); + xue_set_op(sfence); + xue_set_op(lfence); + xue_set_op(pause); + xue_set_op(clflush); + + xue->ops = ops; +} + +static inline void xue_init_work_ring(struct xue *xue, + struct xue_work_ring *wrk) +{ + wrk->enq = 0; + wrk->deq = 0; + wrk->dma = xue->ops->virt_to_dma(xue->sys, wrk->buf); +} + +/* @endcond */ + +/** + * Initialize the DbC and enable it for transfers. First map in the DbC + * registers from the host controller's MMIO region. Then allocate and map + * DMA for the event and transfer rings. Finally, enable the DbC for + * the host to enumerate. On success, the DbC is ready to send packets. + * + * @param xue the xue to open (!= NULL) + * @param ops the xue ops to use (!= NULL) + * @param sys the system-specific data (may be NULL) + * @return 1 iff xue_open succeeded + */ +static inline int64_t xue_open(struct xue *xue, struct xue_ops *ops, void *sys) +{ + if (!xue || !ops) { + return 0; + } + + xue_init_ops(xue, ops); + xue->sys = sys; + + if (!ops->init(sys)) { + return 0; + } + + if (!xue_init_xhc(xue)) { + return 0; + } + + if (!xue_alloc(xue)) { + return 0; + } + + if (!xue_init_dbc(xue)) { + xue_free(xue); + return 0; + } + + xue_init_work_ring(xue, &xue->dbc_owork); + xue_enable_dbc(xue); + xue->open = 1; + + return 1; +} + +/** + * Commit the pending transfer TRBs to the DbC. This notifies + * the DbC of any previously-queued data on the work ring and + * rings the doorbell. + * + * @param xue the xue to flush + * @param trb the ring containing the TRBs to transfer + * @param wrk the work ring containing data to be flushed + */ +static inline void xue_flush(struct xue *xue, struct xue_trb_ring *trb, + struct xue_work_ring *wrk) +{ + struct xue_dbc_reg *reg = xue->dbc_reg; + uint32_t db = (reg->db & 0xFFFF00FF) | (trb->db << 8); + + if (xue->open && !(reg->ctrl & (1UL << XUE_CTRL_DCE))) { + if (!xue_init_dbc(xue)) { + xue_free(xue); + return; + } + + xue_init_work_ring(xue, &xue->dbc_owork); + xue_enable_dbc(xue); + } + + xue_pop_events(xue); + + if (!(reg->ctrl & (1UL << XUE_CTRL_DCR))) { + xue_error("DbC not configured"); + return; + } + + if (reg->ctrl & (1UL << XUE_CTRL_DRC)) { + reg->ctrl |= (1UL << XUE_CTRL_DRC); + reg->portsc |= (1UL << XUE_PSC_PED); + xue->ops->sfence(xue->sys); + } + + if (xue_trb_ring_full(trb)) { + return; + } + + if (wrk->enq == wrk->deq) { + return; + } else if (wrk->enq > wrk->deq) { + xue_push_trb(xue, trb, wrk->dma + wrk->deq, wrk->enq - wrk->deq); + wrk->deq = wrk->enq; + } else { + xue_push_trb(xue, trb, wrk->dma + wrk->deq, + XUE_WORK_RING_CAP - wrk->deq); + wrk->deq = 0; + if (wrk->enq > 0 && !xue_trb_ring_full(trb)) { + xue_push_trb(xue, trb, wrk->dma, wrk->enq); + wrk->deq = wrk->enq; + } + } + + xue->ops->sfence(xue->sys); + reg->db = db; +} + +/** + * Queue the data referenced by the given buffer to the DbC. A transfer TRB + * will be created and the DbC will be notified that data is available for + * writing to the debug host. + * + * @param xue the xue to write to + * @param buf the data to write + * @param size the length in bytes of buf + * @return the number of bytes written + */ +static inline int64_t xue_write(struct xue *xue, const char *buf, uint64_t size) +{ + int64_t ret; + + if (!buf || size <= 0) { + return 0; + } + + ret = xue_push_work(xue, &xue->dbc_owork, buf, size); + if (!ret) { + return 0; + } + + xue_flush(xue, &xue->dbc_oring, &xue->dbc_owork); + return ret; +} + +/** + * Queue a single character to the DbC. A transfer TRB will be created + * if the character is a newline and the DbC will be notified that data is + * available for writing to the debug host. + * + * @param xue the xue to write to + * @param c the character to write + * @return the number of bytes written + */ +static inline int64_t xue_putc(struct xue *xue, char c) +{ + if (!xue_push_work(xue, &xue->dbc_owork, &c, 1)) { + return 0; + } + + if (c == '\n') { + xue_flush(xue, &xue->dbc_oring, &xue->dbc_owork); + } + + return 1; +} + +/** + * Disable the DbC and free DMA and MMIO resources back to the host system. + * + * @param xue the xue to close + */ +static inline void xue_close(struct xue *xue) +{ + xue_disable_dbc(xue); + xue_free(xue); + xue->open = 0; +} + +#ifdef __cplusplus +} +#endif +#endif From patchwork Mon Jun 6 03:40:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= X-Patchwork-Id: 12869915 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 40E01C3F2D4 for ; Mon, 6 Jun 2022 03:41:13 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.342164.567224 (Exim 4.92) (envelope-from ) id 1ny3bk-0006Dj-76; Mon, 06 Jun 2022 03:40:48 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 342164.567224; Mon, 06 Jun 2022 03:40:48 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bk-0006Ca-1Q; Mon, 06 Jun 2022 03:40:48 +0000 Received: by outflank-mailman (input) for mailman id 342164; Mon, 06 Jun 2022 03:40:46 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bi-0006AI-Qm for xen-devel@lists.xenproject.org; Mon, 06 Jun 2022 03:40:46 +0000 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 722c1c16-e54a-11ec-b605-df0040e90b76; Mon, 06 Jun 2022 05:40:45 +0200 (CEST) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 8FFC15C00E6; Sun, 5 Jun 2022 23:40:44 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Sun, 05 Jun 2022 23:40:44 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 5 Jun 2022 23:40:43 -0400 (EDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 722c1c16-e54a-11ec-b605-df0040e90b76 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= invisiblethingslab.com; h=cc:cc:content-transfer-encoding :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm1; t=1654486844; x=1654573244; bh=eX7fSKteqe onuY94tGwQDaahOOYr2OCH2EyjM2W2Mdk=; b=RTUScW8EXvoifl2aFua3yOjN42 DoDd+q7Bz+sdizPVk8CdgetgBwlorqpm6CV4vSswMnEQt1hzdm5+XUWv8glK8aP3 jJM42MJqK7vCSCzZCH2+jXYQHgrey8hsSzmER0IAfk2XfcPCFFMaC3XJdicCk+vu u/AuWuZ+PjptqKMwm/TNd1vl3SQWBYYAsYnsElV4iKnORt6Zp+SM60R3w4zlHK4J 4mcSsDCdCo24dDP5tw8fkZcCxfxUTz+eH3M7KWl21Wiv7k6120fYrOhtzHEIIsMa 9O5WZi01vfNohSlmSJhJnOfIpjc6CfTMSZjwFXsGCiCwgQQUImmT+F9QcW/w== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1654486844; x= 1654573244; bh=eX7fSKteqeonuY94tGwQDaahOOYr2OCH2EyjM2W2Mdk=; b=q KkPMpIyBeYquR/feUT4HEvTY3j2rB4kGyEEYqK57IYMRcH7f7dy81GXY3xfzLidO lmh0Uk/Eh2RB5EJ8f1ddxmFXYKQAYBKS83l6h2Bz1y+ntSzZEKQMcTOV+KaaLlMb 1ZLnEBXvTuGxgieLWFqR9oi0cksjnZq0lIZHeKikn4NAlmDmfubAQ992ITYi9kR4 1t62rdMP6/pBC3aQksattom/OiKqzUGK1uz4GVfExyLA0Ru7GkP0mJM8s3b50ZdO Gi1C5ZPQjJZFzkJzSyTrMszNXFB+8lJQdNHbHFYXX3XkVCxhUebqnBC9b8TacEMb wYbNwCC5rLr7GJ9sH9tHg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedruddtuddgjeegucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpeforghr vghkucforghrtgiihihkohifshhkihdqifpkrhgvtghkihcuoehmrghrmhgrrhgvkhesih hnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhmqeenucggtffrrghtthgvrhhnpefg ueduhefgvdefheehudejheefudevueeghfekhfehleegveduteeuiedugffgffenucevlh hushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehmrghrmhgrrhgv khesihhnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhm X-ME-Proxy: Feedback-ID: i1568416f:Fastmail From: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= To: xen-devel@lists.xenproject.org Cc: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= , Andrew Cooper , George Dunlap , Jan Beulich , Julien Grall , Stefano Stabellini , Wei Liu Subject: [RFC PATCH 02/12] xue: annotate functions with cf_check Date: Mon, 6 Jun 2022 05:40:14 +0200 Message-Id: <7f248769d2e50077b8719f7524c607d843199951.1654486751.git-series.marmarek@invisiblethingslab.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: References: MIME-Version: 1.0 Annotate indirectly called functions for IBT. Signed-off-by: Marek Marczykowski-Górecki --- xen/drivers/char/xue.c | 12 ++++++------ xen/include/xue.h | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/xen/drivers/char/xue.c b/xen/drivers/char/xue.c index 8aefae482b71..98334090c078 100644 --- a/xen/drivers/char/xue.c +++ b/xen/drivers/char/xue.c @@ -39,7 +39,7 @@ struct xue_uart { static struct xue_uart xue_uart; static struct xue_ops xue_ops; -static void xue_uart_poll(void *data) +static void cf_check xue_uart_poll(void *data) { struct serial_port *port = data; struct xue_uart *uart = port->uart; @@ -56,13 +56,13 @@ static void xue_uart_poll(void *data) set_timer(&uart->timer, NOW() + MICROSECS(XUE_POLL_INTERVAL)); } -static void __init xue_uart_init_preirq(struct serial_port *port) +static void __init cf_check xue_uart_init_preirq(struct serial_port *port) { struct xue_uart *uart = port->uart; uart->lock = &port->tx_lock; } -static void __init xue_uart_init_postirq(struct serial_port *port) +static void __init cf_check xue_uart_init_postirq(struct serial_port *port) { struct xue_uart *uart = port->uart; @@ -71,7 +71,7 @@ static void __init xue_uart_init_postirq(struct serial_port *port) set_timer(&uart->timer, NOW() + MILLISECS(1)); } -static int xue_uart_tx_ready(struct serial_port *port) +static int cf_check xue_uart_tx_ready(struct serial_port *port) { struct xue_uart *uart = port->uart; struct xue *xue = &uart->xue; @@ -79,13 +79,13 @@ static int xue_uart_tx_ready(struct serial_port *port) return XUE_WORK_RING_CAP - xue_work_ring_size(&xue->dbc_owork); } -static void xue_uart_putc(struct serial_port *port, char c) +static void cf_check xue_uart_putc(struct serial_port *port, char c) { struct xue_uart *uart = port->uart; xue_putc(&uart->xue, c); } -static inline void xue_uart_flush(struct serial_port *port) +static inline void cf_check xue_uart_flush(struct serial_port *port) { s_time_t goal; struct xue_uart *uart = port->uart; diff --git a/xen/include/xue.h b/xen/include/xue.h index 66f7d66447f3..7515244f6af3 100644 --- a/xen/include/xue.h +++ b/xen/include/xue.h @@ -684,45 +684,45 @@ static inline void xue_sys_clflush(void *sys, void *ptr) #define xue_error(...) printk("xue error: " __VA_ARGS__) #define XUE_SYSID xue_sysid_xen -static inline int xue_sys_init(void *sys) { return 1; } -static inline void xue_sys_sfence(void *sys) { wmb(); } -static inline void xue_sys_lfence(void *sys) { rmb(); } -static inline void xue_sys_unmap_xhc(void *sys, void *virt, uint64_t count) {} -static inline void xue_sys_free_dma(void *sys, void *addr, uint64_t order) {} +static inline int cf_check xue_sys_init(void *sys) { return 1; } +static inline void cf_check xue_sys_sfence(void *sys) { wmb(); } +static inline void cf_check xue_sys_lfence(void *sys) { rmb(); } +static inline void cf_check xue_sys_unmap_xhc(void *sys, void *virt, uint64_t count) {} +static inline void cf_check xue_sys_free_dma(void *sys, void *addr, uint64_t order) {} -static inline void xue_sys_pause(void *sys) +static inline void cf_check xue_sys_pause(void *sys) { (void)sys; __asm volatile("pause" ::: "memory"); } -static inline void xue_sys_clflush(void *sys, void *ptr) +static inline void cf_check xue_sys_clflush(void *sys, void *ptr) { (void)sys; __asm volatile("clflush %0" : "+m"(*(volatile char *)ptr)); } -static inline void *xue_sys_alloc_dma(void *sys, uint64_t order) +static inline void *cf_check xue_sys_alloc_dma(void *sys, uint64_t order) { return NULL; } -static inline uint32_t xue_sys_ind(void *sys, uint32_t port) +static inline uint32_t cf_check xue_sys_ind(void *sys, uint32_t port) { return inl(port); } -static inline void xue_sys_outd(void *sys, uint32_t port, uint32_t data) +static inline void cf_check xue_sys_outd(void *sys, uint32_t port, uint32_t data) { outl(data, port); } -static inline uint64_t xue_sys_virt_to_dma(void *sys, const void *virt) +static inline uint64_t cf_check xue_sys_virt_to_dma(void *sys, const void *virt) { return virt_to_maddr(virt); } -static void *xue_sys_map_xhc(void *sys, uint64_t phys, uint64_t size) +static void *cf_check xue_sys_map_xhc(void *sys, uint64_t phys, uint64_t size) { size_t i; From patchwork Mon Jun 6 03:40:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= X-Patchwork-Id: 12869917 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4C231CCA484 for ; Mon, 6 Jun 2022 03:41:13 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.342166.567247 (Exim 4.92) (envelope-from ) id 1ny3bl-0006mP-Vr; Mon, 06 Jun 2022 03:40:49 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 342166.567247; Mon, 06 Jun 2022 03:40:49 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bl-0006lD-PR; Mon, 06 Jun 2022 03:40:49 +0000 Received: by outflank-mailman (input) for mailman id 342166; Mon, 06 Jun 2022 03:40:49 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bl-0006LY-2l for xen-devel@lists.xenproject.org; Mon, 06 Jun 2022 03:40:49 +0000 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 7311c486-e54a-11ec-bd2c-47488cf2e6aa; Mon, 06 Jun 2022 05:40:47 +0200 (CEST) Received: from compute3.internal (compute3.nyi.internal [10.202.2.43]) by mailout.nyi.internal (Postfix) with ESMTP id 17C635C0148; Sun, 5 Jun 2022 23:40:46 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute3.internal (MEProxy); Sun, 05 Jun 2022 23:40:46 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 5 Jun 2022 23:40:44 -0400 (EDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 7311c486-e54a-11ec-bd2c-47488cf2e6aa DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= invisiblethingslab.com; h=cc:cc:content-transfer-encoding :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm1; t=1654486846; x=1654573246; bh=c0cgv9w4Lg orNmNlJ07oJSahIj0+LHfl1jX6Aux8s3M=; b=Em9l1tQe6BW4ubfwuvScHVisYO NZ9juiKsdj2dzC/QD736ofHVHoXvvzcLgDRdZ5hyWnlegygzwT6Hwb/xc2zCfJTF KrWoED1p85JKkSL3Lmx6lylYJ+GPyEGtnwqqU+fJCJDo6FZ02uSerqjMIhWSmBbr Eo1HcGRmJKy9Q9IhWRk2zAZeD8vs9Bn5SBqFNMRM37nhemaHuDxdXpzqFn5uuHie ha83nwuUFaLntZkwydflYRkkC5Cw6O7sO6YM5hY8YntNdO6lLZYy7/LEUoRtlc4K 9fOCGHquDYmoQrt1Ka5b9pNc3Y5GH4Av8fTLdZPXqy0nEp/GllFHPN5FHVSA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1654486846; x= 1654573246; bh=c0cgv9w4LgorNmNlJ07oJSahIj0+LHfl1jX6Aux8s3M=; b=q DrAlhTnCMLiolvNqEwz453ubt1eiVi+e5NXTnNt+zxnxFOVRcLKbjTfjDR7G6KBH LKdKWoC1R30v6WIXQ7U1JnJN3MhNWV7c+XA+hAEcNjAheb06ch79I0om/Zx8KquH DqP4JhboHogjzNUOJ+NuPrjbpcK/19G8vYVVaPII+5dfwVI1HTisqyMQtjjcQQ0K VW4mbDE7T/Fzw4v1g/jmtTugy2MR+KfGJNggjVYM9XqclSD9zSKzpGT2xWtwKA7U uCXkfgz/2KYb0BuZsBzT/7LjViO5M1IEME115WuaYS62n4S7ezgMte6Jv972uont PPc1I3w7DU/8irBk+EVHQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedruddtuddgjeefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpeforghr vghkucforghrtgiihihkohifshhkihdqifpkrhgvtghkihcuoehmrghrmhgrrhgvkhesih hnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhmqeenucggtffrrghtthgvrhhnpefg ueduhefgvdefheehudejheefudevueeghfekhfehleegveduteeuiedugffgffenucevlh hushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehmrghrmhgrrhgv khesihhnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhm X-ME-Proxy: Feedback-ID: i1568416f:Fastmail From: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= To: xen-devel@lists.xenproject.org Cc: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= , Andrew Cooper , George Dunlap , Jan Beulich , Julien Grall , Stefano Stabellini , Wei Liu Subject: [RFC PATCH 03/12] xue: reset XHCI ports when initializing dbc Date: Mon, 6 Jun 2022 05:40:15 +0200 Message-Id: <27748e5f94769a66900697e521b35b61b1da01d8.1654486751.git-series.marmarek@invisiblethingslab.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: References: MIME-Version: 1.0 Reset ports, to force host system to re-enumerate devices. Otheriwse it will require the cable to be re-plugged, or will wait in the "configuring" state indefinitely. Trick and code copied from Linux: drivers/usb/early/xhci-dbc.c:xdbc_start()->xdbc_reset_debug_port() Signed-off-by: Marek Marczykowski-Górecki --- xen/include/xue.h | 69 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+) diff --git a/xen/include/xue.h b/xen/include/xue.h index 7515244f6af3..6048dcdd5509 100644 --- a/xen/include/xue.h +++ b/xen/include/xue.h @@ -59,6 +59,10 @@ ((1UL << XUE_PSC_CSC) | (1UL << XUE_PSC_PRC) | (1UL << XUE_PSC_PLC) | \ (1UL << XUE_PSC_CEC)) +#define XUE_XHC_EXT_PORT_MAJOR(x) (((x) >> 24) & 0xff) +#define PORT_RESET (1 << 4) +#define PORT_CONNECT (1 << 0) + static inline int known_xhc(uint32_t dev_ven) { switch (dev_ven) { @@ -1420,6 +1424,67 @@ static inline void xue_init_strings(struct xue *xue, uint32_t *info) info[8] = (4 << 24) | (30 << 16) | (8 << 8) | 6; } +static inline void xue_do_reset_debug_port(struct xue *xue, u32 id, u32 count) +{ + uint32_t *ops_reg; + uint32_t *portsc; + u32 val, cap_length; + int i; + + cap_length = (*(uint32_t*)xue->xhc_mmio) & 0xff; + ops_reg = xue->xhc_mmio + cap_length; + + id--; + for (i = id; i < (id + count); i++) { + portsc = ops_reg + 0x100 + i * 0x4; + val = *portsc; + if (!(val & PORT_CONNECT)) + *portsc = val | PORT_RESET; + } +} + + +static inline void xue_reset_debug_port(struct xue *xue) +{ + u32 val, port_offset, port_count; + uint32_t *xcap; + uint32_t next; + uint32_t id; + uint8_t *mmio = (uint8_t *)xue->xhc_mmio; + uint32_t *hccp1 = (uint32_t *)(mmio + 0x10); + const uint32_t PROTOCOL_ID = 0x2; + + /** + * Paranoid check against a zero value. The spec mandates that + * at least one "supported protocol" capability must be implemented, + * so this should always be false. + */ + if ((*hccp1 & 0xFFFF0000) == 0) { + return; + } + + xcap = (uint32_t *)(mmio + (((*hccp1 & 0xFFFF0000) >> 16) << 2)); + next = (*xcap & 0xFF00) >> 8; + id = *xcap & 0xFF; + + /* Look for "supported protocol" capability, major revision 3 */ + for (;next; xcap += next, id = *xcap & 0xFF, next = (*xcap & 0xFF00) >> 8) { + if (id != PROTOCOL_ID && next) + continue; + + if (XUE_XHC_EXT_PORT_MAJOR(*xcap) != 0x3) + continue; + + /* extract ports offset and count from the capability structure */ + val = *(xcap + 2); + port_offset = val & 0xff; + port_count = (val >> 8) & 0xff; + + /* and reset them all */ + xue_do_reset_debug_port(xue, port_offset, port_count); + } +} + static inline void xue_dump(struct xue *xue) { struct xue_ops *op = xue->ops; @@ -1459,6 +1524,10 @@ static inline void xue_enable_dbc(struct xue *xue) ops->pause(sys); } + /* reset ports on initial open, to force re-enumerating by the host */ + if (!xue->open) + xue_reset_debug_port(xue); + ops->sfence(sys); reg->portsc |= (1UL << XUE_PSC_PED); ops->sfence(sys); From patchwork Mon Jun 6 03:40:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= X-Patchwork-Id: 12869918 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 08F8BCCA485 for ; Mon, 6 Jun 2022 03:41:14 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.342167.567263 (Exim 4.92) (envelope-from ) id 1ny3bn-0007Ae-8P; Mon, 06 Jun 2022 03:40:51 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 342167.567263; Mon, 06 Jun 2022 03:40:51 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bn-00079r-3X; Mon, 06 Jun 2022 03:40:51 +0000 Received: by outflank-mailman (input) for mailman id 342167; Mon, 06 Jun 2022 03:40:49 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bl-0006LY-Kk for xen-devel@lists.xenproject.org; Mon, 06 Jun 2022 03:40:49 +0000 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 73f70345-e54a-11ec-bd2c-47488cf2e6aa; Mon, 06 Jun 2022 05:40:48 +0200 (CEST) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 971ED5C0131; Sun, 5 Jun 2022 23:40:47 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Sun, 05 Jun 2022 23:40:47 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 5 Jun 2022 23:40:46 -0400 (EDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 73f70345-e54a-11ec-bd2c-47488cf2e6aa DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= invisiblethingslab.com; h=cc:cc:content-transfer-encoding :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm1; t=1654486847; x=1654573247; bh=rjE4Ee2HRh qow39eHssjbU5ZMvphSoRBeyLy9XO4DAQ=; b=W3lXABqFbA/PUMjQFDR+An8CC5 2L7W6qsjbMmAzZ59mgo0wndLKDLuJDD0PEQQap5NqsXkm9wbKlWNDW1nx7vnkGnH JUT2G4FX5OxFPei1FMFMicEsndVO8c5cLPf2MafUr1cr5ME3smNjv+QsyeK2n/T9 YPg4CTLBR7W7jj0JaW9Br3jmczbK9GzuB2tVNTs2mge7/AU9fYQXFkNvvOEj+3eF HJ0gqj0MrJ06QHEj3gD6hs6AmxFX6KX1donKm0fzpKgy1WabZgrlcFTgNaCU/EBe U0yTWdqaWZeWuhuXdrf45+A/dp1U2w/ZeeJQp2Snyq3xuAOH2pGHlNXCQAbA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1654486847; x= 1654573247; bh=rjE4Ee2HRhqow39eHssjbU5ZMvphSoRBeyLy9XO4DAQ=; b=X 2ABJW7Je5uwXpvgr9FSrCgyORHWpdQqhgsriS4C4OEcPPdXnCBu8IoQssne1Llny uGIs9xdBN0rRaRWYMqbSTpkX+t+ZdW9V9OEpSbgEDgFlhF4MQgxru0iqcJOfiexz 4TTsdWJCpqx4QkeG1bKEF8lUi9d0/AvjUUTUt1SDW/4QOaynxCdJ1oHcTuRvn+cO NV+BaiKhpR5wTx4CImz4iXu9lav1LP2skh9C6U1r/WXRuF3sklQ8XkZQYWRUxGF/ dK9T5g4KoYuNAnzYIgGIn+Td9r7Rlr8kvGMxdb0jr6HpBs+vNlanEXuI4tU2QmAI LD5SDrVq60emRIp47ajcw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedruddtuddgjeefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpeforghr vghkucforghrtgiihihkohifshhkihdqifpkrhgvtghkihcuoehmrghrmhgrrhgvkhesih hnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhmqeenucggtffrrghtthgvrhhnpefg ueduhefgvdefheehudejheefudevueeghfekhfehleegveduteeuiedugffgffenucevlh hushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehmrghrmhgrrhgv khesihhnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhm X-ME-Proxy: Feedback-ID: i1568416f:Fastmail From: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= To: xen-devel@lists.xenproject.org Cc: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= , Andrew Cooper , George Dunlap , Jan Beulich , Julien Grall , Stefano Stabellini , Wei Liu Subject: [RFC PATCH 04/12] xue: add support for selecting specific xhci Date: Mon, 6 Jun 2022 05:40:16 +0200 Message-Id: X-Mailer: git-send-email 2.35.3 In-Reply-To: References: MIME-Version: 1.0 Handle parameters similar to dbgp=ehci. Implement this by not resettting xhc_cf8 again in xue_init_xhc(), but using a value found there if non-zero. Additionally, add xue->xhc_num to select n-th controller. Signed-off-by: Marek Marczykowski-Górecki --- docs/misc/xen-command-line.pandoc | 5 ++++- xen/drivers/char/xue.c | 17 ++++++++++++++- xen/include/xue.h | 38 +++++++++++++++++++------------- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc index 881fe409ac76..37a564c2386f 100644 --- a/docs/misc/xen-command-line.pandoc +++ b/docs/misc/xen-command-line.pandoc @@ -721,10 +721,15 @@ Available alternatives, with their meaning, are: ### dbgp > `= ehci[ | @pci:. ]` +> `= xue[ | @pci:. ]` Specify the USB controller to use, either by instance number (when going over the PCI busses sequentially) or by PCI device (must be on segment 0). +Use `ehci` for EHCI debug port, use `xue` for XHCI debug capability. +Xue driver will wait indefinitely for the debug host to connect - make sure the +cable is connected. + ### debug_stack_lines > `= ` diff --git a/xen/drivers/char/xue.c b/xen/drivers/char/xue.c index 98334090c078..632141715d4d 100644 --- a/xen/drivers/char/xue.c +++ b/xen/drivers/char/xue.c @@ -125,6 +125,7 @@ void __init xue_uart_init(void) { struct xue_uart *uart = &xue_uart; struct xue *xue = &uart->xue; + const char *e; if ( strncmp(opt_dbgp, "xue", 3) ) return; @@ -132,6 +133,22 @@ void __init xue_uart_init(void) memset(xue, 0, sizeof(*xue)); memset(&xue_ops, 0, sizeof(xue_ops)); + if ( isdigit(opt_dbgp[3]) || !opt_dbgp[3] ) + { + if ( opt_dbgp[3] ) + xue->xhc_num = simple_strtoul(opt_dbgp + 3, &e, 10); + } + else if ( strncmp(opt_dbgp + 3, "@pci", 4) == 0 ) + { + unsigned int bus, slot, func; + + e = parse_pci(opt_dbgp + 7, NULL, &bus, &slot, &func); + if ( !e || *e ) + return; + + xue->xhc_cf8 = (1UL << 31) | (bus << 16) | (slot << 11) | (func << 8); + } + xue->dbc_ctx = &ctx; xue->dbc_erst = &erst; xue->dbc_ering.trb = evt_trb; diff --git a/xen/include/xue.h b/xen/include/xue.h index 6048dcdd5509..b1f304958679 100644 --- a/xen/include/xue.h +++ b/xen/include/xue.h @@ -998,6 +998,7 @@ struct xue { int dma_allocated; int open; int sysid; + int xhc_num; /* look for n-th xhc */ }; static inline void *xue_mset(void *dest, int c, uint64_t size) @@ -1068,24 +1069,31 @@ static inline int xue_init_xhc(struct xue *xue) struct xue_ops *ops = xue->ops; void *sys = xue->sys; - xue->xhc_cf8 = 0; - /* - * Search PCI bus 0 for the xHC. All the host controllers supported so far - * are part of the chipset and are on bus 0. - */ - for (devfn = 0; devfn < 256; devfn++) { - uint32_t dev = (devfn & 0xF8) >> 3; - uint32_t fun = devfn & 0x07; - uint32_t cf8 = (1UL << 31) | (dev << 11) | (fun << 8); - uint32_t hdr = (xue_pci_read(xue, cf8, 3) & 0xFF0000U) >> 16; - - if (hdr == 0 || hdr == 0x80) { - if ((xue_pci_read(xue, cf8, 2) >> 8) == XUE_XHC_CLASSC) { - xue->xhc_cf8 = cf8; - break; + if (xue->xhc_cf8 == 0) { + /* + * Search PCI bus 0 for the xHC. All the host controllers supported so far + * are part of the chipset and are on bus 0. + */ + for (devfn = 0; devfn < 256; devfn++) { + uint32_t dev = (devfn & 0xF8) >> 3; + uint32_t fun = devfn & 0x07; + uint32_t cf8 = (1UL << 31) | (dev << 11) | (fun << 8); + uint32_t hdr = (xue_pci_read(xue, cf8, 3) & 0xFF0000U) >> 16; + + if (hdr == 0 || hdr == 0x80) { + if ((xue_pci_read(xue, cf8, 2) >> 8) == XUE_XHC_CLASSC) { + if (xue->xhc_num--) + continue; + xue->xhc_cf8 = cf8; + break; + } } } + } else { + /* Verify if selected device is really xHC */ + if ((xue_pci_read(xue, xue->xhc_cf8, 2) >> 8) != XUE_XHC_CLASSC) + xue->xhc_cf8 = 0; } if (!xue->xhc_cf8) { From patchwork Mon Jun 6 03:40:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= X-Patchwork-Id: 12869913 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 400A2CCA482 for ; Mon, 6 Jun 2022 03:41:13 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.342168.567274 (Exim 4.92) (envelope-from ) id 1ny3bo-0007T0-J5; Mon, 06 Jun 2022 03:40:52 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 342168.567274; Mon, 06 Jun 2022 03:40:52 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bo-0007S0-EO; Mon, 06 Jun 2022 03:40:52 +0000 Received: by outflank-mailman (input) for mailman id 342168; Mon, 06 Jun 2022 03:40:50 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bm-0006LY-L8 for xen-devel@lists.xenproject.org; Mon, 06 Jun 2022 03:40:50 +0000 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 74e2a6e1-e54a-11ec-bd2c-47488cf2e6aa; Mon, 06 Jun 2022 05:40:49 +0200 (CEST) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 2738F5C005B; Sun, 5 Jun 2022 23:40:49 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Sun, 05 Jun 2022 23:40:49 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 5 Jun 2022 23:40:47 -0400 (EDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 74e2a6e1-e54a-11ec-bd2c-47488cf2e6aa DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= invisiblethingslab.com; h=cc:cc:content-transfer-encoding :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm1; t=1654486849; x=1654573249; bh=U8kU4goNfn hejF90xv/RWehAvQ7mOrYaRxEFIubWjr0=; b=vKoohr+AUD15ReHYhN+5posuv8 ylsZ3vFTqlXURpzI/se+U7FhzPiVA0hqzje5Zax24fMlYfIfceiJ4o6hgyn5yZgr 6tAUlsbm4i2G0mpAAsFI5B+tiXdNu4lTYD0rY4D9yFCFoP4r3o+7lEZ1QJA6VDss 1iOeJB78rSUDqTzTT5UT9yRx6mbmyu0Yjn89HRc/BEbDMltMVV19ZpY2YsA/iOlr KtsjaiKIYDyX/SSK/ydwqa8AoEVEzF/pYXrDrYJi/cKNyPC1hdQuXSOnrAHBdxI4 yoT6HsEIetEdP3aCjrNSsrAeAEAHDMKS+GghXQGjWOHVGDTzD/2eg55jdY/g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1654486849; x= 1654573249; bh=U8kU4goNfnhejF90xv/RWehAvQ7mOrYaRxEFIubWjr0=; b=E DAJtJ0Kmuhtg3wq8osJPyguvt9sSGG4+gzZUU37svHFhYSN7eQTcx+B0Vg3WKwLn qAN5I3vEf3hHz9lWDiZSz02NHXtQokOhErVrL4F4Ey0NBjoEGhI7myzZA0GWE8sF tkxwhrA+93qLnPHHpJuJB0s4hd85A5bQfrVGYrwZzylVbV8DYGnyH+I/4I/dFv/s E5TCYvR6zSM85Vcieqlyt2lSGPvdurmIOU3i/F+HedE7qqlOMZTjNDNqxJnBDXEQ JSpzPnQaipcpLHeh9Acuv3U7etNq1P2tcZc6zMGJs3Kg/xMfyF5yN3rwLdIM4PP9 x3hW0mYdy7Ay43krr1cmw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedruddtuddgjeegucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpeforghr vghkucforghrtgiihihkohifshhkihdqifpkrhgvtghkihcuoehmrghrmhgrrhgvkhesih hnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhmqeenucggtffrrghtthgvrhhnpefg ueduhefgvdefheehudejheefudevueeghfekhfehleegveduteeuiedugffgffenucevlh hushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpehmrghrmhgrrhgv khesihhnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhm X-ME-Proxy: Feedback-ID: i1568416f:Fastmail From: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= To: xen-devel@lists.xenproject.org Cc: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= , Andrew Cooper , George Dunlap , Jan Beulich , Julien Grall , Stefano Stabellini , Wei Liu Subject: [RFC PATCH 05/12] ehci-dbgp: fix selecting n-th ehci controller Date: Mon, 6 Jun 2022 05:40:17 +0200 Message-Id: X-Mailer: git-send-email 2.35.3 In-Reply-To: References: MIME-Version: 1.0 The ehci number was parsed but ignored. Signed-off-by: Marek Marczykowski-Górecki --- xen/drivers/char/ehci-dbgp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/drivers/char/ehci-dbgp.c b/xen/drivers/char/ehci-dbgp.c index 16c8ff394d5c..92c588ec0aa3 100644 --- a/xen/drivers/char/ehci-dbgp.c +++ b/xen/drivers/char/ehci-dbgp.c @@ -1480,7 +1480,7 @@ void __init ehci_dbgp_init(void) unsigned int num = 0; if ( opt_dbgp[4] ) - simple_strtoul(opt_dbgp + 4, &e, 10); + num = simple_strtoul(opt_dbgp + 4, &e, 10); dbgp->cap = find_dbgp(dbgp, num); if ( !dbgp->cap ) From patchwork Mon Jun 6 03:40:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= X-Patchwork-Id: 12869921 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 075ABCCA487 for ; Mon, 6 Jun 2022 03:41:16 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.342169.567285 (Exim 4.92) (envelope-from ) id 1ny3bq-0007nD-Re; Mon, 06 Jun 2022 03:40:54 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 342169.567285; Mon, 06 Jun 2022 03:40:54 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bq-0007my-Nn; Mon, 06 Jun 2022 03:40:54 +0000 Received: by outflank-mailman (input) for mailman id 342169; Mon, 06 Jun 2022 03:40:52 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bo-0006AI-Cz for xen-devel@lists.xenproject.org; Mon, 06 Jun 2022 03:40:52 +0000 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 75cd1f4c-e54a-11ec-b605-df0040e90b76; Mon, 06 Jun 2022 05:40:51 +0200 (CEST) Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id A9F915C0061; Sun, 5 Jun 2022 23:40:50 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute5.internal (MEProxy); Sun, 05 Jun 2022 23:40:50 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 5 Jun 2022 23:40:49 -0400 (EDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 75cd1f4c-e54a-11ec-b605-df0040e90b76 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= invisiblethingslab.com; h=cc:cc:content-transfer-encoding :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm1; t=1654486850; x=1654573250; bh=NGSmc+qtu3 4gNopUlqM1N80pu5ni6kp1Nm5hYXfdT1w=; b=Obd1H0trnpDacJCfnGwuE/Lj6D EmLq6/S6pIRz3axGfWdZnP+tDN4tAzEKqIqHscd/W5lVhquhNznD5zEuXZDeXpgL S6053qeQOVeb5UvTeU14L580mcICg7iOr2y0ywJgNZTY0yyLBUunNmMzA8xyZSG3 kwJVS3RThqtGzvv+w3X6OeottG634ba6EIFh786yxpAoF2r20GWXwayqzXWB0/ZX qVGJIRHaAGHiO1y4tOfrh0AanE318hQhh50N+YVfRTBAhkg91hvjgVDzdLRw2oSL uM9j6im+VKEU5oElR+2kwvsxN3msYLNiyoMZHZzutroWb0DNAG0L836YTcTg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1654486850; x= 1654573250; bh=NGSmc+qtu34gNopUlqM1N80pu5ni6kp1Nm5hYXfdT1w=; b=o Io98yxeiOq1ZwOguKQVHDO1642SzCGnhJixkSIWE/vl+ZbS6QKvS5KXDBtrt/GUO ES/GHkLjFIsAsGS9SgsOzx2gFgPaDYEUXMCppUkRPCcCdRewm/McHnebkq639kD2 1mjeBlFknfVPJCJHcTkjLIbekbbRA2EbFmRkntW8pCPXRbgK4bMo2+baxogab5PV inozapL7dcNZIAjygrL++fMti6vjMgy7oSIXXGnZpI5+JXPSoWGa2R0CmSwgyCU6 a/vUOOKo8d8Akqzd1McgWkGE9XDfCHNFzJZlCY6gcL8//gTaN5U0Kr0HrZ8+YepR UlZndUpqIQHP3K7UxdoIw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedruddtuddgjeefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpeforghr vghkucforghrtgiihihkohifshhkihdqifpkrhgvtghkihcuoehmrghrmhgrrhgvkhesih hnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhmqeenucggtffrrghtthgvrhhnpefg ueduhefgvdefheehudejheefudevueeghfekhfehleegveduteeuiedugffgffenucevlh hushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehmrghrmhgrrhgv khesihhnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhm X-ME-Proxy: Feedback-ID: i1568416f:Fastmail From: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= To: xen-devel@lists.xenproject.org Cc: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= , Andrew Cooper , George Dunlap , Jan Beulich , Julien Grall , Stefano Stabellini , Wei Liu Subject: [RFC PATCH 06/12] console: support multiple serial console simultaneously Date: Mon, 6 Jun 2022 05:40:18 +0200 Message-Id: <0762fece2dc26ff926d92840e64ce30167cd3260.1654486751.git-series.marmarek@invisiblethingslab.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: References: MIME-Version: 1.0 Previously only one serial console was supported at the same time. Using console=com1,dbgp,vga silently ignored all but last serial console (in this case: only dbgp and vga were active). Fix this by storing not a single sercon_handle, but an array of them, up to MAX_SERCONS entries. The value of MAX_SERCONS (4) is arbitrary, inspired by the number of SERHND_IDX values. Signed-off-by: Marek Marczykowski-Górecki --- xen/drivers/char/console.c | 58 ++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index f9937c5134c0..f576cfdc3b62 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -113,7 +113,9 @@ static char *__read_mostly conring = _conring; static uint32_t __read_mostly conring_size = _CONRING_SIZE; static uint32_t conringc, conringp; -static int __read_mostly sercon_handle = -1; +#define MAX_SERCONS 4 +static int __read_mostly sercon_handle[MAX_SERCONS]; +static int __read_mostly nr_sercon_handle = 0; #ifdef CONFIG_X86 /* Tristate: 0 disabled, 1 user enabled, -1 default enabled */ @@ -395,9 +397,17 @@ static unsigned int serial_rx_cons, serial_rx_prod; static void (*serial_steal_fn)(const char *, size_t nr) = early_puts; +/* Redirect any console output to *fn*, if *handle* is configured as a console. */ int console_steal(int handle, void (*fn)(const char *, size_t nr)) { - if ( (handle == -1) || (handle != sercon_handle) ) + int i; + + if ( (handle == -1) ) + return 0; + for ( i = 0; i < nr_sercon_handle; i++ ) + if ( handle == sercon_handle[i] ) + break; + if ( nr_sercon_handle && i == nr_sercon_handle ) return 0; if ( serial_steal_fn != NULL ) @@ -415,10 +425,13 @@ void console_giveback(int id) void console_serial_puts(const char *s, size_t nr) { + int i; + if ( serial_steal_fn != NULL ) serial_steal_fn(s, nr); else - serial_puts(sercon_handle, s, nr); + for ( i = 0; i < nr_sercon_handle; i++ ) + serial_puts(sercon_handle[i], s, nr); /* Copy all serial output into PV console */ pv_console_puts(s, nr); @@ -956,7 +969,7 @@ void guest_printk(const struct domain *d, const char *fmt, ...) void __init console_init_preirq(void) { char *p; - int sh; + int sh, i; serial_init_preirq(); @@ -977,7 +990,8 @@ void __init console_init_preirq(void) continue; else if ( (sh = serial_parse_handle(p)) >= 0 ) { - sercon_handle = sh; + if ( nr_sercon_handle < MAX_SERCONS ) + sercon_handle[nr_sercon_handle++] = sh; serial_steal_fn = NULL; } else @@ -996,7 +1010,8 @@ void __init console_init_preirq(void) opt_console_xen = 0; #endif - serial_set_rx_handler(sercon_handle, serial_rx); + for ( i = 0; i < nr_sercon_handle; i++ ) + serial_set_rx_handler(sercon_handle[i], serial_rx); pv_console_set_rx_handler(serial_rx); /* HELLO WORLD --- start-of-day banner text. */ @@ -1014,7 +1029,8 @@ void __init console_init_preirq(void) if ( opt_sync_console ) { - serial_start_sync(sercon_handle); + for ( i = 0; i < nr_sercon_handle; i++ ) + serial_start_sync(sercon_handle[i]); add_taint(TAINT_SYNC_CONSOLE); printk("Console output is synchronous.\n"); warning_add(warning_sync_console); @@ -1121,13 +1137,19 @@ int __init console_has(const char *device) void console_start_log_everything(void) { - serial_start_log_everything(sercon_handle); + int i; + + for ( i = 0; i < nr_sercon_handle; i++ ) + serial_start_log_everything(sercon_handle[i]); atomic_inc(&print_everything); } void console_end_log_everything(void) { - serial_end_log_everything(sercon_handle); + int i; + + for ( i = 0; i < nr_sercon_handle; i++ ) + serial_end_log_everything(sercon_handle[i]); atomic_dec(&print_everything); } @@ -1149,23 +1171,32 @@ void console_unlock_recursive_irqrestore(unsigned long flags) void console_force_unlock(void) { + int i; + watchdog_disable(); spin_debug_disable(); spin_lock_init(&console_lock); - serial_force_unlock(sercon_handle); + for ( i = 0 ; i < nr_sercon_handle ; i++ ) + serial_force_unlock(sercon_handle[i]); console_locks_busted = 1; console_start_sync(); } void console_start_sync(void) { + int i; + atomic_inc(&print_everything); - serial_start_sync(sercon_handle); + for ( i = 0 ; i < nr_sercon_handle ; i++ ) + serial_start_sync(sercon_handle[i]); } void console_end_sync(void) { - serial_end_sync(sercon_handle); + int i; + + for ( i = 0; i < nr_sercon_handle; i++ ) + serial_end_sync(sercon_handle[i]); atomic_dec(&print_everything); } @@ -1291,7 +1322,8 @@ static int suspend_steal_id; int console_suspend(void) { - suspend_steal_id = console_steal(sercon_handle, suspend_steal_fn); + if ( nr_sercon_handle ) + suspend_steal_id = console_steal(sercon_handle[0], suspend_steal_fn); serial_suspend(); return 0; } From patchwork Mon Jun 6 03:40:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= X-Patchwork-Id: 12869916 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 43D2DCCA473 for ; Mon, 6 Jun 2022 03:41:13 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.342170.567290 (Exim 4.92) (envelope-from ) id 1ny3br-0007uf-Ih; Mon, 06 Jun 2022 03:40:55 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 342170.567290; Mon, 06 Jun 2022 03:40:55 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3br-0007td-DR; Mon, 06 Jun 2022 03:40:55 +0000 Received: by outflank-mailman (input) for mailman id 342170; Mon, 06 Jun 2022 03:40:53 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bp-0006AI-KJ for xen-devel@lists.xenproject.org; Mon, 06 Jun 2022 03:40:53 +0000 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 767fca2c-e54a-11ec-b605-df0040e90b76; Mon, 06 Jun 2022 05:40:52 +0200 (CEST) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id D2ECA5C0067; Sun, 5 Jun 2022 23:40:51 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Sun, 05 Jun 2022 23:40:51 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 5 Jun 2022 23:40:50 -0400 (EDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 767fca2c-e54a-11ec-b605-df0040e90b76 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= invisiblethingslab.com; h=cc:cc:content-transfer-encoding :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm1; t=1654486851; x=1654573251; bh=9Z09zPwAMV UfGBsTlLDLpiIwvOBt3luu8w7C4olNcaY=; b=rfKtrEAxCdTEyWbp73pYhMWN6/ 786II0vy2qb982ghSlOhqlBaiBfdCYJYHM7lo0cK4DRoSsHLQiUrNNZPOUqy4VFR qbwFZMTMjo+WphmQhUnz/kRGRp4yGzSUBGGbSuHUP2ylk0tpfcB+EVFKNvDSNhRy xEYe7WosfAUF586LGgxo24t2Qmz3cdvgClydzreRnkhodSDijzUGRwke1wQRp5kp awAkewluaX9KGPuI8q054T4xzynQyTjb+wgi4ARQXggI38aD86pEu63WaXY1STDN Gl/MQchrJepiJE/MMrvJh2ZD7Hqgc1uIMsRjbgIc2fSfWeuATXdPDV0ZhmtQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1654486851; x= 1654573251; bh=9Z09zPwAMVUfGBsTlLDLpiIwvOBt3luu8w7C4olNcaY=; b=R JvWzyPG/YtFe/BIlHdR7UejC82pvAzRXFlCROrJfOWORsaZN8fKD4iwMROYjCC3c Zo54r0ilw5MiWF6oHg1tKFc7dlmspwJOKju37OwkU9jLyTmjPQ9EuhLQE5mqKTAp aCGQXFK9OkmbL825GBaJFTalfCo7leWkituOOd9TPuw373W+bNPNQB1KWXKHKufc NkP6CqM+AeK8yKlHlUGo13nw55GbWwODYBu2S0Zu9ZHIrz9FfjSLr0d3vbFmsmJz VQU/d2DWlfyGq6cnAtXdu5xlTWs+t2Ne6DhkEgxEE2T/n6NmtDochWlBu858sSr2 zyX8sJ9JEbtGLu4J7CQiQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedruddtuddgjeegucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpeforghr vghkucforghrtgiihihkohifshhkihdqifpkrhgvtghkihcuoehmrghrmhgrrhgvkhesih hnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhmqeenucggtffrrghtthgvrhhnpefg ueduhefgvdefheehudejheefudevueeghfekhfehleegveduteeuiedugffgffenucevlh hushhtvghrufhiiigvpedvnecurfgrrhgrmhepmhgrihhlfhhrohhmpehmrghrmhgrrhgv khesihhnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhm X-ME-Proxy: Feedback-ID: i1568416f:Fastmail From: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= To: xen-devel@lists.xenproject.org Cc: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= , Jan Beulich , Paul Durrant , =?utf-8?q?Roger_Pau_Monn=C3=A9?= Subject: [RFC PATCH 07/12] IOMMU: add common API for device reserved memory Date: Mon, 6 Jun 2022 05:40:19 +0200 Message-Id: <8ba3e1cbfc7ee1d0a5da54e47f33a14c526691d3.1654486751.git-series.marmarek@invisiblethingslab.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: References: MIME-Version: 1.0 Add API similar to rmrr= and ivmd= arguments, but in a common code. This will allow drivers to register reserved memory regardless of the IOMMU vendor. The direct reason for this API is xhci-dbc console driver (aka xue), that needs to use DMA. But future change may unify command line arguments for user-supplied reserved memory, and it may be useful for other drivers in the future too. This commit just introduces an API, subsequent patches will plug it in appropriate places. The reserved memory ranges needs to be saved locally, because at the point when they are collected, Xen doesn't know yet which IOMMU driver will be used. Signed-off-by: Marek Marczykowski-Górecki --- xen/drivers/passthrough/iommu.c | 40 ++++++++++++++++++++++++++++++++++- xen/include/xen/iommu.h | 11 +++++++++- 2 files changed, 51 insertions(+) diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index 9393d987c788..5c4162912359 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -654,6 +654,46 @@ bool_t iommu_has_feature(struct domain *d, enum iommu_feature feature) return is_iommu_enabled(d) && test_bit(feature, dom_iommu(d)->features); } +#define MAX_EXTRA_RESERVED_RANGES 20 +struct extra_reserved_range { + xen_pfn_t start; + xen_ulong_t nr; + u32 sbdf; +}; +static unsigned int __initdata nr_extra_reserved_ranges; +static struct extra_reserved_range __initdata extra_reserved_ranges[MAX_EXTRA_RESERVED_RANGES]; + +int iommu_add_extra_reserved_device_memory(xen_pfn_t start, xen_ulong_t nr, u32 sbdf) +{ + unsigned int idx; + + if ( nr_extra_reserved_ranges >= MAX_EXTRA_RESERVED_RANGES ) + return -ENOMEM; + + idx = nr_extra_reserved_ranges++; + extra_reserved_ranges[idx].start = start; + extra_reserved_ranges[idx].nr = nr; + extra_reserved_ranges[idx].sbdf = sbdf; + return 0; +} + +int iommu_get_extra_reserved_device_memory(iommu_grdm_t *func, void *ctxt) +{ + unsigned int idx; + int ret; + + for ( idx = 0; idx < nr_extra_reserved_ranges; idx++ ) + { + ret = func(extra_reserved_ranges[idx].start, + extra_reserved_ranges[idx].nr, + extra_reserved_ranges[idx].sbdf, + ctxt); + if ( ret < 0 ) + return ret; + } + return 0; +} + /* * Local variables: * mode: C diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h index e0f82712ed73..97424130247c 100644 --- a/xen/include/xen/iommu.h +++ b/xen/include/xen/iommu.h @@ -296,6 +296,17 @@ struct iommu_ops { #endif }; +/* + * To be called by Xen internally, to register extra RMRR/IVMD ranges. + * Needs to be called before IOMMU initialization. + */ +extern int iommu_add_extra_reserved_device_memory(xen_pfn_t start, xen_ulong_t nr, u32 sbdf); +/* + * To be called by specific IOMMU driver during initialization, + * to fetch ranges registered with iommu_add_extra_reserved_device_memory(). + */ +extern int iommu_get_extra_reserved_device_memory(iommu_grdm_t *func, void *ctxt); + #include #ifndef iommu_call From patchwork Mon Jun 6 03:40:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= X-Patchwork-Id: 12869919 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EABF6CCA483 for ; Mon, 6 Jun 2022 03:41:13 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.342171.567297 (Exim 4.92) (envelope-from ) id 1ny3bs-00083N-Er; Mon, 06 Jun 2022 03:40:56 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 342171.567297; Mon, 06 Jun 2022 03:40:56 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bs-000812-3M; Mon, 06 Jun 2022 03:40:56 +0000 Received: by outflank-mailman (input) for mailman id 342171; Mon, 06 Jun 2022 03:40:54 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bq-0006AI-LA for xen-devel@lists.xenproject.org; Mon, 06 Jun 2022 03:40:54 +0000 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 77130317-e54a-11ec-b605-df0040e90b76; Mon, 06 Jun 2022 05:40:53 +0200 (CEST) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id CACDB5C0061; Sun, 5 Jun 2022 23:40:52 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Sun, 05 Jun 2022 23:40:52 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 5 Jun 2022 23:40:52 -0400 (EDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 77130317-e54a-11ec-b605-df0040e90b76 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= invisiblethingslab.com; h=cc:cc:content-transfer-encoding :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm1; t=1654486852; x=1654573252; bh=evEV0WFYEo SI8Y7yrgXC8kLje73u4yjd3P/XL+ndlpo=; b=jmKfYEQRXSaBoyGyjAWh8THlWt ptJbuQKMWadP1SntUcRUAnH0ThxD/Buf60iqtrgpDJIFnjaezP9eRttGoJ4J7dtD ePiadAXC0EmK4jcf3Ag4O03d1a7izzcEAzjyCSIftnGoh7T8pW2/CMSUpaifutkQ HChP6nKlgi8YwaI3hB8sQW95dtEiXTLgd7QjDeJle3zcpRfNa/7GlzOOW1PddmDI UaVpnwSR/Y9izc97VBZTalikKbKAn0/RBlAbNwFlosB+X65eOrmnmU6S29NjIYHg DcTW1EtSVdGxLUbwl/822LGZA9jS2/kky46TNuGQtlS83v1J14nY4J5mHanA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1654486852; x= 1654573252; bh=evEV0WFYEoSI8Y7yrgXC8kLje73u4yjd3P/XL+ndlpo=; b=k l2P84RsPPWV38SKsArP+1S8k4/zLT2OVCv21o7gUF4SBhe4D2yrw8RWnd94KRFTM EgFAJ1jlV5qsDKhn/YKSPYeXoOZgU3HNZBrKhvnIduwHNCEzzJ1JpFH8NQFX3FR/ cYqYW4TB8BfGkspN8aMTqjzfK3FvyDCu4DGEGNFh4Ry4Z9BxhNtX9swLlVg5aUMH OxE8hfZrHnyofFNAPN1csOH2SdZ1gueVZC3AJCrRR5DZ/FVowkTstCvwbd3fj9jf JZ3sjcrvNbFUlhmfEG3SQ/1BI9AZnbkN/dUhDpIPqeb2KTT5lMC1fhPoIqfRUCVK 8HEQV/aDa37x3LWA+xQxw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedruddtuddgjeegucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpeforghr vghkucforghrtgiihihkohifshhkihdqifpkrhgvtghkihcuoehmrghrmhgrrhgvkhesih hnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhmqeenucggtffrrghtthgvrhhnpefg ueduhefgvdefheehudejheefudevueeghfekhfehleegveduteeuiedugffgffenucevlh hushhtvghrufhiiigvpedvnecurfgrrhgrmhepmhgrihhlfhhrohhmpehmrghrmhgrrhgv khesihhnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhm X-ME-Proxy: Feedback-ID: i1568416f:Fastmail From: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= To: xen-devel@lists.xenproject.org Cc: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= , Kevin Tian Subject: [RFC PATCH 08/12] IOMMU/VT-d: wire common device reserved memory API Date: Mon, 6 Jun 2022 05:40:20 +0200 Message-Id: <386e7729069f427c537e2a59eb05f95427504e2e.1654486751.git-series.marmarek@invisiblethingslab.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: References: MIME-Version: 1.0 Re-use rmrr= parameter handling code to handle common device reserved memory. Signed-off-by: Marek Marczykowski-Górecki --- xen/drivers/passthrough/vtd/dmar.c | 201 +++++++++++++++++------------- 1 file changed, 119 insertions(+), 82 deletions(-) diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c index 367304c8739c..661a182b08d9 100644 --- a/xen/drivers/passthrough/vtd/dmar.c +++ b/xen/drivers/passthrough/vtd/dmar.c @@ -861,111 +861,148 @@ static struct user_rmrr __initdata user_rmrrs[MAX_USER_RMRR]; /* Macro for RMRR inclusive range formatting. */ #define ERMRRU_FMT "[%lx-%lx]" -#define ERMRRU_ARG(eru) eru.base_pfn, eru.end_pfn +#define ERMRRU_ARG base_pfn, end_pfn + +static int __init add_one_user_rmrr(unsigned long base_pfn, + unsigned long end_pfn, + unsigned int dev_count, + u32 *sbdf); static int __init add_user_rmrr(void) { + unsigned int i; + int ret; + + for ( i = 0; i < nr_rmrr; i++ ) + { + ret = add_one_user_rmrr(user_rmrrs[i].base_pfn, + user_rmrrs[i].end_pfn, + user_rmrrs[i].dev_count, + user_rmrrs[i].sbdf); + if ( ret < 0 ) + return ret; + } + return 0; +} + +/* Returns 1 on success, 0 when ignoring and < 0 on error. */ +static int __init add_one_user_rmrr(unsigned long base_pfn, + unsigned long end_pfn, + unsigned int dev_count, + u32 *sbdf) +{ struct acpi_rmrr_unit *rmrr, *rmrru; - unsigned int idx, seg, i; - unsigned long base, end; + unsigned int idx, seg; + unsigned long base_iter; bool overlap; - for ( i = 0; i < nr_rmrr; i++ ) + if ( iommu_verbose ) + printk(XENLOG_DEBUG VTDPREFIX + "Adding RMRR for %d device ([0]: %#x) range "ERMRRU_FMT"\n", + dev_count, sbdf[0], ERMRRU_ARG); + + if ( base_pfn > end_pfn ) + { + printk(XENLOG_ERR VTDPREFIX + "Invalid RMRR Range "ERMRRU_FMT"\n", + ERMRRU_ARG); + return 0; + } + + if ( (end_pfn - base_pfn) >= MAX_USER_RMRR_PAGES ) { - base = user_rmrrs[i].base_pfn; - end = user_rmrrs[i].end_pfn; + printk(XENLOG_ERR VTDPREFIX + "RMRR range "ERMRRU_FMT" exceeds "\ + __stringify(MAX_USER_RMRR_PAGES)" pages\n", + ERMRRU_ARG); + return 0; + } - if ( base > end ) + overlap = false; + list_for_each_entry(rmrru, &acpi_rmrr_units, list) + { + if ( pfn_to_paddr(base_pfn) <= rmrru->end_address && + rmrru->base_address <= pfn_to_paddr(end_pfn) ) { printk(XENLOG_ERR VTDPREFIX - "Invalid RMRR Range "ERMRRU_FMT"\n", - ERMRRU_ARG(user_rmrrs[i])); - continue; + "Overlapping RMRRs: "ERMRRU_FMT" and [%lx-%lx]\n", + ERMRRU_ARG, + paddr_to_pfn(rmrru->base_address), + paddr_to_pfn(rmrru->end_address)); + overlap = true; + break; } + } + /* Don't add overlapping RMRR. */ + if ( overlap ) + return 0; - if ( (end - base) >= MAX_USER_RMRR_PAGES ) + base_iter = base_pfn; + do + { + if ( !mfn_valid(_mfn(base_iter)) ) { printk(XENLOG_ERR VTDPREFIX - "RMRR range "ERMRRU_FMT" exceeds "\ - __stringify(MAX_USER_RMRR_PAGES)" pages\n", - ERMRRU_ARG(user_rmrrs[i])); - continue; + "Invalid pfn in RMRR range "ERMRRU_FMT"\n", + ERMRRU_ARG); + break; } + } while ( base_iter++ < end_pfn ); - overlap = false; - list_for_each_entry(rmrru, &acpi_rmrr_units, list) - { - if ( pfn_to_paddr(base) <= rmrru->end_address && - rmrru->base_address <= pfn_to_paddr(end) ) - { - printk(XENLOG_ERR VTDPREFIX - "Overlapping RMRRs: "ERMRRU_FMT" and [%lx-%lx]\n", - ERMRRU_ARG(user_rmrrs[i]), - paddr_to_pfn(rmrru->base_address), - paddr_to_pfn(rmrru->end_address)); - overlap = true; - break; - } - } - /* Don't add overlapping RMRR. */ - if ( overlap ) - continue; + /* Invalid pfn in range as the loop ended before end_pfn was reached. */ + if ( base_iter <= end_pfn ) + return 0; - do - { - if ( !mfn_valid(_mfn(base)) ) - { - printk(XENLOG_ERR VTDPREFIX - "Invalid pfn in RMRR range "ERMRRU_FMT"\n", - ERMRRU_ARG(user_rmrrs[i])); - break; - } - } while ( base++ < end ); + rmrr = xzalloc(struct acpi_rmrr_unit); + if ( !rmrr ) + return -ENOMEM; - /* Invalid pfn in range as the loop ended before end_pfn was reached. */ - if ( base <= end ) - continue; + rmrr->scope.devices = xmalloc_array(u16, dev_count); + if ( !rmrr->scope.devices ) + { + xfree(rmrr); + return -ENOMEM; + } - rmrr = xzalloc(struct acpi_rmrr_unit); - if ( !rmrr ) - return -ENOMEM; + seg = 0; + for ( idx = 0; idx < dev_count; idx++ ) + { + rmrr->scope.devices[idx] = sbdf[idx]; + seg |= PCI_SEG(sbdf[idx]); + } + if ( seg != PCI_SEG(sbdf[0]) ) + { + printk(XENLOG_ERR VTDPREFIX + "Segments are not equal for RMRR range "ERMRRU_FMT"\n", + ERMRRU_ARG); + scope_devices_free(&rmrr->scope); + xfree(rmrr); + return 0; + } - rmrr->scope.devices = xmalloc_array(u16, user_rmrrs[i].dev_count); - if ( !rmrr->scope.devices ) - { - xfree(rmrr); - return -ENOMEM; - } + rmrr->segment = seg; + rmrr->base_address = pfn_to_paddr(base_pfn); + /* Align the end_address to the end of the page */ + rmrr->end_address = pfn_to_paddr(end_pfn) | ~PAGE_MASK; + rmrr->scope.devices_cnt = dev_count; - seg = 0; - for ( idx = 0; idx < user_rmrrs[i].dev_count; idx++ ) - { - rmrr->scope.devices[idx] = user_rmrrs[i].sbdf[idx]; - seg |= PCI_SEG(user_rmrrs[i].sbdf[idx]); - } - if ( seg != PCI_SEG(user_rmrrs[i].sbdf[0]) ) - { - printk(XENLOG_ERR VTDPREFIX - "Segments are not equal for RMRR range "ERMRRU_FMT"\n", - ERMRRU_ARG(user_rmrrs[i])); - scope_devices_free(&rmrr->scope); - xfree(rmrr); - continue; - } + if ( register_one_rmrr(rmrr) ) + printk(XENLOG_ERR VTDPREFIX + "Could not register RMMR range "ERMRRU_FMT"\n", + ERMRRU_ARG); - rmrr->segment = seg; - rmrr->base_address = pfn_to_paddr(user_rmrrs[i].base_pfn); - /* Align the end_address to the end of the page */ - rmrr->end_address = pfn_to_paddr(user_rmrrs[i].end_pfn) | ~PAGE_MASK; - rmrr->scope.devices_cnt = user_rmrrs[i].dev_count; + return 1; +} - if ( register_one_rmrr(rmrr) ) - printk(XENLOG_ERR VTDPREFIX - "Could not register RMMR range "ERMRRU_FMT"\n", - ERMRRU_ARG(user_rmrrs[i])); - } +static int __init cf_check add_one_extra_rmrr(xen_pfn_t start, xen_ulong_t nr, u32 id, void *ctxt) +{ + u32 sbdf_array[] = { id }; + return add_one_user_rmrr(start, start+nr, 1, sbdf_array); +} - return 0; +static int __init add_extra_rmrr(void) +{ + return iommu_get_extra_reserved_device_memory(add_one_extra_rmrr, NULL); } #include @@ -1010,7 +1047,7 @@ int __init acpi_dmar_init(void) { iommu_init_ops = &intel_iommu_init_ops; - return add_user_rmrr(); + return add_user_rmrr() || add_extra_rmrr(); } return ret; From patchwork Mon Jun 6 03:40:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= X-Patchwork-Id: 12869911 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3286CC433EF for ; Mon, 6 Jun 2022 03:41:13 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.342172.567305 (Exim 4.92) (envelope-from ) id 1ny3bt-0008CO-6u; Mon, 06 Jun 2022 03:40:57 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 342172.567305; Mon, 06 Jun 2022 03:40:57 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bs-00089i-RS; Mon, 06 Jun 2022 03:40:56 +0000 Received: by outflank-mailman (input) for mailman id 342172; Mon, 06 Jun 2022 03:40:55 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3br-0006AI-EP for xen-devel@lists.xenproject.org; Mon, 06 Jun 2022 03:40:55 +0000 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 77b6ac07-e54a-11ec-b605-df0040e90b76; Mon, 06 Jun 2022 05:40:54 +0200 (CEST) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id DC8F55C0092; Sun, 5 Jun 2022 23:40:53 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Sun, 05 Jun 2022 23:40:53 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 5 Jun 2022 23:40:52 -0400 (EDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 77b6ac07-e54a-11ec-b605-df0040e90b76 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= invisiblethingslab.com; h=cc:cc:content-transfer-encoding :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm1; t=1654486853; x=1654573253; bh=A6IUb5PhcA I6HvRB0V+hA466Exyej9hEMYg/SSDCyCk=; b=JMETKEtYs3QGO3ansj1uSe4kBc HWOucFNHxq5QDlAgtlc95WNZ9eSQjz4xzlbOzRKO9ZsQtIsYwQRzGQLUcmKFGQZ8 sALDkfuN1/MDvBKuMaAqU19kgN+W6FpOnOtHAIheLY2Rsh+SkKW/aCcTYyVW5nr2 rDs0UzvfDow7TxbSjNK1k/k59rxTa6SNryHwKoEQVPZljEM2omduu5eBPvIb1NrT 3twJ8H5Qmy+ZcbgAGyLW43MWUep8lJjQHLJxWnaC7T25JBxEyv4axqDoxbz90Inc 6lIsv+acUCl/jyBACLdkome3zJtqrpVPFG3c3KFAeO3GWv5LYcV92k48GCfQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1654486853; x= 1654573253; bh=A6IUb5PhcAI6HvRB0V+hA466Exyej9hEMYg/SSDCyCk=; b=H as4gHtuzhsetWd9GSU457Un5devnnoow7tHZSR5crfCyWz6bzWK6/+suTYMoYAN4 XJk8ddBrvtL97myk1FV3M7v5K7DRL1TEyQyq4bafwFZ3f3qGn/IS4Awwq75BupoA va5SMTi9PuBZCUNwPKLcCE/xWVTbdiDEv8BXjKpnV0iPv8sLBLi9G5W1pJP+nxCa wZuMwse9RbUDRTTZTiIobete1YH98h3x2pfXezHQU2LqlplbpwaugfATP04fCb+A FyVxOcd4U3ULZrNFM0sQjNTIKVsZixafcpTWT1MVkTYfr2WKb9eWOCJLn331AnM4 siGtkD5fT5B23ksyg9DhQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedruddtuddgjeefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpeforghr vghkucforghrtgiihihkohifshhkihdqifpkrhgvtghkihcuoehmrghrmhgrrhgvkhesih hnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhmqeenucggtffrrghtthgvrhhnpefg ueduhefgvdefheehudejheefudevueeghfekhfehleegveduteeuiedugffgffenucevlh hushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehmrghrmhgrrhgv khesihhnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhm X-ME-Proxy: Feedback-ID: i1568416f:Fastmail From: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= To: xen-devel@lists.xenproject.org Cc: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= , Jan Beulich , Andrew Cooper Subject: [RFC PATCH 09/12] IOMMU/AMD: wire common device reserved memory API Date: Mon, 6 Jun 2022 05:40:21 +0200 Message-Id: X-Mailer: git-send-email 2.35.3 In-Reply-To: References: MIME-Version: 1.0 Register common device reserved memory similar to how ivmd= parameter is handled. Signed-off-by: Marek Marczykowski-Górecki --- xen/drivers/passthrough/amd/iommu_acpi.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/xen/drivers/passthrough/amd/iommu_acpi.c b/xen/drivers/passthrough/amd/iommu_acpi.c index ac6835225bae..2a4896c05442 100644 --- a/xen/drivers/passthrough/amd/iommu_acpi.c +++ b/xen/drivers/passthrough/amd/iommu_acpi.c @@ -1078,6 +1078,20 @@ static inline bool_t is_ivmd_block(u8 type) type == ACPI_IVRS_TYPE_MEMORY_IOMMU); } +static int __init cf_check add_one_extra_ivmd(xen_pfn_t start, xen_ulong_t nr, u32 id, void *ctxt) +{ + struct acpi_ivrs_memory ivmd; + + ivmd.start_address = start << PAGE_SHIFT; + ivmd.memory_length = nr << PAGE_SHIFT; + ivmd.header.flags = ACPI_IVMD_UNITY | + ACPI_IVMD_READ | ACPI_IVMD_WRITE; + ivmd.header.length = sizeof(ivmd); + ivmd.header.device_id = id; + ivmd.header.type = ACPI_IVRS_TYPE_MEMORY_ONE; + return parse_ivmd_block(&ivmd); +} + static int __init cf_check parse_ivrs_table(struct acpi_table_header *table) { const struct acpi_ivrs_header *ivrs_block; @@ -1121,6 +1135,8 @@ static int __init cf_check parse_ivrs_table(struct acpi_table_header *table) AMD_IOMMU_DEBUG("IVMD: %u command line provided entries\n", nr_ivmd); for ( i = 0; !error && i < nr_ivmd; ++i ) error = parse_ivmd_block(user_ivmds + i); + if ( !error ) + error = iommu_get_extra_reserved_device_memory(add_one_extra_ivmd, NULL); /* Each IO-APIC must have been mentioned in the table. */ for ( apic = 0; !error && iommu_intremap && apic < nr_ioapics; ++apic ) From patchwork Mon Jun 6 03:40:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= X-Patchwork-Id: 12869912 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E6C37C43334 for ; Mon, 6 Jun 2022 03:41:12 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.342173.567318 (Exim 4.92) (envelope-from ) id 1ny3bu-0000H5-VB; Mon, 06 Jun 2022 03:40:58 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 342173.567318; Mon, 06 Jun 2022 03:40:58 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bu-0000EZ-Nc; Mon, 06 Jun 2022 03:40:58 +0000 Received: by outflank-mailman (input) for mailman id 342173; Mon, 06 Jun 2022 03:40:57 +0000 Received: from se1-gles-sth1-in.inumbo.com ([159.253.27.254] helo=se1-gles-sth1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bt-0006LY-6L for xen-devel@lists.xenproject.org; Mon, 06 Jun 2022 03:40:57 +0000 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by se1-gles-sth1.inumbo.com (Halon) with ESMTPS id 78aa8a0a-e54a-11ec-bd2c-47488cf2e6aa; Mon, 06 Jun 2022 05:40:56 +0200 (CEST) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id 7A3D45C00B0; Sun, 5 Jun 2022 23:40:55 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Sun, 05 Jun 2022 23:40:55 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 5 Jun 2022 23:40:54 -0400 (EDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 78aa8a0a-e54a-11ec-bd2c-47488cf2e6aa DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= invisiblethingslab.com; h=cc:cc:content-transfer-encoding :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm1; t=1654486855; x=1654573255; bh=GtGzwElcnt Lkp+5KlVnKOJoP8pGSO5IG2VUoVVDwK7c=; b=Bg0fF7DTBeCgzVA0LNP6vSeH1Q 1OB5C3aTEjXpNqmG+oYnnLfamf2ZaaicKWuv7EM+8lYxq8k268pCfe+L27oEXpgu whbDko5RJBACdRywSdg8oxvXnqSJnLfcSqZc8wmEsEPJbcyndLjcdKmtfJhzOMHj cOoAp8WnGms8//keHBb9gwZ5HTgF3M4RCh1P7ywj/Ze7YOf7cDCZbJVtw8RBMvV9 sHwMC88QUJuHcJxUX/GZRocP0qBk+IbrdFYPbtka2RBVlWv/sbAiD7QR3BKMQZGZ l17Lp9Z8AA5101ExmYk121SNjAotISU68k95kjAmCYXu+S2w2/t9q6yV2wgg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1654486855; x= 1654573255; bh=GtGzwElcntLkp+5KlVnKOJoP8pGSO5IG2VUoVVDwK7c=; b=K bZgKOu3WOFZ5Zhqjrv+muQsi/hcSa6CrxOO1wYyqaEzQ8gtdQwFtE/0z1nhMVXcC TjXrReM6re8Z9SJA9C2M349Bsh+MmOlZDz0PEciHNl4Ta11ExcWvqS8ExIVmiQTp XIuCuy7n1/mwg0HDBa2nhKZZsxW6DIDX9wCquZuuPdEI6cfBkGZ/MEQXYOrww9kk IGoysPSVrVOC/3KQ+DcMcRT3mqOfmo5mlKNrJy2STWc+qCctvMlI573otSEOaz0s YtzcnvhECXyGaEGffqUqdmCLDuSL/nv3VniEZM+QtWg4TlWTlwFccXGz109e7jj6 J8a5yS2H/Wkwk6G0+DygQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedruddtuddgjeegucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpeforghr vghkucforghrtgiihihkohifshhkihdqifpkrhgvtghkihcuoehmrghrmhgrrhgvkhesih hnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhmqeenucggtffrrghtthgvrhhnpefg ueduhefgvdefheehudejheefudevueeghfekhfehleegveduteeuiedugffgffenucevlh hushhtvghrufhiiigvpedvnecurfgrrhgrmhepmhgrihhlfhhrohhmpehmrghrmhgrrhgv khesihhnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhm X-ME-Proxy: Feedback-ID: i1568416f:Fastmail From: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= To: xen-devel@lists.xenproject.org Cc: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= , Andrew Cooper , George Dunlap , Jan Beulich , Julien Grall , Stefano Stabellini , Wei Liu , Kevin Tian Subject: [RFC PATCH 10/12] xue: mark DMA buffers as reserved for the device Date: Mon, 6 Jun 2022 05:40:22 +0200 Message-Id: <2080c30addd42a0a6d72c4608da54cbc3fe2d860.1654486751.git-series.marmarek@invisiblethingslab.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: References: MIME-Version: 1.0 The important part is to include those buffers in IOMMU page table relevant for the USB controller. Otherwise, DbC will stop working as soon as IOMMU is enabled, regardless of to which domain device assigned (be it xen or dom0). If the device is passed through to dom0 or other domain (see later patches), that domain will effectively have access to those buffers too. It does give such domain yet another way to DoS the system (as is the case when having PCI device assigned already), but also possibly steal the console ring content. Thus, such domain should be a trusted one. In any case, prevent anything else being placed on those pages by adding artificial padding. Signed-off-by: Marek Marczykowski-Górecki --- xen/drivers/char/xue.c | 46 ++++++++++++++++++++----------- xen/drivers/passthrough/vtd/dmar.c | 2 +- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/xen/drivers/char/xue.c b/xen/drivers/char/xue.c index 632141715d4d..8863b996c619 100644 --- a/xen/drivers/char/xue.c +++ b/xen/drivers/char/xue.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #define XUE_POLL_INTERVAL 100 /* us */ @@ -110,13 +111,21 @@ static struct uart_driver xue_uart_driver = { .getc = NULL }; -static struct xue_trb evt_trb[XUE_TRB_RING_CAP] __aligned(XUE_PAGE_SIZE); -static struct xue_trb out_trb[XUE_TRB_RING_CAP] __aligned(XUE_PAGE_SIZE); -static struct xue_trb in_trb[XUE_TRB_RING_CAP] __aligned(XUE_PAGE_SIZE); -static struct xue_erst_segment erst __aligned(64); -static struct xue_dbc_ctx ctx __aligned(64); -static uint8_t wrk_buf[XUE_WORK_RING_CAP] __aligned(XUE_PAGE_SIZE); -static char str_buf[XUE_PAGE_SIZE] __aligned(64); +struct xue_dma_bufs { + struct xue_trb evt_trb[XUE_TRB_RING_CAP] __aligned(XUE_PAGE_SIZE); + struct xue_trb out_trb[XUE_TRB_RING_CAP] __aligned(XUE_PAGE_SIZE); + struct xue_trb in_trb[XUE_TRB_RING_CAP] __aligned(XUE_PAGE_SIZE); + struct xue_erst_segment erst __aligned(64); + struct xue_dbc_ctx ctx __aligned(64); + uint8_t wrk_buf[XUE_WORK_RING_CAP] __aligned(XUE_PAGE_SIZE); + char str_buf[XUE_PAGE_SIZE] __aligned(64); + /* + * Don't place anything else on this page - it will be + * DMA-reachable by the USB controller. + */ + char _pad[0] __aligned(XUE_PAGE_SIZE); +}; +static struct xue_dma_bufs xue_dma_bufs __aligned(XUE_PAGE_SIZE); static char __initdata opt_dbgp[30]; string_param("dbgp", opt_dbgp); @@ -149,17 +158,24 @@ void __init xue_uart_init(void) xue->xhc_cf8 = (1UL << 31) | (bus << 16) | (slot << 11) | (func << 8); } - xue->dbc_ctx = &ctx; - xue->dbc_erst = &erst; - xue->dbc_ering.trb = evt_trb; - xue->dbc_oring.trb = out_trb; - xue->dbc_iring.trb = in_trb; - xue->dbc_owork.buf = wrk_buf; - xue->dbc_str = str_buf; + + xue->dbc_ctx = &xue_dma_bufs.ctx; + xue->dbc_erst = &xue_dma_bufs.erst; + xue->dbc_ering.trb = xue_dma_bufs.evt_trb; + xue->dbc_oring.trb = xue_dma_bufs.out_trb; + xue->dbc_iring.trb = xue_dma_bufs.in_trb; + xue->dbc_owork.buf = xue_dma_bufs.wrk_buf; + xue->dbc_str = xue_dma_bufs.str_buf; xue->dma_allocated = 1; xue->sysid = xue_sysid_xen; - xue_open(xue, &xue_ops, NULL); + if (xue_open(xue, &xue_ops, NULL)) + { + iommu_add_extra_reserved_device_memory( + PFN_DOWN(virt_to_maddr(&xue_dma_bufs)), + PFN_UP(sizeof(xue_dma_bufs)), + (uart->xue.xhc_cf8 >> 8) & 0xffff); + } serial_register_uart(SERHND_DBGP, &xue_uart_driver, &xue_uart); } diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c index 661a182b08d9..2caa3e9ad1b0 100644 --- a/xen/drivers/passthrough/vtd/dmar.c +++ b/xen/drivers/passthrough/vtd/dmar.c @@ -845,7 +845,7 @@ out: return ret; } -#define MAX_USER_RMRR_PAGES 16 +#define MAX_USER_RMRR_PAGES 64 #define MAX_USER_RMRR 10 /* RMRR units derived from command line rmrr option. */ From patchwork Mon Jun 6 03:40:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= X-Patchwork-Id: 12869914 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 36737CCA47F for ; Mon, 6 Jun 2022 03:41:13 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.342174.567335 (Exim 4.92) (envelope-from ) id 1ny3bx-0000md-5C; Mon, 06 Jun 2022 03:41:01 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 342174.567335; Mon, 06 Jun 2022 03:41:01 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bw-0000iw-ND; Mon, 06 Jun 2022 03:41:00 +0000 Received: by outflank-mailman (input) for mailman id 342174; Mon, 06 Jun 2022 03:40:58 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bu-0006AI-L9 for xen-devel@lists.xenproject.org; Mon, 06 Jun 2022 03:40:58 +0000 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 7999dc07-e54a-11ec-b605-df0040e90b76; Mon, 06 Jun 2022 05:40:57 +0200 (CEST) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 0D5C45C009E; Sun, 5 Jun 2022 23:40:57 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Sun, 05 Jun 2022 23:40:57 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 5 Jun 2022 23:40:55 -0400 (EDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 7999dc07-e54a-11ec-b605-df0040e90b76 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= invisiblethingslab.com; h=cc:cc:content-transfer-encoding :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm1; t=1654486857; x=1654573257; bh=CJWHUy2VWq xW/8CRCgMpeNzBJIn8oo40U2Dyt2b4CbY=; b=cbiGlQRAPePlltHvsM0totHwde mQgxKBrEQIYBdnaLgbZTwEBcaVF00/5RSMlM3pwDjpagnY2htyg0s+bcgvV9Ezkm /T9/p/IQnLOoOuThbgBEcexfysh05byebCgqkROmb7ilaOUxmDExJ9cx4JLftnBa tynWvL1cV52Xh/dGPChY9d5REvIiIDaDkG8h3VNttXMZd+t0QfN9sjFTy5ovLZHX XPHfxQJiDTRCbgjKolXQ37pZimlsB9MNLb75oiwmxBy6tXAe2Rnsxb/40eh1nwpf u+gf0b0clblWPqhAmXV2n/euYLdfVjtrntxMVbd20x47RoJAV12vEZCxsRWQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1654486857; x= 1654573257; bh=CJWHUy2VWqxW/8CRCgMpeNzBJIn8oo40U2Dyt2b4CbY=; b=S is+XW1FcqbLf61YDtDrxLIWBV+PynaefCYM3lTuYwR/KqA4AeQGPSLammQU4BTMx ReDxr94nAgQ1HrPlbIsvn5oNRv3wJRwOYKzUTNe3wu7NbMwQ3aQYo00spND0o+Cl h+wC3jebG6HUUJ+RI5sujOw5SAdfASpYwQKuYcOCDvc5Zx6Yh3/5K2fdWi69rMaP Xa5x03kHSMZnDsslalwZHGmwt1ro65BW9t3E4Y4XodaXyksRXF70E7Y9oIfrdHr4 EV5WE99XaMam6TrsDWOGNp0/tH5+HXK4n28BuJLLh2oP30jRaWGpn47bNZx/YxFa 6xcZLM/NHJ8049V/szPaQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedruddtuddgjeefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpeforghr vghkucforghrtgiihihkohifshhkihdqifpkrhgvtghkihcuoehmrghrmhgrrhgvkhesih hnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhmqeenucggtffrrghtthgvrhhnpefg ueduhefgvdefheehudejheefudevueeghfekhfehleegveduteeuiedugffgffenucevlh hushhtvghrufhiiigvpedunecurfgrrhgrmhepmhgrihhlfhhrohhmpehmrghrmhgrrhgv khesihhnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhm X-ME-Proxy: Feedback-ID: i1568416f:Fastmail From: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= To: xen-devel@lists.xenproject.org Cc: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= , Andrew Cooper , George Dunlap , Jan Beulich , Julien Grall , Stefano Stabellini , Wei Liu Subject: [RFC PATCH 11/12] xue: prevent dom0 (or other domain) from using the device Date: Mon, 6 Jun 2022 05:40:23 +0200 Message-Id: <74ffafdaa109f6067f2ecbc89b885a8a9cdbadaf.1654486751.git-series.marmarek@invisiblethingslab.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: References: MIME-Version: 1.0 Mark config space of the device as read-only, to prevent dom0 (or others) re-configuring the USB controller while it's used as a debug console. This isn't strictly necessary, as the xhci and xhci-dbc drivers can co-exists, but that's a simpler option. Signed-off-by: Marek Marczykowski-Górecki --- xen/drivers/char/xue.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/xen/drivers/char/xue.c b/xen/drivers/char/xue.c index 8863b996c619..ff62b868e906 100644 --- a/xen/drivers/char/xue.c +++ b/xen/drivers/char/xue.c @@ -70,6 +70,13 @@ static void __init cf_check xue_uart_init_postirq(struct serial_port *port) serial_async_transmit(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); } static int cf_check xue_uart_tx_ready(struct serial_port *port) From patchwork Mon Jun 6 03:40:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= X-Patchwork-Id: 12869922 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BEAA9C43334 for ; Mon, 6 Jun 2022 03:41:15 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.342177.567346 (Exim 4.92) (envelope-from ) id 1ny3by-00014j-TG; Mon, 06 Jun 2022 03:41:02 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 342177.567346; Mon, 06 Jun 2022 03:41:02 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3by-00013b-EM; Mon, 06 Jun 2022 03:41:02 +0000 Received: by outflank-mailman (input) for mailman id 342177; Mon, 06 Jun 2022 03:41:00 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1ny3bw-0006AI-69 for xen-devel@lists.xenproject.org; Mon, 06 Jun 2022 03:41:00 +0000 Received: from out4-smtp.messagingengine.com (out4-smtp.messagingengine.com [66.111.4.28]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 7a80778f-e54a-11ec-b605-df0040e90b76; Mon, 06 Jun 2022 05:40:59 +0200 (CEST) Received: from compute1.internal (compute1.nyi.internal [10.202.2.41]) by mailout.nyi.internal (Postfix) with ESMTP id 8D86E5C00D9; Sun, 5 Jun 2022 23:40:58 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute1.internal (MEProxy); Sun, 05 Jun 2022 23:40:58 -0400 Received: by mail.messagingengine.com (Postfix) with ESMTPA; Sun, 5 Jun 2022 23:40:57 -0400 (EDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 7a80778f-e54a-11ec-b605-df0040e90b76 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= invisiblethingslab.com; h=cc:cc:content-transfer-encoding :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm1; t=1654486858; x=1654573258; bh=Ul/YTZELjd XhM4yte1+Tqag6FgjJfdtEGmy0W8pthfU=; b=ODhMNVSmVnU+BovLPcl9pPwYol vgV/TPSH8AnyApCoRV37VwaQBaTdew7GP5M3kL7Vgj23TjpnM6f9cvuBPgUBSDY/ AUHh/R8HqIRw1IY8xqxM4s4DswLhOJxne8V65TvrVOTF6dYwm598m8p/yNN/LgfK NZaxJocsBshN8IJ+n7YJY43teIoW6gRKGsu/mXmZZyJ1u+ffO3ZWUcGHBw+mL/Ht 3YW8cAVDMsrbVEL14J2upacDPWqexqz7vBheU468FlnB0dJzsXEaUYFqFJqtONvs JnOEG56vlKyPdnT/qycODnr2TFL0mtNgv8Z4KHADArZISoJ8mXwMJmxXOjCQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1654486858; x= 1654573258; bh=Ul/YTZELjdXhM4yte1+Tqag6FgjJfdtEGmy0W8pthfU=; b=H suzKn2Dd738Q1vwBxYukEroFNsufQJddh/iizV9eAY9HQy3+DB+EXVF4HtfcLq5+ ds0kHEwJ/ou3x7dzPw0xH4hRSu/SI0I4jQlZXUtfhauoiiXNCVmKdiYFjiqo6suM bRwnPkVPdlo/cozd7u8zB9nCx/zNeVt4DtIZ7RMMhY5uilfqut0svYg4i02abqw2 MoESh5Xluc9vOouB/Y9eZQKR5+nc9KjV0Tfh0KUr3olyFQSlylgY/LrUxyd0IW4V mORk2Zbs+ohdDYmxemPQIcLnseOX8JYHEwQcTQM1pNx9rdTvIvW7DLjC2RVc17bs KS4dmqvwSta545M1uRDmQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvfedruddtuddgjeefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhephffvvefufffkofgjfhggtgfgsehtkeertdertdejnecuhfhrohhmpeforghr vghkucforghrtgiihihkohifshhkihdqifpkrhgvtghkihcuoehmrghrmhgrrhgvkhesih hnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhmqeenucggtffrrghtthgvrhhnpefg ueduhefgvdefheehudejheefudevueeghfekhfehleegveduteeuiedugffgffenucevlh hushhtvghrufhiiigvpedvnecurfgrrhgrmhepmhgrihhlfhhrohhmpehmrghrmhgrrhgv khesihhnvhhishhisghlvghthhhinhhgshhlrggsrdgtohhm X-ME-Proxy: Feedback-ID: i1568416f:Fastmail From: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= To: xen-devel@lists.xenproject.org Cc: =?utf-8?q?Marek_Marczykowski-G=C3=B3recki?= , Andrew Cooper , George Dunlap , Jan Beulich , Julien Grall , Stefano Stabellini , Wei Liu Subject: [RFC PATCH 12/12] xue: allow driving the reset of XHCI by a domain while Xen uses DbC Date: Mon, 6 Jun 2022 05:40:24 +0200 Message-Id: <2f7660330861b1c6db9520332bee20388178c162.1654486751.git-series.marmarek@invisiblethingslab.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: References: MIME-Version: 1.0 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 --- xen/drivers/char/xue.c | 13 +++++++------ xen/include/xue.h | 10 ++++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) 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 #include #include +#include #include #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))) {