Linux Serial subsystem development
 help / color / mirror / Atom feed
From: John Ogness <john.ogness@linutronix.de>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jiri Slaby <jirislaby@kernel.org>
Cc: "Andy Shevchenko" <andy.shevchenko@gmail.com>,
	"Petr Mladek" <pmladek@suse.com>,
	"Sebastian Andrzej Siewior" <bigeasy@linutronix.de>,
	linux-kernel@vger.kernel.org,
	"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>,
	"Andy Shevchenko" <andriy.shevchenko@linux.intel.com>,
	"Hugo Villeneuve" <hvilleneuve@dimonoff.com>,
	"Stepan Ionichev" <sozdayvek@gmail.com>,
	"Kees Cook" <kees@kernel.org>,
	"Fushuai Wang" <wangfushuai@baidu.com>,
	"Jacques Nilo" <jnilo@free.fr>,
	"Peng Zhang" <zhangpeng.00@bytedance.com>,
	linux-serial@vger.kernel.org
Subject: Re: [PATCH tty v10 1/2] serial: 8250: Switch to nbcon console, take 2
Date: Tue, 28 Jul 2026 15:40:06 +0206	[thread overview]
Message-ID: <87ecgntf01.fsf@jogness.linutronix.de> (raw)
In-Reply-To: <20260727145332.231949-2-john.ogness@linutronix.de>

On 2026-07-27, Sashiko wrote:
> > diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
> > index 8c241ec7f4f29..5bcbb6deb12f7 100644
> > --- a/drivers/tty/serial/8250/8250_port.c
> > +++ b/drivers/tty/serial/8250/8250_port.c
> [ ... ]
> > @@ -3332,6 +3405,18 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,
> >  		mdelay(port->rs485.delay_rts_before_send);
> >  	}
> >  
> > +	/* If ownership was lost, no writing is allowed */
> > +	if (!nbcon_can_proceed(wctxt))
> > +		goto skip_write;
> > +
> > +	/*
> > +	 * If console printer did not fully output the previous line, it must
> > +	 * have been handed or taken over. Insert a newline in order to
> > +	 * maintain clean output.
> > +	 */
> > +	if (!up->console_line_ended)
> > +		uart_console_write(port, "\n", 1, serial8250_console_wait_putchar);
> > +
>
> Will this cause the newline characters to be silently dropped if the
> hardware FIFO is already full from a preempted context?
>
> When uart_console_write() calls serial8250_console_wait_putchar(), it
> relies on wait_for_lsr() to wait for transmitter room. The timeout in
> wait_for_lsr() is calculated based on frame_time, which is only enough
> for a single character. If the preempted context left a full FIFO (e.g.,
> 16-64 bytes), the wait_for_lsr() timeout will expire before the FIFO
> drains, causing the hardware to drop the injected newline characters.

Sashiko is correct. For v11 I am writing helper functions to handle
@console_line_ended and the console line printing for fifo and
non-fifo. This causes a bit more churn than I would like to see at this
point (v11) but it will handle all situations, has increased code
re-use, and should be easier to read/maintain.

> [ ... ]
> >	while (!nbcon_enter_unsafe(wctxt))
> >		nbcon_reacquire_nobuf(wctxt);
> >
> >  	/*
> >  	 *	Finally, wait for transmitter to become empty
> >  	 *	and restore the IER
> >  	 */
> >  	wait_for_xmitr(up, UART_LSR_BOTH_EMPTY);
> >  
> > +	if (em485) {
> > +		mdelay(port->rs485.delay_rts_after_send);
> > +		if (em485->tx_stopped)
> > +			up->rs485_stop_tx(up, false);
> > +	}
> > +
> >  	serial_port_out(port, UART_IER, ier);
>
> Could the hardware state be corrupted here if a hostile takeover occurs
> while waiting for the transmitter to empty?
>
> The wait_for_xmitr() call can take a significant amount of time to let the
> FIFO drain. If a system panic triggers a hostile console takeover during
> this window, the panic context might reconfigure the hardware. Once the
> original context finishes waiting, it will unconditionally execute
> serial_port_out(), potentially undoing the panic context's configuration
> or causing interrupt storms.
>
> Should we check nbcon_can_proceed(wctxt) again before modifying the
> hardware state?

nbcon_can_proceed() is not enough because these final actions are
necessary. It would need to be:

	nbcon_exit_unsafe(wctxt);
	while (!nbcon_enter_unsafe(wctxt))
		nbcon_reacquire_nobuf(wctxt);

Although this does not close the window, it does make it quite
small. And if we are really in the unlikely situation of:

- a panic occurs
- the panic is unable to stop all the CPUs
- a console printer is actively printing from a non-stopped CPU
- the panic CPU performs a hostile takeover

then we should probably do everything we can (within reason) to avoid
interfering with the panic printing.

As Sashiko points out, the wait_for_xmitr() and mdelay() calls could be
relatively large. I agree that it makes sense to peform unsafe toggles
in these two locations. I will add that for v11. It will look something
like this:

@@ -3481,10 +3487,21 @@ void serial8250_console_write(struct uart_8250_port *up,
 
 	if (em485) {
 		mdelay(port->rs485.delay_rts_after_send);
+
+		/* Toggle unsafe after possibly long delay */
+		nbcon_exit_unsafe(wctxt);
+		while (!nbcon_enter_unsafe(wctxt))
+			nbcon_reacquire_nobuf(wctxt);
+
 		if (em485->tx_stopped)
 			up->rs485_stop_tx(up, false);
 	}
 
+	/* Toggle unsafe after possibly long delay */
+	nbcon_exit_unsafe(wctxt);
+	while (!nbcon_enter_unsafe(wctxt))
+		nbcon_reacquire_nobuf(wctxt);
+
 	serial_port_out(port, UART_IER, ier);
 
 	/*

> > @@ -3400,8 +3509,24 @@ static unsigned int probe_baud(struct uart_port *port)
> >  	return (port->uartclk / 16) / quot;
> >  }
> >  
> > +/*
> > + * irq_work handler to perform modem control during console output.
> > + * Only triggered via ->write_atomic() callback because it may be
> > + * in a scheduler or NMI context, unable to wake tasks.
> > + */
> > +static void console_msr_handler(struct irq_work *iwp)
> > +{
> > +	struct uart_8250_port *up = container_of(iwp, struct uart_8250_port, console_msr_work);
> > +	struct uart_port *port = &up->port;
> > +
> > +	guard(uart_port_lock)(port);
> > +
> > +	serial8250_modem_status(up);
> > +}
>
> Does this code introduce a race condition that could cause invalid hardware
> accesses on a suspended device?
>
> If CPU1 is executing serial8250_console_write(), it reads
> up->console_msr_work_allow locklessly before queueing the work...

Sashiko is not correct. Both code blocks (reader and writer) are within
unsafe sections and therefore synchronized.

John

  reply	other threads:[~2026-07-28 13:34 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-27 14:53 [PATCH tty v10 0/2] Convert 8250 to NBCON, take 2 John Ogness
2026-07-27 14:53 ` [PATCH tty v10 1/2] serial: 8250: Switch to nbcon console, " John Ogness
2026-07-28 13:34   ` John Ogness [this message]
2026-07-27 14:53 ` [PATCH tty v10 2/2] Revert "serial: 8250: drop lockdep annotation from serial8250_clear_IER()" John Ogness

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=87ecgntf01.fsf@jogness.linutronix.de \
    --to=john.ogness@linutronix.de \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=andy.shevchenko@gmail.com \
    --cc=bigeasy@linutronix.de \
    --cc=gregkh@linuxfoundation.org \
    --cc=hvilleneuve@dimonoff.com \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=jirislaby@kernel.org \
    --cc=jnilo@free.fr \
    --cc=kees@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=pmladek@suse.com \
    --cc=sozdayvek@gmail.com \
    --cc=wangfushuai@baidu.com \
    --cc=zhangpeng.00@bytedance.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox