qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 1/2] hw/openrisc/openrisc_sim: keep serial@90000000 as defaul


From: Peter Maydell
Subject: Re: [PATCH 1/2] hw/openrisc/openrisc_sim: keep serial@90000000 as default
Date: Mon, 2 Dec 2024 10:54:03 +0000

On Sun, 1 Dec 2024 at 06:57, Stafford Horne <shorne@gmail.com> wrote:
>
> On Sun, Dec 01, 2024 at 06:44:39AM +0000, Stafford Horne wrote:
> > On Mon, Nov 25, 2024 at 02:02:35PM +0000, Peter Maydell wrote:
> > > On Sat, 23 Nov 2024 at 10:39, Stafford Horne <shorne@gmail.com> wrote:
> > > >
> > > > From: Ahmad Fatoum <a.fatoum@pengutronix.de>
> > > >
> > > > We used to only have a single UART on the platform and it was located at
> > > > address 0x90000000. When the number of UARTs was increased to 4, the
> > > > first UART remained at it's location, but instead of being the first one
> > > > to be registered, it became the last.
> > > >
> > > > This caused QEMU to pick 0x90000300 as the default UART, which broke
> > > > software that hardcoded the address of 0x90000000 and expected it's
> > > > output to be visible when the user configured only a single console.
> > > >
> > > > This caused regressions[1] in the barebox test suite when updating to a
> > > > newer QEMU. As there seems to be no good reason to register the UARTs in
> > > > inverse order, let's register them by ascending address, so existing
> > > > software can remain oblivious to the additional UART ports.
> > > >
> > > > Changing the order of uart registration alone breaks Linux which
> > > > was choosing the UART at 0x90000300 as the default for ttyS0.  To fix
> > > > Linux we fix two things in the device tree:
> > > >
> > > >  1. Define stdout-path only one time for the first registerd UART
> > >
> > > "registered"
> >
> > OK
> >
> > > >     instead of incorrectly defining for each UART.
> > > >  2. Change the UART alias name from 'uart0' to 'serial0' as almost all
> > > >     Linux tty drivers look for an alias starting with "serial".
> > >
> > > I would recommend for maximum backwards compatibility also changing
> > > one other thing. With this patch, the UARTs are listed in the
> > > device tree starting with the one with the highest address and
> > > working down. You can see this if you run
> > >  qemu-system-or1k -M or1k-sim -machine dumpdtb=or1k.dtb -kernel /dev/null
> > > and then
> > >  dtc -I dtb -O dts /or1k.dtb |less
> > > -- the output shows that "serial@90000300" is first.
> > >
> > > This happens because (due to an implementation quirk that I forget
> > > the details of) nodes we add to the DTB in QEMU end up being listed
> > > in reverse order of creation. I would recommend making the
> > > UART-creation loop in openrisc_sim_init() run backwards rather
> > > than forwards, so that the nodes end up in the DTB in ascending order.
> > >
> > > This should not affect any guests that do the "right thing" for
> > > finding their UART, i.e. look at stdout-path or at the UART alias
> > > nodes; but for Arm we found that at least some guest code had been
> > > written to just find the first UART node in the dtb and use that.
> > >
> > > (I suspect, incidentally, that this is the reason why 777784bda468
> > > was using "serial_hd(OR1KSIM_UART_COUNT - uart_idx - 1)" -- it was
> > > trying to fix this but didn't quite put the change in the right place.)
> > >
> > > That would correspond to squashing in this change on top of your patch:
> > >
> > > --- a/hw/openrisc/openrisc_sim.c
> > > +++ b/hw/openrisc/openrisc_sim.c
> > > @@ -329,11 +329,22 @@ static void openrisc_sim_init(MachineState *machine)
> > >                                  smp_cpus, cpus, OR1KSIM_OMPIC_IRQ);
> > >      }
> > >
> > > -    for (n = 0; n < OR1KSIM_UART_COUNT; ++n)
> > > +    /*
> > > +     * We create the UART nodes starting with the highest address and
> > > +     * working downwards, because in QEMU the DTB nodes end up in the
> > > +     * DTB in reverse order of creation. Correctly-written guest software
> > > +     * will not care about the node order (it will look at stdout-path
> > > +     * or the alias nodes), but for the benefit of guest software which
> > > +     * just looks for the first UART node in the DTB, make sure the
> > > +     * lowest-address UART (which is QEMU's first serial port) appears
> > > +     * first in the DTB.
> > > +     */
> > > +    for (n = OR1KSIM_UART_COUNT - 1; n >= 0; n--) {
> > >          openrisc_sim_serial_init(state, 
> > > or1ksim_memmap[OR1KSIM_UART].base +
> > >                                          
> > > or1ksim_memmap[OR1KSIM_UART].size * n,
> > >                                   or1ksim_memmap[OR1KSIM_UART].size,
> > >                                   smp_cpus, cpus, OR1KSIM_UART_IRQ, n);
> > > +    }
> > >
> > >      load_addr = openrisc_load_kernel(ram_size, kernel_filename,
> > >                                       &boot_info.bootstrap_pc);
> >
> > OK it makes sense, I will add this as well.
>
> Hi Peter,
>
> One comment on this, in the commit message from Ahmad he says.  The 
> registration
> order... ''This caused QEMU to pick 0x90000300 as the default UART,''

The thing that made QEMU pick 0x90000300 as the first serial
terminal is that the current code
 (1) loops through calling openrisc_sim_serial_init() starting
     lowest address first and
 (2) calls "serial_hd(OR1KSIM_UART_COUNT - uart_idx - 1)"
     to get the QEMU chardev.

If you do that then the uart that gets serial_hd(0) is 0x90000300.
This is completely unrelated to the order of nodes in the dtb,
or to any logic that the guest uses to select a UART: it's what
means that if the user only passes one "-serial foo" that's the
UART they're configuring. It happens that if the guest code
is doing the "pick the first node in the DTB" then the current
code will give them the UART that QEMU thinks of as the "first"
serial port. But if the guest code is doing any of a bunch of
other reasonable things then it will pick a UART that isn't what
QEMU is currently calling the "first" serial port.

 We want all of these to be true:
 * serial_hd(0) is the lowest-address UART
 * serial_hd(0) is listed first in the DTB
 * serial_hd(0) is the /chosen/stdout-path one
 * the /aliases/serial0 alias points at serial_hd(0)
   (and then up in ascending order for serial1, etc)

(I would probably reword the commit message a bit to make it
clear that this is what we're trying to achieve and what we
think the commit does.)

thanks
-- PMM



reply via email to

[Prev in Thread] Current Thread [Next in Thread]