aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-06-08 13:54:23 +0100
committerPeter Maydell <peter.maydell@linaro.org>2021-06-08 13:54:23 +0100
commita4716fd8d7c877185652f5f8e25032dc7699d51b (patch)
treeb89e4cabdf30fb88a514c243522028c5719ed681 /hw
parent33ba8b0adc91482dd4247a0773cfe7def011933f (diff)
parentd2c1a177b138be35cb96216baa870c3564b123e4 (diff)
Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20210608-1' into staging
Second RISC-V PR for QEMU 6.1 - Update the PLIC and CLINT DT bindings - Improve documentation for RISC-V machines - Support direct kernel boot for microchip_pfsoc - Fix WFI exception behaviour - Improve CSR printing - Initial support for the experimental Bit Manip extension # gpg: Signature made Tue 08 Jun 2021 01:28:27 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-20210608-1: (32 commits) target/riscv: rvb: add b-ext version cpu option target/riscv: rvb: support and turn on B-extension from command line target/riscv: rvb: add/shift with prefix zero-extend target/riscv: rvb: address calculation target/riscv: rvb: generalized or-combine target/riscv: rvb: generalized reverse target/riscv: rvb: rotate (left/right) target/riscv: rvb: shift ones target/riscv: rvb: single-bit instructions target/riscv: add gen_shifti() and gen_shiftiw() helper functions target/riscv: rvb: sign-extend instructions target/riscv: rvb: min/max instructions target/riscv: rvb: pack two words into one register target/riscv: rvb: logic-with-negate target/riscv: rvb: count bits set target/riscv: rvb: count leading/trailing zeros target/riscv: reformat @sh format encoding for B-extension target/riscv: Pass the same value to oprsz and maxsz. target/riscv/pmp: Add assert for ePMP operations target/riscv: Dump CSR mscratch/sscratch/satp ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/riscv/microchip_pfsoc.c81
-rw-r--r--hw/riscv/sifive_u.c24
-rw-r--r--hw/riscv/spike.c12
-rw-r--r--hw/riscv/virt.c25
4 files changed, 117 insertions, 25 deletions
diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
index 6cbd17ebf2..eb8e79e0a1 100644
--- a/hw/riscv/microchip_pfsoc.c
+++ b/hw/riscv/microchip_pfsoc.c
@@ -51,6 +51,7 @@
#include "hw/riscv/microchip_pfsoc.h"
#include "hw/intc/sifive_clint.h"
#include "hw/intc/sifive_plic.h"
+#include "sysemu/device_tree.h"
#include "sysemu/sysemu.h"
/*
@@ -460,6 +461,12 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
MemoryRegion *mem_high = g_new(MemoryRegion, 1);
MemoryRegion *mem_high_alias = g_new(MemoryRegion, 1);
uint64_t mem_high_size;
+ hwaddr firmware_load_addr;
+ const char *firmware_name;
+ bool kernel_as_payload = false;
+ target_ulong firmware_end_addr, kernel_start_addr;
+ uint64_t kernel_entry;
+ uint32_t fdt_load_addr;
DriveInfo *dinfo = drive_get_next(IF_SD);
/* Sanity check on RAM size */
@@ -504,9 +511,6 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
memmap[MICROCHIP_PFSOC_DRAM_HI_ALIAS].base,
mem_high_alias);
- /* Load the firmware */
- riscv_find_and_load_firmware(machine, BIOS_FILENAME, RESET_VECTOR, NULL);
-
/* Attach an SD card */
if (dinfo) {
CadenceSDHCIState *sdhci = &(s->soc.sdhci);
@@ -516,6 +520,77 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
&error_fatal);
qdev_realize_and_unref(card, sdhci->bus, &error_fatal);
}
+
+ /*
+ * We follow the following table to select which payload we execute.
+ *
+ * -bios | -kernel | payload
+ * -------+------------+--------
+ * N | N | HSS
+ * Y | don't care | HSS
+ * N | Y | kernel
+ *
+ * This ensures backwards compatibility with how we used to expose -bios
+ * to users but allows them to run through direct kernel booting as well.
+ *
+ * When -kernel is used for direct boot, -dtb must be present to provide
+ * a valid device tree for the board, as we don't generate device tree.
+ */
+
+ if (machine->kernel_filename && machine->dtb) {
+ int fdt_size;
+ machine->fdt = load_device_tree(machine->dtb, &fdt_size);
+ if (!machine->fdt) {
+ error_report("load_device_tree() failed");
+ exit(1);
+ }
+
+ firmware_name = RISCV64_BIOS_BIN;
+ firmware_load_addr = memmap[MICROCHIP_PFSOC_DRAM_LO].base;
+ kernel_as_payload = true;
+ }
+
+ if (!kernel_as_payload) {
+ firmware_name = BIOS_FILENAME;
+ firmware_load_addr = RESET_VECTOR;
+ }
+
+ /* Load the firmware */
+ firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
+ firmware_load_addr, NULL);
+
+ if (kernel_as_payload) {
+ kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus,
+ firmware_end_addr);
+
+ kernel_entry = riscv_load_kernel(machine->kernel_filename,
+ kernel_start_addr, NULL);
+
+ if (machine->initrd_filename) {
+ hwaddr start;
+ hwaddr end = riscv_load_initrd(machine->initrd_filename,
+ machine->ram_size, kernel_entry,
+ &start);
+ qemu_fdt_setprop_cell(machine->fdt, "/chosen",
+ "linux,initrd-start", start);
+ qemu_fdt_setprop_cell(machine->fdt, "/chosen",
+ "linux,initrd-end", end);
+ }
+
+ if (machine->kernel_cmdline) {
+ qemu_fdt_setprop_string(machine->fdt, "/chosen",
+ "bootargs", machine->kernel_cmdline);
+ }
+
+ /* Compute the fdt load address in dram */
+ fdt_load_addr = riscv_load_fdt(memmap[MICROCHIP_PFSOC_DRAM_LO].base,
+ machine->ram_size, machine->fdt);
+ /* Load the reset vector */
+ riscv_setup_rom_reset_vec(machine, &s->soc.u_cpus, firmware_load_addr,
+ memmap[MICROCHIP_PFSOC_ENVM_DATA].base,
+ memmap[MICROCHIP_PFSOC_ENVM_DATA].size,
+ kernel_entry, fdt_load_addr, machine->fdt);
+ }
}
static void microchip_icicle_kit_machine_class_init(ObjectClass *oc, void *data)
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 698637e8e1..273c86418c 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -95,9 +95,15 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
int cpu;
uint32_t *cells;
char *nodename;
- char ethclk_names[] = "pclk\0hclk";
uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1;
uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle;
+ static const char * const ethclk_names[2] = { "pclk", "hclk" };
+ static const char * const clint_compat[2] = {
+ "sifive,clint0", "riscv,clint0"
+ };
+ static const char * const plic_compat[2] = {
+ "sifive,plic-1.0.0", "riscv,plic0"
+ };
if (ms->dtb) {
fdt = s->fdt = load_device_tree(ms->dtb, &s->fdt_size);
@@ -209,7 +215,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
nodename = g_strdup_printf("/soc/clint@%lx",
(long)memmap[SIFIVE_U_DEV_CLINT].base);
qemu_fdt_add_subnode(fdt, nodename);
- qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,clint0");
+ qemu_fdt_setprop_string_array(fdt, nodename, "compatible",
+ (char **)&clint_compat, ARRAY_SIZE(clint_compat));
qemu_fdt_setprop_cells(fdt, nodename, "reg",
0x0, memmap[SIFIVE_U_DEV_CLINT].base,
0x0, memmap[SIFIVE_U_DEV_CLINT].size);
@@ -266,7 +273,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
(long)memmap[SIFIVE_U_DEV_PLIC].base);
qemu_fdt_add_subnode(fdt, nodename);
qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1);
- qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,plic0");
+ qemu_fdt_setprop_string_array(fdt, nodename, "compatible",
+ (char **)&plic_compat, ARRAY_SIZE(plic_compat));
qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0);
qemu_fdt_setprop(fdt, nodename, "interrupts-extended",
cells, (ms->smp.cpus * 4 - 2) * sizeof(uint32_t));
@@ -412,8 +420,8 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap,
qemu_fdt_setprop_cell(fdt, nodename, "interrupts", SIFIVE_U_GEM_IRQ);
qemu_fdt_setprop_cells(fdt, nodename, "clocks",
prci_phandle, PRCI_CLK_GEMGXLPLL, prci_phandle, PRCI_CLK_GEMGXLPLL);
- qemu_fdt_setprop(fdt, nodename, "clock-names", ethclk_names,
- sizeof(ethclk_names));
+ qemu_fdt_setprop_string_array(fdt, nodename, "clock-names",
+ (char **)&ethclk_names, ARRAY_SIZE(ethclk_names));
qemu_fdt_setprop(fdt, nodename, "local-mac-address",
s->soc.gem.conf.macaddr.a, ETH_ALEN);
qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", 1);
@@ -552,12 +560,10 @@ static void sifive_u_machine_init(MachineState *machine)
if (riscv_is_32bit(&s->soc.u_cpus)) {
firmware_end_addr = riscv_find_and_load_firmware(machine,
- "opensbi-riscv32-generic-fw_dynamic.bin",
- start_addr, NULL);
+ RISCV32_BIOS_BIN, start_addr, NULL);
} else {
firmware_end_addr = riscv_find_and_load_firmware(machine,
- "opensbi-riscv64-generic-fw_dynamic.bin",
- start_addr, NULL);
+ RISCV64_BIOS_BIN, start_addr, NULL);
}
if (machine->kernel_filename) {
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index fe0806a476..fead77f0c4 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -59,6 +59,9 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
uint32_t cpu_phandle, intc_phandle, phandle = 1;
char *name, *mem_name, *clint_name, *clust_name;
char *core_name, *cpu_name, *intc_name;
+ static const char * const clint_compat[2] = {
+ "sifive,clint0", "riscv,clint0"
+ };
fdt = s->fdt = create_device_tree(&s->fdt_size);
if (!fdt) {
@@ -152,7 +155,8 @@ static void create_fdt(SpikeState *s, const MemMapEntry *memmap,
(memmap[SPIKE_CLINT].size * socket);
clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr);
qemu_fdt_add_subnode(fdt, clint_name);
- qemu_fdt_setprop_string(fdt, clint_name, "compatible", "riscv,clint0");
+ qemu_fdt_setprop_string_array(fdt, clint_name, "compatible",
+ (char **)&clint_compat, ARRAY_SIZE(clint_compat));
qemu_fdt_setprop_cells(fdt, clint_name, "reg",
0x0, clint_addr, 0x0, memmap[SPIKE_CLINT].size);
qemu_fdt_setprop(fdt, clint_name, "interrupts-extended",
@@ -254,13 +258,11 @@ static void spike_board_init(MachineState *machine)
*/
if (riscv_is_32bit(&s->soc[0])) {
firmware_end_addr = riscv_find_and_load_firmware(machine,
- "opensbi-riscv32-generic-fw_dynamic.elf",
- memmap[SPIKE_DRAM].base,
+ RISCV32_BIOS_ELF, memmap[SPIKE_DRAM].base,
htif_symbol_callback);
} else {
firmware_end_addr = riscv_find_and_load_firmware(machine,
- "opensbi-riscv64-generic-fw_dynamic.elf",
- memmap[SPIKE_DRAM].base,
+ RISCV64_BIOS_ELF, memmap[SPIKE_DRAM].base,
htif_symbol_callback);
}
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 95a11adaa2..4a3cd2599a 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -194,6 +194,12 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
char *name, *clint_name, *plic_name, *clust_name;
hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
+ static const char * const clint_compat[2] = {
+ "sifive,clint0", "riscv,clint0"
+ };
+ static const char * const plic_compat[2] = {
+ "sifive,plic-1.0.0", "riscv,plic0"
+ };
if (mc->dtb) {
fdt = mc->fdt = load_device_tree(mc->dtb, &s->fdt_size);
@@ -299,7 +305,8 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
(memmap[VIRT_CLINT].size * socket);
clint_name = g_strdup_printf("/soc/clint@%lx", clint_addr);
qemu_fdt_add_subnode(fdt, clint_name);
- qemu_fdt_setprop_string(fdt, clint_name, "compatible", "riscv,clint0");
+ qemu_fdt_setprop_string_array(fdt, clint_name, "compatible",
+ (char **)&clint_compat, ARRAY_SIZE(clint_compat));
qemu_fdt_setprop_cells(fdt, clint_name, "reg",
0x0, clint_addr, 0x0, memmap[VIRT_CLINT].size);
qemu_fdt_setprop(fdt, clint_name, "interrupts-extended",
@@ -315,7 +322,8 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
"#address-cells", FDT_PLIC_ADDR_CELLS);
qemu_fdt_setprop_cell(fdt, plic_name,
"#interrupt-cells", FDT_PLIC_INT_CELLS);
- qemu_fdt_setprop_string(fdt, plic_name, "compatible", "riscv,plic0");
+ qemu_fdt_setprop_string_array(fdt, plic_name, "compatible",
+ (char **)&plic_compat, ARRAY_SIZE(plic_compat));
qemu_fdt_setprop(fdt, plic_name, "interrupt-controller", NULL, 0);
qemu_fdt_setprop(fdt, plic_name, "interrupts-extended",
plic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4);
@@ -394,8 +402,11 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
(long)memmap[VIRT_TEST].base);
qemu_fdt_add_subnode(fdt, name);
{
- const char compat[] = "sifive,test1\0sifive,test0\0syscon";
- qemu_fdt_setprop(fdt, name, "compatible", compat, sizeof(compat));
+ static const char * const compat[3] = {
+ "sifive,test1", "sifive,test0", "syscon"
+ };
+ qemu_fdt_setprop_string_array(fdt, name, "compatible", (char **)&compat,
+ ARRAY_SIZE(compat));
}
qemu_fdt_setprop_cells(fdt, name, "reg",
0x0, memmap[VIRT_TEST].base,
@@ -670,12 +681,10 @@ static void virt_machine_init(MachineState *machine)
if (riscv_is_32bit(&s->soc[0])) {
firmware_end_addr = riscv_find_and_load_firmware(machine,
- "opensbi-riscv32-generic-fw_dynamic.bin",
- start_addr, NULL);
+ RISCV32_BIOS_BIN, start_addr, NULL);
} else {
firmware_end_addr = riscv_find_and_load_firmware(machine,
- "opensbi-riscv64-generic-fw_dynamic.bin",
- start_addr, NULL);
+ RISCV64_BIOS_BIN, start_addr, NULL);
}
if (machine->kernel_filename) {