All of lore.kernel.org
 help / color / mirror / Atom feed
From: dmukhin@xen.org
To: Stefano Stabellini <sstabellini@kernel.org>
Cc: xen-devel@lists.xenproject.org, andrew.cooper3@citrix.com,
	anthony.perard@vates.tech, jbeulich@suse.com, julien@xen.org,
	michal.orzel@amd.com, roger.pau@citrix.com, dmukhin@ford.com
Subject: Re: [PATCH v5 06/15] emul/ns16x50: implement THR/RBR registers
Date: Fri, 5 Sep 2025 15:20:05 -0700	[thread overview]
Message-ID: <aLtiFWKhicoCCYMB@kraken> (raw)
In-Reply-To: <alpine.DEB.2.22.394.2508291320330.341243@ubuntu-linux-20-04-desktop>

On Fri, Aug 29, 2025 at 01:28:41PM -0700, Stefano Stabellini wrote:
> On Thu, 28 Aug 2025, dmukhin@xen.org wrote:
> > From: Denis Mukhin <dmukhin@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 <dmukhin@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.

Ack.

> 
> 
> > +}
> > +
> > +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 used TX buffer not as a FIFO but as a large buffer for simplicity...

I have reworked that into a normal circular buffer in v6.

> 
> 
> > +}
> > +
> > +/*
> > + * 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

Ack.

> 
> 
> > +    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 ?

I moved that to the I/O handler calling ns16x50_fifo_tx_flush() instead,
because ns16x50_fifo_tx_flush() can be called during vuart destroy,
and there's no need to emulate IRQs at domain destroy.

> 
> 
> > +}
> > +
> > +/*
> > + * Accumulate guest OS output before sending to Xen console.
> > + */
> > +static void ns16x50_fifo_tx_putchar(struct vuart_ns16x50 *vdev, char ch)
> > +{
> > +    struct xencons_interface *cons = &vdev->cons;
> > +
> > +    if ( !is_console_printable(ch) )
> > +        return;
> > +
> > +    if ( ch != '\0' )
> > +    {
> > +        cons->out[cons->out_prod] = ch;
> 
> should use MASK_XENCONS_IDX to access the array

Ack.

> 
> 
> > +        cons->out_prod++;
> > +    }
> > +
> > +    if ( cons->out_prod == ARRAY_SIZE(cons->out) - 1 ||
> > +         ch == '\n' || ch == '\0' )
> > +        ns16x50_fifo_tx_flush(vdev);
> > +}
> > +
> >  static inline uint8_t cf_check ns16x50_dlab_get(const struct vuart_ns16x50 *vdev)
> >  {
> >      return vdev->regs[UART_LCR] & UART_LCR_DLAB ? 1 : 0;
> > @@ -228,6 +341,16 @@ static int ns16x50_io_write8(
> >      {
> >          switch ( reg )
> >          {
> > +        case UART_THR:
> > +            if ( regs[UART_MCR] & UART_MCR_LOOP )
> > +                rc = ns16x50_fifo_rx_putchar(vdev, val);
> > +            else
> > +                ns16x50_fifo_tx_putchar(vdev, val);
> 
> should UART_IIR_THR be cleared here?

Yes, thanks for the catch!

> 
> 
> > +            rc = 0;
> > +
> > +            break;
> > +
> >          case UART_IER:
> >              /*
> >               * NB: Make sure THR interrupt is re-triggered once guest OS
> > @@ -312,6 +435,14 @@ static int ns16x50_io_read8(
> >      else {
> >          switch ( reg )
> >          {
> > +        case UART_RBR:
> > +            rc = ns16x50_fifo_rx_getchar(vdev);
> > +            if ( rc >= 0 )
> > +                val = (uint8_t)rc;
> 
> Empty fifo check?

Will do.

> 
> 
> > +            rc = 0;
> > +            break;
> > +
> >          case UART_IER:
> >              val = regs[UART_IER];
> >              break;
> > @@ -499,6 +630,10 @@ static void cf_check ns16x50_deinit(void *arg)
> >      struct vuart_ns16x50 *vdev = arg;
> >  
> >      ASSERT(vdev);
> > +
> > +    spin_lock(&vdev->lock);
> > +    ns16x50_fifo_tx_flush(vdev);
> > +    spin_unlock(&vdev->lock);
> >  }
> >  
> >  static void * cf_check ns16x50_alloc(struct domain *d, const struct vuart_info *info)
> > -- 
> > 2.51.0
> > 


  parent reply	other threads:[~2025-09-05 22:20 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-28 23:53 [PATCH v5 00/15] x86: introduce NS16550-compatible UART emulator dmukhin
2025-08-28 23:53 ` [PATCH v5 01/15] emul/vuart: introduce framework for UART emulators dmukhin
2025-08-29 19:27   ` Stefano Stabellini
2025-09-01  8:14     ` Jan Beulich
2025-09-01 22:27       ` dmukhin
2025-09-02  6:14         ` Jan Beulich
2025-09-01 22:11     ` dmukhin
2025-08-28 23:53 ` [PATCH v5 02/15] xen/8250-uart: update definitions dmukhin
2025-08-29 19:32   ` Stefano Stabellini
2025-09-01 22:28     ` dmukhin
2025-08-28 23:53 ` [PATCH v5 03/15] emul/ns16x50: implement emulator stub dmukhin
2025-08-29 19:57   ` Stefano Stabellini
2025-09-01 23:11     ` dmukhin
2025-09-02  9:32       ` Jan Beulich
2025-09-05 23:34         ` dmukhin
2025-09-06  0:07           ` dmukhin
2025-09-02  9:36     ` Jan Beulich
2025-09-05 23:34       ` dmukhin
2025-08-28 23:53 ` [PATCH v5 04/15] emul/ns16x50: implement DLL/DLM registers dmukhin
2025-08-28 23:53 ` [PATCH v5 05/15] emul/ns16x50: implement EIR/IIR registers dmukhin
2025-08-29 20:14   ` Stefano Stabellini
2025-09-05 22:05     ` dmukhin
2025-08-28 23:54 ` [PATCH v5 06/15] emul/ns16x50: implement THR/RBR registers dmukhin
2025-08-29 20:28   ` Stefano Stabellini
2025-08-29 20:34     ` Stefano Stabellini
2025-09-05 22:29       ` dmukhin
2025-09-05 22:20     ` dmukhin [this message]
2025-08-28 23:54 ` [PATCH v5 07/15] emul/ns16x50: implement FCR register (write-only) dmukhin
2025-08-29 20:38   ` Stefano Stabellini
2025-09-05 22:33     ` dmukhin
2025-08-28 23:54 ` [PATCH v5 08/15] emul/ns16x50: implement LCR/LSR registers dmukhin
2025-08-28 23:54 ` [PATCH v5 09/15] emul/ns16x50: implement MCR/MSR registers dmukhin
2025-08-28 23:54 ` [PATCH v5 10/15] emul/ns16x50: implement SCR register dmukhin
2025-08-28 23:54 ` [PATCH v5 11/15] emul/ns16x50: implement put_rx() hook dmukhin
2025-08-28 23:54 ` [PATCH v5 12/15] emul/ns16550: implement dump_state() hook dmukhin
2025-08-28 23:54 ` [PATCH v5 13/15] x86/domain: enable per-domain I/O port bitmaps dmukhin
2025-08-29 21:43   ` Stefano Stabellini
2025-09-05 22:38     ` dmukhin
2025-08-28 23:54 ` [PATCH v5 14/15] xen/domain: allocate d->irq_caps before arch-specific initialization dmukhin
2025-08-29 21:46   ` Stefano Stabellini
2025-09-05 22:43     ` dmukhin
2025-08-28 23:54 ` [PATCH v5 15/15] emul/ns16x50: implement IRQ emulation via vIOAPIC dmukhin
2025-08-29 22:21   ` Stefano Stabellini
2025-09-05 22:54     ` dmukhin
2025-09-05 23:01       ` Stefano Stabellini
2025-09-05 23:44         ` dmukhin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aLtiFWKhicoCCYMB@kraken \
    --to=dmukhin@xen.org \
    --cc=andrew.cooper3@citrix.com \
    --cc=anthony.perard@vates.tech \
    --cc=dmukhin@ford.com \
    --cc=jbeulich@suse.com \
    --cc=julien@xen.org \
    --cc=michal.orzel@amd.com \
    --cc=roger.pau@citrix.com \
    --cc=sstabellini@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.