aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/riscv/sifive_e.c2
-rw-r--r--hw/riscv/virt.c71
-rw-r--r--linux-user/syscall.c6
-rw-r--r--target/riscv/cpu_helper.c54
-rw-r--r--target/riscv/tcg/tcg-cpu.c9
5 files changed, 85 insertions, 57 deletions
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 0d37adc542..87d9602383 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -225,7 +225,7 @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
RISCV_ACLINT_SWI_SIZE,
RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
- RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, false);
+ SIFIVE_E_LFCLK_DEFAULT_FREQ, false);
sifive_e_prci_create(memmap[SIFIVE_E_DEV_PRCI].base);
/* AON */
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index c7fc97e273..d2eac24156 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -962,7 +962,6 @@ static void create_fdt_uart(RISCVVirtState *s, const MemMapEntry *memmap,
qemu_fdt_setprop_cells(ms->fdt, name, "interrupts", UART0_IRQ, 0x4);
}
- qemu_fdt_add_subnode(ms->fdt, "/chosen");
qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", name);
g_free(name);
}
@@ -1023,11 +1022,29 @@ static void create_fdt_fw_cfg(RISCVVirtState *s, const MemMapEntry *memmap)
g_free(nodename);
}
-static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap)
+static void finalize_fdt(RISCVVirtState *s)
{
- MachineState *ms = MACHINE(s);
uint32_t phandle = 1, irq_mmio_phandle = 1, msi_pcie_phandle = 1;
uint32_t irq_pcie_phandle = 1, irq_virtio_phandle = 1;
+
+ create_fdt_sockets(s, virt_memmap, &phandle, &irq_mmio_phandle,
+ &irq_pcie_phandle, &irq_virtio_phandle,
+ &msi_pcie_phandle);
+
+ create_fdt_virtio(s, virt_memmap, irq_virtio_phandle);
+
+ create_fdt_pcie(s, virt_memmap, irq_pcie_phandle, msi_pcie_phandle);
+
+ create_fdt_reset(s, virt_memmap, &phandle);
+
+ create_fdt_uart(s, virt_memmap, irq_mmio_phandle);
+
+ create_fdt_rtc(s, virt_memmap, irq_mmio_phandle);
+}
+
+static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap)
+{
+ MachineState *ms = MACHINE(s);
uint8_t rng_seed[32];
ms->fdt = create_device_tree(&s->fdt_size);
@@ -1047,28 +1064,16 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap)
qemu_fdt_setprop_cell(ms->fdt, "/soc", "#size-cells", 0x2);
qemu_fdt_setprop_cell(ms->fdt, "/soc", "#address-cells", 0x2);
- create_fdt_sockets(s, memmap, &phandle, &irq_mmio_phandle,
- &irq_pcie_phandle, &irq_virtio_phandle,
- &msi_pcie_phandle);
-
- create_fdt_virtio(s, memmap, irq_virtio_phandle);
-
- create_fdt_pcie(s, memmap, irq_pcie_phandle, msi_pcie_phandle);
-
- create_fdt_reset(s, memmap, &phandle);
-
- create_fdt_uart(s, memmap, irq_mmio_phandle);
-
- create_fdt_rtc(s, memmap, irq_mmio_phandle);
-
- create_fdt_flash(s, memmap);
- create_fdt_fw_cfg(s, memmap);
- create_fdt_pmu(s);
+ qemu_fdt_add_subnode(ms->fdt, "/chosen");
/* Pass seed to RNG */
qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
qemu_fdt_setprop(ms->fdt, "/chosen", "rng-seed",
rng_seed, sizeof(rng_seed));
+
+ create_fdt_flash(s, memmap);
+ create_fdt_fw_cfg(s, memmap);
+ create_fdt_pmu(s);
}
static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem,
@@ -1257,15 +1262,12 @@ static void virt_machine_done(Notifier *notifier, void *data)
uint64_t kernel_entry = 0;
BlockBackend *pflash_blk0;
- /* load/create device tree */
- if (machine->dtb) {
- machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
- if (!machine->fdt) {
- error_report("load_device_tree() failed");
- exit(1);
- }
- } else {
- create_fdt(s, memmap);
+ /*
+ * An user provided dtb must include everything, including
+ * dynamic sysbus devices. Our FDT needs to be finalized.
+ */
+ if (machine->dtb == NULL) {
+ finalize_fdt(s);
}
/*
@@ -1541,6 +1543,17 @@ static void virt_machine_init(MachineState *machine)
}
virt_flash_map(s, system_memory);
+ /* load/create device tree */
+ if (machine->dtb) {
+ machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
+ if (!machine->fdt) {
+ error_report("load_device_tree() failed");
+ exit(1);
+ }
+ } else {
+ create_fdt(s, memmap);
+ }
+
s->machine_done.notify = virt_machine_done;
qemu_add_machine_init_done_notifier(&s->machine_done);
}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 16ca5ea7b6..e384e14248 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8808,6 +8808,8 @@ static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count)
#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)
#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)
+#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6
+
struct riscv_hwprobe {
abi_llong key;
abi_ullong value;
@@ -8860,6 +8862,10 @@ static void risc_hwprobe_fill_pairs(CPURISCVState *env,
case RISCV_HWPROBE_KEY_CPUPERF_0:
__put_user(RISCV_HWPROBE_MISALIGNED_FAST, &pair->value);
break;
+ case RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE:
+ value = cfg->ext_zicboz ? cfg->cboz_blocksize : 0;
+ __put_user(value, &pair->value);
+ break;
default:
__put_user(-1, &pair->key);
break;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index b7af69de53..e7e23b34f4 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1032,13 +1032,29 @@ restart:
prot |= PAGE_WRITE;
}
if (pte & PTE_X) {
- bool mxr;
+ bool mxr = false;
- if (first_stage == true) {
+ /*
+ * Use mstatus for first stage or for the second stage without
+ * virt_enabled (MPRV+MPV)
+ */
+ if (first_stage || !env->virt_enabled) {
mxr = get_field(env->mstatus, MSTATUS_MXR);
- } else {
- mxr = get_field(env->vsstatus, MSTATUS_MXR);
}
+
+ /* MPRV+MPV case, check VSSTATUS */
+ if (first_stage && two_stage && !env->virt_enabled) {
+ mxr |= get_field(env->vsstatus, MSTATUS_MXR);
+ }
+
+ /*
+ * Setting MXR at HS-level overrides both VS-stage and G-stage
+ * execute-only permissions
+ */
+ if (env->virt_enabled) {
+ mxr |= get_field(env->mstatus_hs, MSTATUS_MXR);
+ }
+
if (mxr) {
prot |= PAGE_READ;
}
@@ -1143,47 +1159,31 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
bool two_stage_indirect)
{
CPUState *cs = env_cpu(env);
- int page_fault_exceptions, vm;
- uint64_t stap_mode;
-
- if (riscv_cpu_mxl(env) == MXL_RV32) {
- stap_mode = SATP32_MODE;
- } else {
- stap_mode = SATP64_MODE;
- }
-
- if (first_stage) {
- vm = get_field(env->satp, stap_mode);
- } else {
- vm = get_field(env->hgatp, stap_mode);
- }
-
- page_fault_exceptions = vm != VM_1_10_MBARE && !pmp_violation;
switch (access_type) {
case MMU_INST_FETCH:
if (env->virt_enabled && !first_stage) {
cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
} else {
- cs->exception_index = page_fault_exceptions ?
- RISCV_EXCP_INST_PAGE_FAULT : RISCV_EXCP_INST_ACCESS_FAULT;
+ cs->exception_index = pmp_violation ?
+ RISCV_EXCP_INST_ACCESS_FAULT : RISCV_EXCP_INST_PAGE_FAULT;
}
break;
case MMU_DATA_LOAD:
if (two_stage && !first_stage) {
cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
} else {
- cs->exception_index = page_fault_exceptions ?
- RISCV_EXCP_LOAD_PAGE_FAULT : RISCV_EXCP_LOAD_ACCESS_FAULT;
+ cs->exception_index = pmp_violation ?
+ RISCV_EXCP_LOAD_ACCESS_FAULT : RISCV_EXCP_LOAD_PAGE_FAULT;
}
break;
case MMU_DATA_STORE:
if (two_stage && !first_stage) {
cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
} else {
- cs->exception_index = page_fault_exceptions ?
- RISCV_EXCP_STORE_PAGE_FAULT :
- RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
+ cs->exception_index = pmp_violation ?
+ RISCV_EXCP_STORE_AMO_ACCESS_FAULT :
+ RISCV_EXCP_STORE_PAGE_FAULT;
}
break;
default:
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 08adad304d..8a35683a34 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -250,6 +250,15 @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
for (edata = isa_edata_arr; edata && edata->name; edata++) {
if (isa_ext_is_enabled(cpu, edata->ext_enable_offset) &&
(env->priv_ver < edata->min_version)) {
+ /*
+ * These two extensions are always enabled as they were supported
+ * by QEMU before they were added as extensions in the ISA.
+ */
+ if (!strcmp(edata->name, "zicntr") ||
+ !strcmp(edata->name, "zihpm")) {
+ continue;
+ }
+
isa_ext_update_enabled(cpu, edata->ext_enable_offset, false);
#ifndef CONFIG_USER_ONLY
warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx