qemu-riscv
[Top][All Lists]
Advanced

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

Re: [PATCH 12/12] hw/riscv: spike: Decouple create_fdt() dependency to E


From: Daniel Henrique Barboza
Subject: Re: [PATCH 12/12] hw/riscv: spike: Decouple create_fdt() dependency to ELF loading
Date: Tue, 27 Dec 2022 11:33:12 -0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.6.0

Hi Bin,

On 12/27/22 03:48, Bin Meng wrote:
At present create_fdt() calls htif_uses_elf_symbols() to determine
whether to insert a <reg> property for the HTIF. This unfortunately
creates a hidden dependency to riscv_load_{firmware,kernel} that
create_fdt() must be called after the ELF {firmware,kernel} image
has been loaded.

Decouple such dependency be adding a new parameter to create_fdt(),
whether custom HTIF base address is used. The flag will be set if
non ELF {firmware,kernel} image is given by user.

Signed-off-by: Bin Meng <bmeng@tinylab.org>

---

  include/hw/char/riscv_htif.h |  5 +---
  hw/char/riscv_htif.c         | 17 +++++-------
  hw/riscv/spike.c             | 54 ++++++++++++++++++++++++++++++------
  3 files changed, 53 insertions(+), 23 deletions(-)

diff --git a/include/hw/char/riscv_htif.h b/include/hw/char/riscv_htif.h
index 9e8ebbe017..5958c5b986 100644
--- a/include/hw/char/riscv_htif.h
+++ b/include/hw/char/riscv_htif.h
@@ -44,11 +44,8 @@ typedef struct HTIFState {
  void htif_symbol_callback(const char *st_name, int st_info, uint64_t st_value,
      uint64_t st_size);
-/* Check if HTIF uses ELF symbols */
-bool htif_uses_elf_symbols(void);
-
  /* legacy pre qom */
  HTIFState *htif_mm_init(MemoryRegion *address_space, Chardev *chr,
-                        uint64_t nonelf_base);
+                        uint64_t nonelf_base, bool custom_base);
#endif
diff --git a/hw/char/riscv_htif.c b/hw/char/riscv_htif.c
index 1477fc0090..098de50e35 100644
--- a/hw/char/riscv_htif.c
+++ b/hw/char/riscv_htif.c
@@ -52,20 +52,17 @@
  #define PK_SYS_WRITE            64
