All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stafford Horne <shorne@gmail.com>
To: Peter Maydell <peter.maydell@linaro.org>
Cc: QEMU Development <qemu-devel@nongnu.org>, Jia Liu <proljc@gmail.com>
Subject: Re: [PATCH 3/4] hw/openrisc/openrisc_sim; Add support for loading a decice tree
Date: Fri, 18 Feb 2022 06:39:05 +0900	[thread overview]
Message-ID: <Yg7AeSuZOEW3nT26@antec> (raw)
In-Reply-To: <CAFEAcA_kMsoO26G-KhuNkUH=fJpdWPP_aKCwWva8RnV6ZDKkvg@mail.gmail.com>

On Thu, Feb 17, 2022 at 06:18:58PM +0000, Peter Maydell wrote:
> On Thu, 10 Feb 2022 at 06:46, Stafford Horne <shorne@gmail.com> wrote:
> >
> > Using the device tree means that qemu can now directly tell
> > the kernel what hardware is configured rather than use having
> > to maintain and update a separate device tree file.
> >
> > This patch adds device tree support for the OpenRISC simulator.
> > A device tree is built up based on the state of the configure
> > openrisc simulator.
> 
> This sounds like it's support for creating a device
> tree? Support for loading a device tree would be "the
> user passes us a filename of a dtb file". (This is mostly a
> quibble about commit message wording.)

Ah, yes I will fix this to say, "adds automatic device tree generation support"
....

> > -static void openrisc_load_kernel(ram_addr_t ram_size,
> > +static hwaddr openrisc_load_kernel(ram_addr_t ram_size,
> >                                   const char *kernel_filename)
> 
> Indentation looks off now ?

Fixed now.

> >  {
> >      long kernel_size;
> >      uint64_t elf_entry;
> > +    uint64_t high_addr;
> >      hwaddr entry;
> >
> >      if (kernel_filename && !qtest_enabled()) {
> >          kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
> > -                               &elf_entry, NULL, NULL, NULL, 1, EM_OPENRISC,
> > -                               1, 0);
> > +                               &elf_entry, NULL, &high_addr, NULL, 1,
> > +                               EM_OPENRISC, 1, 0);
> >          entry = elf_entry;
> >          if (kernel_size < 0) {
> >              kernel_size = load_uimage(kernel_filename,
> >                                        &entry, NULL, NULL, NULL, NULL);
> > +            high_addr = entry + kernel_size;
> >          }
> >          if (kernel_size < 0) {
> >              kernel_size = load_image_targphys(kernel_filename,
> >                                                KERNEL_LOAD_ADDR,
> >                                                ram_size - KERNEL_LOAD_ADDR);
> > +            high_addr = KERNEL_LOAD_ADDR + kernel_size;
> >          }
> >
> >          if (entry <= 0) {
> > @@ -168,7 +181,139 @@ static void openrisc_load_kernel(ram_addr_t ram_size,
> >              exit(1);
> >          }
> >          boot_info.bootstrap_pc = entry;
> > +
> > +        return high_addr;
> > +    }
> > +    return 0;
> > +}
> > +
> > +static uint32_t openrisc_load_fdt(Or1ksimState *s, hwaddr load_start,
> > +    uint64_t mem_size)
> 
> Indentation again.

Fixed.

> > +{
> > +    uint32_t fdt_addr;
> > +    int fdtsize = fdt_totalsize(s->fdt);
> > +
> > +    if (fdtsize <= 0) {
> > +        error_report("invalid device-tree");
> > +        exit(1);
> > +    }
> > +
> > +    /* We should put fdt right after the kernel */
> 
> You change this comment in patch 4 -- I think you might as well
> just use that text in this patch to start with.

OK, I had that at first but I did this to be more techincally correct.  I will
simplify as you suggest.

> > +    fdt_addr = ROUND_UP(load_start, 4);
> > +
> > +    fdt_pack(s->fdt);
> 
> fdt_pack() returns an error code -- you should check it.

OK.

> > +    /* copy in the device tree */
> > +    qemu_fdt_dumpdtb(s->fdt, fdtsize);
> > +
> > +    rom_add_blob_fixed_as("fdt", s->fdt, fdtsize, fdt_addr,
> > +                          &address_space_memory);
> > +
> > +    return fdt_addr;
> > +}
> > +
> > +static void openrisc_create_fdt(Or1ksimState *s,
> > +    const struct MemmapEntry *memmap, int num_cpus, uint64_t mem_size,
> > +    const char *cmdline)
> 
> Indentation.

