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: Stafford Horne
Subject: Re: [PATCH 1/2] hw/openrisc/openrisc_sim: keep serial@90000000 as default
Date: Sun, 1 Dec 2024 06:44:39 +0000

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.

> 
> > [1]: 
> > https://lore.barebox.org/barebox/707e7c50-aad1-4459-8796-0cc54bab32e2@pengutronix.de/T/#m5da26e8a799033301489a938b5d5667b81cef6ad
> >
> > Fixes: 777784bda468 ("hw/openrisc: support 4 serial ports in or1ksim")
> > Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
> > [stafford: Change to serial0 alias and update change message]
> > Signed-off-by: Stafford Horne <shorne@gmail.com>
> > ---
> >  hw/openrisc/openrisc_sim.c | 13 ++++++++-----
> >  1 file changed, 8 insertions(+), 5 deletions(-)
> >
> > diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
> > index 9fb63515ef..5ec9172ccf 100644
> > --- a/hw/openrisc/openrisc_sim.c
> > +++ b/hw/openrisc/openrisc_sim.c
> > @@ -250,7 +250,7 @@ static void openrisc_sim_serial_init(Or1ksimState 
> > *state, hwaddr base,
> >      void *fdt = state->fdt;
> >      char *nodename;
> >      qemu_irq serial_irq;
> > -    char alias[sizeof("uart0")];
> > +    char alias[sizeof("serial0")];
> 
> Using g_strdup_printf() (and a g_autofree pointer) is better than
> a fixed-size array; but I guess we don't really need to clean
> that up in this patch.

I will leave this as is.

> >      int i;
> >
> >      if (num_cpus > 1) {
> > @@ -265,7 +265,7 @@ static void openrisc_sim_serial_init(Or1ksimState 
> > *state, hwaddr base,
> >          serial_irq = get_cpu_irq(cpus, 0, irq_pin);
> >      }
> >      serial_mm_init(get_system_memory(), base, 0, serial_irq, 115200,
> > -                   serial_hd(OR1KSIM_UART_COUNT - uart_idx - 1),
> > +                   serial_hd(uart_idx),
> >                     DEVICE_NATIVE_ENDIAN);
> >
> >      /* Add device tree node for serial. */
> > @@ -277,10 +277,13 @@ static void openrisc_sim_serial_init(Or1ksimState 
> > *state, hwaddr base,
> >      qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", 
> > OR1KSIM_CLK_MHZ);
> >      qemu_fdt_setprop(fdt, nodename, "big-endian", NULL, 0);
> >
> > -    /* The /chosen node is created during fdt creation. */
> > -    qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename);
> > -    snprintf(alias, sizeof(alias), "uart%d", uart_idx);
> > +    if (uart_idx == 0) {
> > +        /* The /chosen node is created during fdt creation. */
> > +        qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename);
> > +    }
> > +    snprintf(alias, sizeof(alias), "serial%d", uart_idx);
> >      qemu_fdt_setprop_string(fdt, "/aliases", alias, nodename);
> > +
> >      g_free(nodename);
> >  }
> 
> thanks

Thanks,

-Stafford



reply via email to

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