static uint64_t fromhost_addr, tohost_addr;
-static int address_symbol_set;
void htif_symbol_callback(const char *st_name, int st_info, uint64_t st_value,
                            uint64_t st_size)
  {
      if (strcmp("fromhost", st_name) == 0) {
-        address_symbol_set |= 1;
          fromhost_addr = st_value;
          if (st_size != 8) {
              error_report("HTIF fromhost must be 8 bytes");
              exit(1);
          }
      } else if (strcmp("tohost", st_name) == 0) {
-        address_symbol_set |= 2;
          tohost_addr = st_value;
          if (st_size != 8) {
              error_report("HTIF tohost must be 8 bytes");
@@ -275,19 +272,19 @@ static const MemoryRegionOps htif_mm_ops = {
      .write = htif_mm_write,
  };
-bool htif_uses_elf_symbols(void)
-{
-    return (address_symbol_set == 3) ? true : false;
-}
-
  HTIFState *htif_mm_init(MemoryRegion *address_space, Chardev *chr,
-                        uint64_t nonelf_base)
+                        uint64_t nonelf_base, bool custom_base)
  {
      uint64_t base, size, tohost_offset, fromhost_offset;
- if (!htif_uses_elf_symbols()) {
+    if (custom_base) {
          fromhost_addr = nonelf_base;
          tohost_addr = nonelf_base + 8;
+    } else {
+        if (!fromhost_addr || !tohost_addr) {
+            error_report("Invalid HTIF fromhost or tohost address");
+            exit(1);
+        }
      }
base = MIN(tohost_addr, fromhost_addr);
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 810a18f283..90f9e581e4 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -50,7 +50,8 @@ static const MemMapEntry spike_memmap[] = {
  };
static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
-                       uint64_t mem_size, const char *cmdline, bool is_32_bit)
+                       uint64_t mem_size, const char *cmdline,
+                       bool is_32_bit, bool htif_custom_base)
  {
      void *fdt;
      uint64_t addr, size;
@@ -78,7 +79,7 @@ static void create_fdt(SpikeState *s, const MemMapEntry 
*memmap,
qemu_fdt_add_subnode(fdt, "/htif");
      qemu_fdt_setprop_string(fdt, "/htif", "compatible", "ucb,htif0");
-    if (!htif_uses_elf_symbols()) {
+    if (htif_custom_base) {
          qemu_fdt_setprop_cells(fdt, "/htif", "reg",
              0x0, memmap[SPIKE_HTIF].base, 0x0, memmap[SPIKE_HTIF].size);
      }
@@ -184,6 +185,21 @@ static void create_fdt(SpikeState *s, const MemMapEntry 
*memmap,
      }
  }
+static bool spike_test_elf_image(char *filename)
+{
+    Error *err = NULL;
+
+    if (filename) {
+        load_elf_hdr(filename, NULL, NULL, &err);
+        if (err) {
+            error_free(err);
+            return false;
+        }
+    }
+
+    return true;
+}
+
  static void spike_board_init(MachineState *machine)
  {
      const MemMapEntry *memmap = spike_memmap;
@@ -191,11 +207,12 @@ static void spike_board_init(MachineState *machine)
      MemoryRegion *system_memory = get_system_memory();
      MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
      target_ulong firmware_end_addr, kernel_start_addr;
-    const char *firmware_name;
+    char *firmware_name;
      uint32_t fdt_load_addr;
      uint64_t kernel_entry;
      char *soc_name;
      int i, base_hartid, hart_count;
+    bool htif_custom_base;
/* Check socket count limit */
      if (SPIKE_SOCKETS_MAX < riscv_socket_count(machine)) {
@@ -257,10 +274,28 @@ static void spike_board_init(MachineState *machine)
      memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
                                  mask_rom);
- firmware_name = riscv_default_firmware_name(&s->soc[0]);
-    firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
-                                                     memmap[SPIKE_DRAM].base,
-                                                     htif_symbol_callback);
+    /* Find firmware */
+    firmware_name = riscv_find_firmware(machine->firmware,
+                        riscv_default_firmware_name(&s->soc[0]));
+
+    /*
+     * Test the given firmware or kernel file to see if it is an ELF image.
+     * If it is an ELF, we assume it contains the symbols required for
+     * the HTIF console, otherwise we fall back to use the custom base
+     * passed from device tree for the HTIF console.
+     */
+    htif_custom_base = !spike_test_elf_image(firmware_name);
+    if (!htif_custom_base) {
+        htif_custom_base = !spike_test_elf_image(machine->kernel_filename);
+    }
+
+    /* Load firmware */
+    if (firmware_name) {
+        firmware_end_addr = riscv_load_firmware(firmware_name,
+                                                memmap[SPIKE_DRAM].base,
+                                                htif_symbol_callback);
+        g_free(firmware_name);
+    }
/* Load kernel */
      if (machine->kernel_filename) {

'make' is giving me a maybe-uninitialized error in this point:

../hw/riscv/spike.c: In function ‘spike_board_init’:
../hw/riscv/spike.c:301:29: error: ‘firmware_end_addr’ may be used 
uninitialized [-Werror=maybe-uninitialized]
  301 |         kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0],
      | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  302 | firmware_end_addr);
      | ~~~~~~~~~~~~~~~~~~
../hw/riscv/spike.c:208:18: note: ‘firmware_end_addr’ was declared here
  208 |     target_ulong firmware_end_addr, kernel_start_addr;
      |                  ^~~~~~~~~~~~~~~~~


The full context:


    /* Load firmware */
    if (firmware_name) {
        firmware_end_addr = riscv_load_firmware(firmware_name,
memmap[SPIKE_DRAM].base,
htif_symbol_callback);
        g_free(firmware_name);
    }

    /* Load kernel */
    if (machine->kernel_filename) {
        kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0],
firmware_end_addr);

        kernel_entry = riscv_load_kernel(machine->kernel_filename,
                                         kernel_start_addr,
                                         htif_symbol_callback);
    } else {


The error is happening because, with this patch, 'firmware_end_addr' may not be
initialized via riscv_load_firmware() because we're not guaranteeing that
'firmware_name' will be valid.

riscv_load_firmware() is guaranteed to either return > 0 or error out with 
exit(1),
so a simple fix would be to initialize 'firmware_end_addr' with 0.



Thanks,

Daniel


@@ -280,7 +315,7 @@ static void spike_board_init(MachineState *machine)
/* Create device tree */
      create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
-               riscv_is_32bit(&s->soc[0]));
+               riscv_is_32bit(&s->soc[0]), htif_custom_base);
/* Load initrd */
      if (machine->kernel_filename && machine->initrd_filename) {
@@ -308,7 +343,8 @@ static void spike_board_init(MachineState *machine)
                                fdt_load_addr);
/* initialize HTIF using symbols found in load_kernel */
-    htif_mm_init(system_memory, serial_hd(0), memmap[SPIKE_HTIF].base);
+    htif_mm_init(system_memory, serial_hd(0), memmap[SPIKE_HTIF].base,
+                 htif_custom_base);
  }
static void spike_machine_instance_init(Object *obj)




reply via email to

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