qemu-riscv
[Top][All Lists]
Advanced

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

Re: [Qemu-riscv] [Qemu-devel] [PATCH for-4.1 2/2] target/riscv: Add supp


From: Alistair Francis
Subject: Re: [Qemu-riscv] [Qemu-devel] [PATCH for-4.1 2/2] target/riscv: Add support for -bios "firmware_filename" flag
Date: Fri, 17 May 2019 15:36:28 -0700

On Fri, May 17, 2019 at 3:25 PM Jonathan Behrens <address@hidden> wrote:
>
> QEMU does not have any default firmware for RISC-V. However, it isn't possible
> to run a normal kernel binary without firmware. Thus it has previously been
> necessary to compile the two together into a single binary to pass with the
> -kernel flag. This patch allows passing separate firmware and kernel binaries 
> by
> passing both the -bios and -kernel flags.

I've never been fully convinced of this, why not just use the generic loader?

This does match other architectures though so it's fine to go in. I
think you will also get better in_asm output with this as well, which
is something the loader doesn't give you.

>
> This is based on a previously proposed patch by Michael Clark:
> https://patchwork.kernel.org/patch/10419975/
>
> Signed-off-by: Jonathan Behrens <address@hidden>
> ---
>  hw/riscv/virt.c | 66 ++++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 55 insertions(+), 11 deletions(-)
>
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 87cc08016b..d7b1792b58 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -62,6 +62,40 @@ static const struct MemmapEntry {
>      [VIRT_PCIE_ECAM] =   { 0x30000000,    0x10000000 },
>  };
>
> +
> +static target_ulong load_firmware_and_kernel(const char *firmware_filename,
> +                                             const char *kernel_filename,
> +                                             uint64_t mem_size,
> +                                             uint64_t* kernel_start,
> +                                             uint64_t* kernel_end)
> +{
> +    uint64_t firmware_entry, firmware_end;
> +    int size;
> +
> +    if (load_elf(firmware_filename, NULL, NULL, NULL,
> +                 &firmware_entry, NULL, &firmware_end,
> +                 0, EM_RISCV, 1, 0) < 0) {
> +        error_report("could not load firmware '%s'", firmware_filename);
> +        exit(1);
> +    }
> +
> +    /* align kernel load address to the megapage after the firmware */
> +#if defined(TARGET_RISCV32)
> +    *kernel_start = (firmware_end + 0x3fffff) & ~0x3fffff;
> +#else
> +    *kernel_start = (firmware_end + 0x1fffff) & ~0x1fffff;
> +#endif
> +
> +    size = load_image_targphys(kernel_filename, *kernel_start,
> +                               mem_size - *kernel_start);
> +    if (size == -1) {
> +        error_report("could not load kernel '%s'", kernel_filename);
> +        exit(1);
> +    }
> +    *kernel_end = *kernel_start + size;
> +    return firmware_entry;
> +}

This should be in a generic boot.c file and support added to all RISC-V boards.

Alistair

> +
>  static target_ulong load_kernel(const char *kernel_filename)
>  {
>      uint64_t kernel_entry;
> @@ -423,19 +457,29 @@ static void riscv_virt_board_init(MachineState *machine)
>                                  mask_rom);
>
>      uint64_t entry = memmap[VIRT_DRAM].base;
> -    if (machine->kernel_filename) {
> +    if (machine->firmware && machine->kernel_filename) {
> +        uint64_t kernel_start, kernel_end;
> +        entry = load_firmware_and_kernel(machine->firmware,
> +                                         machine->kernel_filename,
> +                                         machine->ram_size, &kernel_start,
> +                                         &kernel_end);
> +
> +        qemu_fdt_setprop_cells(fdt, "/chosen", "riscv,kernel-end",
> +                               kernel_end >> 32, kernel_end);
> +        qemu_fdt_setprop_cells(fdt, "/chosen", "riscv,kernel-start",
> +                               kernel_start >> 32, kernel_start);
> +    } else if (machine->kernel_filename) {
>          entry = load_kernel(machine->kernel_filename);
> +    }
>
> -        if (machine->initrd_filename) {
> -            uint64_t start;
> -            uint64_t end = load_initrd(machine->initrd_filename,
> -                                       memmap[VIRT_DRAM].base, 
> machine->ram_size,
> -                                       &start);
> -            qemu_fdt_setprop_cell(fdt, "/chosen",
> -                                  "linux,initrd-start", start);
> -            qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end",
> -                                  end);
> -        }
> +    if (machine->kernel_filename && machine->initrd_filename) {
> +        uint64_t start;
> +        uint64_t end = load_initrd(machine->initrd_filename,
> +                                   memmap[VIRT_DRAM].base, machine->ram_size,
> +                                   &start);
> +
> +        qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start);
> +        qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end);
>      }
>
>      /* reset vector */
> --
> 2.20.1
>



reply via email to

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