From nobody Mon Feb 9 23:40:16 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1757365945; cv=none; d=zohomail.com; s=zohoarc; b=gzpnzf94UTQaUy+Q31xMpEQpmf6fzOvvoaLmVr/15ZIw83mOpUy/IQ/c3Tny9HZbGnqCZ94zMB/4vo5S2gkBFFL9DF5bfuc1YDXpUFFOv+GqN8ZfAi6wkKM3wtD6tb7ONL/ZGIxXMjt4Z4k8805cP1wXIs4i9swGkSu7ZU/0jFU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1757365945; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=sJw6viqpsDfMS5MRma9QK/++3SeyoW0ownBjjeYeZKo=; b=cNBgWmQLUT9DjMwobIoNfe9Os7wNisHc61jQ55+8KE9UYXTt1lygquxBbagy9p+6W5KZR8rLRxDwxhDv4f9lhnzWevcbxI3lwG6B3n8DowdFculf5DbkmD/kK7HVgJqvqclGKuEHFPhglkbmyGYBr5/SLA92O9LvWtPAm4RA2mE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1757365945280648.9815905421576; Mon, 8 Sep 2025 14:12:25 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1115542.1462159 (Exim 4.92) (envelope-from ) id 1uvj9g-0001BX-10; Mon, 08 Sep 2025 21:12:04 +0000 Received: by outflank-mailman (output) from mailman id 1115542.1462159; Mon, 08 Sep 2025 21:12:03 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1uvj9f-0001AG-Nw; Mon, 08 Sep 2025 21:12:03 +0000 Received: by outflank-mailman (input) for mailman id 1115542; Mon, 08 Sep 2025 21:12:02 +0000 Received: from mail.xenproject.org ([104.130.215.37]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1uvj9e-0000zQ-53 for xen-devel@lists.xenproject.org; Mon, 08 Sep 2025 21:12:02 +0000 Received: from xenbits.xenproject.org ([104.239.192.120]) by mail.xenproject.org with esmtp (Exim 4.96) (envelope-from ) id 1uvj9d-000FU1-2x; Mon, 08 Sep 2025 21:12:01 +0000 Received: from [19.12.91.86] (helo=localhost) by xenbits.xenproject.org with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1uvj9d-000gMV-3B; Mon, 08 Sep 2025 21:12:01 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version 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" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=xen.org; s=20200302mail; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:Cc:To:From; bh=sJw6viqpsDfMS5MRma9QK/++3SeyoW0ownBjjeYeZKo=; b=Zqr8zJltVqZnjQMSoCh8s/n1nd +xuQYSproeuFQMambh3zctjtcQW64xcEIRma5q/s4hI7FmFGIYPU+XtPnX9Nxuu+rGZ/1NkXYzHew YsVmI/C5mtSEsEd8Z/256c+5QN0GkArjOCIlBP9tJ+ohtvhAumN64SR3dFQb+99ZeCt0=; From: dmukhin@xen.org To: xen-devel@lists.xenproject.org Cc: andrew.cooper3@citrix.com, anthony.perard@vates.tech, jbeulich@suse.com, julien@xen.org, michal.orzel@amd.com, roger.pau@citrix.com, sstabellini@kernel.org, dmukhin@ford.com Subject: [PATCH v7 09/16] emul/ns16x50: implement RBR register Date: Mon, 8 Sep 2025 14:11:42 -0700 Message-ID: <20250908211149.279143-10-dmukhin@ford.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20250908211149.279143-1-dmukhin@ford.com> References: <20250908211149.279143-1-dmukhin@ford.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @xen.org) X-ZM-MESSAGEID: 1757365947609124100 Content-Type: text/plain; charset="utf-8" From: Denis Mukhin =20 Add RBR register emulation to the I/O port handlder. Add RX FIFO management code since RBR depends on RX FIFO. RX FIFO is not emulated as per UART specs for simplicity (not need to emula= te baud rate). Emulator does not emulate NS8250 (no FIFO), NS16550a (16 bytes)= or NS16750 (64 bytes). RX FIFO is emulated by means of using xencons_interface which conveniently provides primitives for buffer management and later can be used for inter-domain communication similarly to vpl011. Account for DLL =3D=3D 0: in this case, disable receiver. Add UART_LSR_DR handling since it depends on RBR register access. Finally, implement put_rx() vUART hook for placing a character into the emulated RX FIFO from console driver. That implements physical console forwarding to the guest OS over emulated NS16550. Signed-off-by: Denis Mukhin --- Changes since v6: - added DLL =3D=3D 0 case handling as per Mykola's suggestion --- xen/common/emul/vuart/ns16x50.c | 134 +++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 2 deletions(-) diff --git a/xen/common/emul/vuart/ns16x50.c b/xen/common/emul/vuart/ns16x5= 0.c index fdc20124d4c9..250411e0a7d8 100644 --- a/xen/common/emul/vuart/ns16x50.c +++ b/xen/common/emul/vuart/ns16x50.c @@ -9,6 +9,8 @@ * https://www.ti.com/lit/ds/symlink/tl16c550c.pdf * - UART w/ 64 byte FIFO: * https://www.ti.com/lit/ds/symlink/tl16c750.pdf + * - DesignWare DW_apb_uart Databook, v4.02a: + * https://iccircle.com/static/upload/img20240313113905.pdf * * Limitations: * - Only x86; @@ -85,6 +87,74 @@ struct vuart_ns16x50 { struct xencons_interface cons; /* Emulated RX/TX FIFOs */ }; =20 +static bool ns16x50_fifo_rx_empty(const struct vuart_ns16x50 *vdev) +{ + const struct xencons_interface *cons =3D &vdev->cons; + + return cons->in_prod =3D=3D cons->in_cons; +} + +static bool ns16x50_fifo_rx_full(const struct vuart_ns16x50 *vdev) +{ + const struct xencons_interface *cons =3D &vdev->cons; + + return cons->in_prod - cons->in_cons =3D=3D ARRAY_SIZE(cons->in); +} + +static void ns16x50_fifo_rx_reset(struct vuart_ns16x50 *vdev) +{ + struct xencons_interface *cons =3D &vdev->cons; + + cons->in_cons =3D cons->in_prod; +} + +/* + * Transfer character from RX FIFO and return the RX FIFO status after the + * transfer. + */ +static int ns16x50_fifo_rx_getchar(struct vuart_ns16x50 *vdev, uint8_t *pt= r) +{ + struct xencons_interface *cons =3D &vdev->cons; + + if ( ns16x50_fifo_rx_empty(vdev) ) + return -ENODATA; + + *ptr =3D cons->in[MASK_XENCONS_IDX(cons->in_cons, cons->in)]; + cons->in_cons++; + + return ns16x50_fifo_rx_empty(vdev) ? -ENODATA : 0; +} + +static int ns16x50_fifo_rx_putchar(struct vuart_ns16x50 *vdev, char c) +{ + struct xencons_interface *cons =3D &vdev->cons; + int rc; + + /* + * FIFO-less 8250/16450 UARTs: newly arrived word overwrites the conte= nts + * of the THR. + */ + if ( ns16x50_fifo_rx_full(vdev) ) + { + ns16x50_debug(vdev, "RX FIFO full; resetting\n"); + ns16x50_fifo_rx_reset(vdev); + rc =3D -ENOSPC; + } + else + rc =3D 0; + + cons->in[MASK_XENCONS_IDX(cons->in_prod, cons->in)] =3D c; + cons->in_prod++; + + return rc; +} + +static bool ns16x50_is_running(const struct vuart_ns16x50 *vdev) +{ + /* DLL set to 0 disables serial communication. */ + return vdev->regs[NS16X50_REGS_NUM + UART_DLL]; +} + static uint8_t ns16x50_dlab_get(const struct vuart_ns16x50 *vdev) { return vdev->regs[UART_LCR] & UART_LCR_DLAB ? 1 : 0; @@ -97,7 +167,7 @@ static bool cf_check ns16x50_iir_check_lsi(const struct = vuart_ns16x50 *vdev) =20 static bool cf_check ns16x50_iir_check_rda(const struct vuart_ns16x50 *vde= v) { - return false; + return !ns16x50_fifo_rx_empty(vdev); } =20 static bool cf_check ns16x50_iir_check_thr(const struct vuart_ns16x50 *vde= v) @@ -362,6 +432,20 @@ static int ns16x50_io_read8( { switch ( reg ) { + case UART_RBR: + if ( !ns16x50_is_running(vdev) ) + break; + + /* NB: do not forget to clear overrun condition */ + regs[UART_LSR] &=3D ~UART_LSR_OE; + + if ( ns16x50_fifo_rx_getchar(vdev, &val) ) + regs[UART_LSR] &=3D ~UART_LSR_DR; + else + regs[UART_LSR] |=3D UART_LSR_DR; + + break; + case UART_IER: val =3D regs[UART_IER]; break; @@ -611,13 +695,59 @@ static void cf_check ns16x50_free(void *arg) xvfree(arg); } =20 +static int cf_check ns16x50_put_rx(void *arg, char ch) +{ + struct vuart_ns16x50 *vdev =3D arg; + uint8_t *regs; + uint8_t dlab; + int rc =3D -EBUSY; + + spin_lock(&vdev->lock); + + dlab =3D ns16x50_dlab_get(vdev); + regs =3D vdev->regs; + + if ( !ns16x50_is_running(vdev) ) + ns16x50_debug(vdev, "THR/RBR access disabled: DLL =3D=3D 0\n"); + else if ( dlab ) + ns16x50_debug(vdev, "THR/RBR access disabled: DLAB=3D1\n"); + else if ( regs[UART_MCR] & UART_MCR_LOOP ) + ns16x50_debug(vdev, "THR/RBR access disabled: loopback mode\n"); + else + { + const struct domain *d =3D vdev->owner; + + /* + * Echo the user input on Xen console iff Xen console input is own= ed + * by ns16x50 domain. + * NB: use 'console_timestamps=3Dnone' to disable Xen timestamps. + */ + if ( is_console_printable(ch) ) + guest_printk(d, "%c", ch); + + if ( ns16x50_fifo_rx_putchar(vdev, ch) ) + regs[UART_LSR] |=3D UART_LSR_OE; + + regs[UART_LSR] |=3D UART_LSR_DR; + + /* TODO: check FCR when to fire an interrupt */ + ns16x50_irq_check(vdev); + + rc =3D 0; + } + + spin_unlock(&vdev->lock); + + return rc; +} + #define ns16x50_emulator \ { \ .compatible =3D "ns16550", \ .alloc =3D ns16x50_alloc, \ .free =3D ns16x50_free, \ .dump_state =3D NULL, \ - .put_rx =3D NULL, \ + .put_rx =3D ns16x50_put_rx, \ } =20 VUART_REGISTER(ns16x50, ns16x50_emulator); --=20 2.51.0