Right, fixed.

> > +{
> > +    void *fdt;
> > +    int cpu;
> > +    char *nodename;
> > +    int pic_ph;
> > +
> > +    fdt = s->fdt = create_device_tree(&s->fdt_size);
> > +    if (!fdt) {
> > +        error_report("create_device_tree() failed");
> > +        exit(1);
> > +    }
> > +
> > +    qemu_fdt_setprop_string(fdt, "/", "compatible", "opencores,or1ksim");
> > +    qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x1);
> > +    qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x1);
> > +
> > +    nodename = g_strdup_printf("/memory@%lx",
> > +                               (long)memmap[OR1KSIM_DRAM].base);
> 
> Use the appropriate format string macro for the type, rather than
> casting to long (here and below).

Right good point.

> > +    qemu_fdt_add_subnode(fdt, nodename);
> > +    qemu_fdt_setprop_cells(fdt, nodename, "reg",
> > +                           memmap[OR1KSIM_DRAM].base, mem_size);
> > +    qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory");
> > +    g_free(nodename);
> > +
> > +    qemu_fdt_add_subnode(fdt, "/cpus");
> > +    qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0);
> > +    qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1);
> > +
> > +    for (cpu = 0; cpu < num_cpus; cpu++) {
> > +        nodename = g_strdup_printf("/cpus/cpu@%d", cpu);
> > +        qemu_fdt_add_subnode(fdt, nodename);
> > +        qemu_fdt_setprop_string(fdt, nodename, "compatible",
> > +                                "opencores,or1200-rtlsvn481");
> > +        qemu_fdt_setprop_cell(fdt, nodename, "reg", cpu);
> > +        qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
> > +                              OR1KSIM_CLK_MHZ);
> > +        g_free(nodename);
> > +    }
> > +
> > +    if (num_cpus > 0) {
> > +        nodename = g_strdup_printf("/ompic@%lx",
> > +                                   (long)memmap[OR1KSIM_OMPIC].base);
> > +        qemu_fdt_add_subnode(fdt, nodename);
> > +        qemu_fdt_setprop_string(fdt, nodename, "compatible", "openrisc,ompic");
> > +        qemu_fdt_setprop_cells(fdt, nodename, "reg",
> > +                               memmap[OR1KSIM_OMPIC].base,
> > +                               memmap[OR1KSIM_OMPIC].size);
> > +        qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
> > +        qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 0);
> > +        qemu_fdt_setprop_cell(fdt, nodename, "interrupts", OR1KSIM_OMPIC_IRQ);
> > +        g_free(nodename);
> >      }
> > +
> > +    nodename = (char *)"/pic";
> > +    qemu_fdt_add_subnode(fdt, nodename);
> > +    pic_ph = qemu_fdt_alloc_phandle(fdt);
> > +    qemu_fdt_setprop_string(fdt, nodename, "compatible",
> > +                            "opencores,or1k-pic-level");
> > +    qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1);
> > +    qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
> > +    qemu_fdt_setprop_cell(fdt, nodename, "phandle", pic_ph);
> > +
> > +    qemu_fdt_setprop_cell(fdt, "/", "interrupt-parent", pic_ph);
> > +
> > +    if (nd_table[0].used) {
> > +        nodename = g_strdup_printf("/ethoc@%lx",
> > +                                   (long)memmap[OR1KSIM_ETHOC].base);
> > +        qemu_fdt_add_subnode(fdt, nodename);
> > +        qemu_fdt_setprop_string(fdt, nodename, "compatible", "opencores,ethoc");
> > +        qemu_fdt_setprop_cells(fdt, nodename, "reg",
> > +                               memmap[OR1KSIM_ETHOC].base,
> > +                               memmap[OR1KSIM_ETHOC].size);
> > +        qemu_fdt_setprop_cell(fdt, nodename, "interrupts", OR1KSIM_ETHOC_IRQ);
> > +        qemu_fdt_setprop(fdt, nodename, "big-endian", NULL, 0);
> > +
> > +        qemu_fdt_add_subnode(fdt, "/aliases");
> > +        qemu_fdt_setprop_string(fdt, "/aliases", "enet0", nodename);
> > +        g_free(nodename);
> > +    }
> > +
> > +    nodename = g_strdup_printf("/serial@%lx",
> > +                               (long)memmap[OR1KSIM_UART].base);
> > +    qemu_fdt_add_subnode(fdt, nodename);
> > +    qemu_fdt_setprop_string(fdt, nodename, "compatible", "ns16550a");
> > +    qemu_fdt_setprop_cells(fdt, nodename, "reg",
> > +                           memmap[OR1KSIM_UART].base,
> > +                           memmap[OR1KSIM_UART].size);
> > +    qemu_fdt_setprop_cell(fdt, nodename, "interrupts", OR1KSIM_UART_IRQ);
> > +    qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", OR1KSIM_CLK_MHZ);
> > +    qemu_fdt_setprop(fdt, nodename, "big-endian", NULL, 0);
> > +
> > +    qemu_fdt_add_subnode(fdt, "/chosen");
> > +    qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename);
> > +    if (cmdline) {
> > +        qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
> > +    }
> > +
> > +    qemu_fdt_setprop_string(fdt, "/aliases", "uart0", nodename);
> 
> I think the pattern the hw/arm/virt.c code uses, where the board
> code functions that create the UART, interrupt controller, etc
> devices on the board also have the code to add FDT nodes for them.
> Especially as the board gets new devices added over time, it's easier
> to check that the FDT nodes and the devices match up, and you don't
> have to awkwardly duplicate control-flow logic like "we only have
> an ethernet device if nd_table[0].used". But I won't insist that
> you rewrite this.

