On Fri, 29 Aug 2025, Stefano Stabellini wrote: > On Thu, 28 Aug 2025, dmuk...@xen.org wrote: > > From: Denis Mukhin <dmuk...@ford.com> > > > > Add RBR/THR registers emulation to the I/O port handlder. > > > > Also, add RX/TX FIFO management code since RBR depends on RX FIFO and > > THR depends on TX FIFO. > > > > FIFOs are not emulated as per UART specs for simplicity (not need to emulate > > baud rate). Emulator does not emulate NS8250 (no FIFO), NS16550a (16 bytes) > > or > > NS16750 (64 bytes). > > > > FIFOs are 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. > > > > Signed-off-by: Denis Mukhin <dmuk...@ford.com> > > --- > > Changes since v4: > > - new patch > > --- > > xen/common/emul/vuart/ns16x50.c | 135 ++++++++++++++++++++++++++++++++ > > 1 file changed, 135 insertions(+) > > > > diff --git a/xen/common/emul/vuart/ns16x50.c > > b/xen/common/emul/vuart/ns16x50.c > > index 20597cc36b35..efb2f4c6441c 100644 > > --- a/xen/common/emul/vuart/ns16x50.c > > +++ b/xen/common/emul/vuart/ns16x50.c > > @@ -92,6 +92,119 @@ static bool ns16x50_fifo_rx_empty(const struct > > vuart_ns16x50 *vdev) > > return cons->in_prod == cons->in_cons; > > } > > > > +static bool ns16x50_fifo_rx_full(const struct vuart_ns16x50 *vdev) > > +{ > > + const struct xencons_interface *cons = &vdev->cons; > > + > > + return cons->in_prod - cons->in_cons == ARRAY_SIZE(cons->in); > > +} > > + > > +static void ns16x50_fifo_rx_reset(struct vuart_ns16x50 *vdev) > > +{ > > + struct xencons_interface *cons = &vdev->cons; > > + > > + cons->in_cons = cons->in_prod; > > +} > > + > > +static int ns16x50_fifo_rx_getchar(struct vuart_ns16x50 *vdev) > > +{ > > + struct xencons_interface *cons = &vdev->cons; > > + int rc; > > + > > + if ( ns16x50_fifo_rx_empty(vdev) ) > > + { > > + ns16x50_debug(vdev, "RX FIFO empty\n"); > > + rc = -ENODATA; > > + } > > + else > > + { > > + rc = cons->in[MASK_XENCONS_IDX(cons->in_cons, cons->in)]; > > + cons->in_cons++; > > + } > > + > > + return rc; > > The signed integer to char conversion here is not great from a MISRA > perspective. I think it would be better to keep rc as success/failure > return value and take the read char as a pointer parameter. > > > > +} > > + > > +static int ns16x50_fifo_rx_putchar(struct vuart_ns16x50 *vdev, char c) > > +{ > > + struct xencons_interface *cons = &vdev->cons; > > + int rc; > > + > > + /* > > + * FIFO-less 8250/16450 UARTs: newly arrived word overwrites the > > contents > > + * of the THR. > > + */ > > + if ( ns16x50_fifo_rx_full(vdev) ) > > + { > > + ns16x50_debug(vdev, "RX FIFO full; resetting\n"); > > + ns16x50_fifo_rx_reset(vdev); > > + rc = -ENOSPC; > > + } > > + else > > + rc = 0; > > + > > + cons->in[MASK_XENCONS_IDX(cons->in_prod, cons->in)] = c; > > + cons->in_prod++; > > + > > + return rc; > > +} > > + > > +static bool ns16x50_fifo_tx_empty(const struct vuart_ns16x50 *vdev) > > +{ > > + const struct xencons_interface *cons = &vdev->cons; > > + > > + return cons->out_prod == cons->out_cons; > > +} > > + > > +static void ns16x50_fifo_tx_reset(struct vuart_ns16x50 *vdev) > > +{ > > + struct xencons_interface *cons = &vdev->cons; > > + > > + cons->out_prod = 0; > > + ASSERT(cons->out_cons == cons->out_prod); > > I am not sure about this.. why resetting the out_prod index? In theory > it could keep increasing until wrap around and still go forward thanks > to the mask
I get it now .. it is because it is called from ns16x50_fifo_tx_flush right after printing to the real console. I think it is better to simply do: cons->out_cons = cons->out_prod; which effectively clears out the whole buffer. It is dangerous to do: cons->out_prod = 0; without also doing: cons->out_cons = 0; Also, if ns16x50_fifo_tx_flush is the only caller of ns16x50_fifo_tx_reset, I would open code the implementation directly inside ns16x50_fifo_tx_flush to make it more obvious. > > +} > > + > > +/* > > + * Flush cached output to Xen console. > > + */ > > +static void ns16x50_fifo_tx_flush(struct vuart_ns16x50 *vdev) > > +{ > > + struct xencons_interface *cons = &vdev->cons; > > + struct domain *d = vdev->owner; > > + > > + if ( ns16x50_fifo_tx_empty(vdev) ) > > + return; > > + > > + UART_IIR_THR ASSERT(cons->out_prod < ARRAY_SIZE(cons->out)); > > + cons->out[cons->out_prod] = '\0'; > > should use MASK_XENCONS_IDX to access the array > > > > + cons->out_prod++; > > + > > + guest_printk(d, guest_prefix "%s", cons->out); > > + > > + ns16x50_fifo_tx_reset(vdev); > > set UART_IIR_THR and call ns16x50_irq_check ? > > > > +}