summary refs log tree commit diff stats
path: root/hw/riscv/sifive_u.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-07-14 17:58:00 +0100
committerPeter Maydell <peter.maydell@linaro.org>2020-07-14 17:58:00 +0100
commitaeb07b5f6e69ce93afea71027325e3e7a22d2149 (patch)
treeb69b0b816316aa827aff123efcf3f72f5c559233 /hw/riscv/sifive_u.c
parentbeff47a2f6a8295161f98a9dac94e18e5376e749 (diff)
parentcfad709bceb629a4ebeb5d8a3acd1871b9a6436b (diff)
downloadfocaccia-qemu-aeb07b5f6e69ce93afea71027325e3e7a22d2149.tar.gz
focaccia-qemu-aeb07b5f6e69ce93afea71027325e3e7a22d2149.zip
Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20200713' into staging
This is a colection of bug fixes and small imrprovements for RISC-V.

This includes some vector extensions fixes, a PMP bug fix, OpenTitan
UART bug fix and support for OpenSBI dynamic firmware.

# gpg: Signature made Tue 14 Jul 2020 01:29:44 BST
# gpg:                using RSA key F6C4AC46D4934868D3B8CE8F21E10D29DF977054
# gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [full]
# Primary key fingerprint: F6C4 AC46 D493 4868 D3B8  CE8F 21E1 0D29 DF97 7054

* remotes/alistair/tags/pull-riscv-to-apply-20200713:
  target/riscv: Fix pmp NA4 implementation
  tcg/riscv: Remove superfluous breaks
  hw/char: Convert the Ibex UART to use the registerfields API
  hw/char: Convert the Ibex UART to use the qdev Clock model
  target/riscv: fix vill bit index in vtype register
  target/riscv: fix return value of do_opivx_widen()
  target/riscv: correct the gvec IR called in gen_vec_rsub16_i64()
  target/riscv: fix rsub gvec tcg_assert_listed_vecop assertion
  hw/riscv: Modify MROM size to end at 0x10000
  RISC-V: Support 64 bit start address
  riscv: Add opensbi firmware dynamic support
  RISC-V: Copy the fdt in dram instead of ROM
  riscv: Unify Qemu's reset vector code path
  hw/riscv: virt: Sort the SoC memmap table entries
  MAINTAINERS: Add an entry for OpenSBI firmware

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/riscv/sifive_u.c')
-rw-r--r--hw/riscv/sifive_u.c53
1 files changed, 32 insertions, 21 deletions
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 7851326988..19a976c9a6 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -56,7 +56,6 @@
 #include "sysemu/device_tree.h"
 #include "sysemu/runstate.h"
 #include "sysemu/sysemu.h"
-#include "exec/address-spaces.h"
 
 #include <libfdt.h>
 
@@ -71,7 +70,7 @@ static const struct MemmapEntry {
     hwaddr size;
 } sifive_u_memmap[] = {
     [SIFIVE_U_DEBUG] =    {        0x0,      0x100 },
-    [SIFIVE_U_MROM] =     {     0x1000,    0x11000 },
+    [SIFIVE_U_MROM] =     {     0x1000,     0xf000 },
     [SIFIVE_U_CLINT] =    {  0x2000000,    0x10000 },
     [SIFIVE_U_L2LIM] =    {  0x8000000,  0x2000000 },
     [SIFIVE_U_PLIC] =     {  0xc000000,  0x4000000 },
@@ -379,7 +378,10 @@ static void sifive_u_machine_init(MachineState *machine)
     MemoryRegion *main_mem = g_new(MemoryRegion, 1);
     MemoryRegion *flash0 = g_new(MemoryRegion, 1);
     target_ulong start_addr = memmap[SIFIVE_U_DRAM].base;
+    uint32_t start_addr_hi32 = 0x00000000;
     int i;
+    uint32_t fdt_load_addr;
+    uint64_t kernel_entry;
 
     /* Initialize SoC */
     object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_U_SOC);
@@ -436,8 +438,7 @@ static void sifive_u_machine_init(MachineState *machine)
     riscv_find_and_load_firmware(machine, BIOS_FILENAME, start_addr, NULL);
 
     if (machine->kernel_filename) {
-        uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename,
-                                                  NULL);
+        kernel_entry = riscv_load_kernel(machine->kernel_filename, NULL);
 
         if (machine->initrd_filename) {
             hwaddr start;
@@ -449,42 +450,52 @@ static void sifive_u_machine_init(MachineState *machine)
             qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end",
                                   end);
         }
+    } else {
+       /*
+        * If dynamic firmware is used, it doesn't know where is the next mode
+        * if kernel argument is not set.
+        */
+        kernel_entry = 0;
     }
 
+    /* Compute the fdt load address in dram */
+    fdt_load_addr = riscv_load_fdt(memmap[SIFIVE_U_DRAM].base,
+                                   machine->ram_size, s->fdt);
+    #if defined(TARGET_RISCV64)
+    start_addr_hi32 = start_addr >> 32;
+    #endif
+
     /* reset vector */
-    uint32_t reset_vec[8] = {
+    uint32_t reset_vec[11] = {
         s->msel,                       /* MSEL pin state */
-        0x00000297,                    /* 1:  auipc  t0, %pcrel_hi(dtb) */
-        0x01c28593,                    /*     addi   a1, t0, %pcrel_lo(1b) */
+        0x00000297,                    /* 1:  auipc  t0, %pcrel_hi(fw_dyn) */
+        0x02828613,                    /*     addi   a2, t0, %pcrel_lo(1b) */
         0xf1402573,                    /*     csrr   a0, mhartid  */
 #if defined(TARGET_RISCV32)
+        0x0202a583,                    /*     lw     a1, 32(t0) */
         0x0182a283,                    /*     lw     t0, 24(t0) */
 #elif defined(TARGET_RISCV64)
-        0x0182e283,                    /*     lwu    t0, 24(t0) */
+        0x0202b583,                    /*     ld     a1, 32(t0) */
+        0x0182b283,                    /*     ld     t0, 24(t0) */
 #endif
         0x00028067,                    /*     jr     t0 */
-        0x00000000,
         start_addr,                    /* start: .dword */
-                                       /* dtb: */
+        start_addr_hi32,
+        fdt_load_addr,                 /* fdt_laddr: .dword */
+        0x00000000,
+                                       /* fw_dyn: */
     };
 
     /* copy in the reset vector in little_endian byte order */
-    for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
+    for (i = 0; i < ARRAY_SIZE(reset_vec); i++) {
         reset_vec[i] = cpu_to_le32(reset_vec[i]);
     }
     rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
                           memmap[SIFIVE_U_MROM].base, &address_space_memory);
 
-    /* copy in the device tree */
-    if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) >
-            memmap[SIFIVE_U_MROM].size - sizeof(reset_vec)) {
-        error_report("not enough space to store device-tree");
-        exit(1);
-    }
-    qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt));
-    rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt),
-                          memmap[SIFIVE_U_MROM].base + sizeof(reset_vec),
-                          &address_space_memory);
+    riscv_rom_copy_firmware_info(memmap[SIFIVE_U_MROM].base,
+                                 memmap[SIFIVE_U_MROM].size,
+                                 sizeof(reset_vec), kernel_entry);
 }
 
 static bool sifive_u_machine_get_start_in_flash(Object *obj, Error **errp)