Right, this makes sense.  I might as well split it out.  I did it that way for
initrd.  I it may make sense to do for UART, OMPIC and Ethernet here.

> > +    g_free(nodename);
> >  }
> >
> >  static void openrisc_sim_init(MachineState *machine)
> > @@ -178,6 +323,7 @@ static void openrisc_sim_init(MachineState *machine)
> >      OpenRISCCPU *cpus[2] = {};
> >      Or1ksimState *s = OR1KSIM_MACHINE(machine);
> >      MemoryRegion *ram;
> > +    hwaddr load_addr;
> >      qemu_irq serial_irq;
> >      int n;
> >      unsigned int smp_cpus = machine->smp.cpus;
> > @@ -219,7 +365,11 @@ static void openrisc_sim_init(MachineState *machine)
> >      serial_mm_init(get_system_memory(), or1ksim_memmap[OR1KSIM_UART].base, 0,
> >                     serial_irq, 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);
> >
> > -    openrisc_load_kernel(ram_size, kernel_filename);
> > +    openrisc_create_fdt(s, or1ksim_memmap, smp_cpus, machine->ram_size,
> > +                        machine->kernel_cmdline);
> > +
> > +    load_addr = openrisc_load_kernel(ram_size, kernel_filename);
> > +    boot_info.fdt_addr = openrisc_load_fdt(s, load_addr, machine->ram_size);
> >  }
> 
> If the user doesn't specify a kernel file, we'll still load the FDT,
> at address zero. Is that sensible/intended behaviour ?

Good point,  I guess we can add some space to not override the interrupt
vectors.  The system booting with no kernel will probably not very useful
anyway.  But I imaging one could connect a debugger and load some binary into
memory and having the FDT in memory would be helpful.

So moving the fdt offset to 0 + 1-page would give enough space.  Does this sound
OK?

-Stafford


  reply	other threads:[~2022-02-17 21:41 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-10  6:30 [PATCH 0/4] OpenRISC Device Tree Support Stafford Horne
2022-02-10  6:30 ` [PATCH 1/4] hw/openrisc/openrisc_sim: Create machine state for or1ksim Stafford Horne
2022-02-10 11:05   ` Philippe Mathieu-Daudé via
2022-02-10 12:16     ` Stafford Horne
2022-02-10  6:30 ` [PATCH 2/4] hw/openrisc/openrisc_sim: Paramatarize initialization Stafford Horne
2022-02-10 11:07   ` Philippe Mathieu-Daudé via
2022-02-10 12:18     ` Stafford Horne
2022-02-10  6:30 ` [PATCH 3/4] hw/openrisc/openrisc_sim; Add support for loading a decice tree Stafford Horne
2022-02-10 11:10   ` Philippe Mathieu-Daudé via
2022-02-10 12:34     ` Stafford Horne
2022-02-17 18:18   ` Peter Maydell
2022-02-17 21:39     ` Stafford Horne [this message]
2022-02-18 11:46       ` Peter Maydell
2022-02-10  6:30 ` [PATCH 4/4] hw/openrisc/openrisc_sim: Add support for initrd loading Stafford Horne

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=Yg7AeSuZOEW3nT26@antec \
    --to=shorne@gmail.com \
    --cc=peter.maydell@linaro.org \
    --cc=proljc@gmail.com \
    --cc=qemu-devel@nongnu.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.