aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2023-01-20 16:17:56 +0000
committerPeter Maydell <peter.maydell@linaro.org>2023-01-20 16:17:56 +0000
commit65cc5ccf06a74c98de73ec683d9a543baa302a12 (patch)
tree77ffd0b33a251ce4fb2772cc27cd269695f3107e /target
parentfcb7e040f5c69ca1f0678f991ab5354488a9e192 (diff)
parentb748352c555b42d497fe8ee00ee2e44eb8627660 (diff)
downloadqemu-65cc5ccf06a74c98de73ec683d9a543baa302a12.zip
qemu-65cc5ccf06a74c98de73ec683d9a543baa302a12.tar.gz
qemu-65cc5ccf06a74c98de73ec683d9a543baa302a12.tar.bz2
Merge tag 'pull-riscv-to-apply-20230120' of https://github.com/alistair23/qemu into staging
Second RISC-V PR for QEMU 8.0 * riscv_htif: Support console output via proxy syscall * Cleanup firmware and device tree loading * Fix elen check when using vector extensions * add RISC-V OpenSBI boot test * Ensure we always follow MISA parsing * Fix up masking of vsip/vsie accesses * Trap on writes to stimecmp from VS when hvictl.VTI=1 * Introduce helper_set_rounding_mode_chkfrm # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCAAdFiEE9sSsRtSTSGjTuM6PIeENKd+XcFQFAmPKRP0ACgkQIeENKd+X # cFTHTwgAkyRDxrLepvI0KNaT0+cUBh+3QFlJ5JRtVnDW+5R+3aGT72PTS7Migqoh # H3IFCB2mcSdQvyjj2jDFlrFd0oVIaqE0+bnhouS/4nHB5S/vmapHi4Mc74Vv1CMB # rgXScL+C5gDOH1I7XjqOb1FY5Vxqyhi3IzdIoj+0ysUrGmUkqx+ij/cfQL7jkH9Q # slNAkorgwgrTgMgkJ5RKd4cjyv35O4XKLAsgixVTfJ+WcxKmc/zaJOkNM/UDnmxK # k2+2P8bshZWtWscXbm3oMC5+2ow1QtFedEkhHqb4adkQIyolKL7P1TfMlCgMSvES # BKl0DUhqQ+7F77tik3GPy9spQ6LpTQ== # =ifFF # -----END PGP SIGNATURE----- # gpg: Signature made Fri 20 Jan 2023 07:38:37 GMT # 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 * tag 'pull-riscv-to-apply-20230120' of https://github.com/alistair23/qemu: (37 commits) hw/riscv/virt.c: move create_fw_cfg() back to virt_machine_init() target/riscv: Remove helper_set_rod_rounding_mode target/riscv: Introduce helper_set_rounding_mode_chkfrm tcg/riscv: Use tcg_pcrel_diff in tcg_out_ldst target/riscv: Trap on writes to stimecmp from VS when hvictl.VTI=1 target/riscv: Fix up masking of vsip/vsie accesses hw/riscv: use ms->fdt in riscv_socket_fdt_write_distance_matrix() hw/riscv: use MachineState::fdt in riscv_socket_fdt_write_id() hw/riscv/virt.c: remove 'is_32_bit' param from create_fdt_socket_cpus() hw/riscv/sifive_u.c: simplify create_fdt() hw/riscv/virt.c: simplify create_fdt() hw/riscv/spike.c: simplify create_fdt() target/riscv: Use TARGET_FMT_lx for env->mhartid target/riscv/cpu.c: do not skip misa logic in riscv_cpu_realize() target/riscv/cpu: set cpu->cfg in register_cpu_props() hw/riscv/boot.c: use MachineState in riscv_load_kernel() hw/riscv/boot.c: use MachineState in riscv_load_initrd() hw/riscv: write bootargs 'chosen' FDT after riscv_load_kernel() hw/riscv: write initrd 'chosen' FDT inside riscv_load_initrd() hw/riscv/spike.c: load initrd right after riscv_load_kernel() ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/riscv/cpu.c445
-rw-r--r--target/riscv/cpu.h8
-rw-r--r--target/riscv/csr.c41
-rw-r--r--target/riscv/fpu_helper.c36
-rw-r--r--target/riscv/helper.h2
-rw-r--r--target/riscv/insn_trans/trans_rvv.c.inc24
-rw-r--r--target/riscv/machine.c6
-rw-r--r--target/riscv/translate.c21
8 files changed, 328 insertions, 255 deletions
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index cc75ca7..14a7027 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -256,6 +256,7 @@ static void rv64_sifive_u_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+ register_cpu_props(DEVICE(obj));
set_priv_version(env, PRIV_VERSION_1_10_0);
}
@@ -265,6 +266,7 @@ static void rv64_sifive_e_cpu_init(Object *obj)
RISCVCPU *cpu = RISCV_CPU(obj);
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
+ register_cpu_props(DEVICE(obj));
set_priv_version(env, PRIV_VERSION_1_10_0);
cpu->cfg.mmu = false;
}
@@ -299,6 +301,7 @@ static void rv32_sifive_u_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+ register_cpu_props(DEVICE(obj));
set_priv_version(env, PRIV_VERSION_1_10_0);
}
@@ -308,6 +311,7 @@ static void rv32_sifive_e_cpu_init(Object *obj)
RISCVCPU *cpu = RISCV_CPU(obj);
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU);
+ register_cpu_props(DEVICE(obj));
set_priv_version(env, PRIV_VERSION_1_10_0);
cpu->cfg.mmu = false;
}
@@ -318,6 +322,7 @@ static void rv32_ibex_cpu_init(Object *obj)
RISCVCPU *cpu = RISCV_CPU(obj);
set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
+ register_cpu_props(DEVICE(obj));
set_priv_version(env, PRIV_VERSION_1_11_0);
cpu->cfg.mmu = false;
cpu->cfg.epmp = true;
@@ -329,6 +334,7 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj)
RISCVCPU *cpu = RISCV_CPU(obj);
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU);
+ register_cpu_props(DEVICE(obj));
set_priv_version(env, PRIV_VERSION_1_10_0);
cpu->cfg.mmu = false;
}
@@ -619,6 +625,207 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
}
}
+/*
+ * Check consistency between chosen extensions while setting
+ * cpu->cfg accordingly, doing a set_misa() in the end.
+ */
+static void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
+{
+ CPURISCVState *env = &cpu->env;
+ uint32_t ext = 0;
+
+ /* Do some ISA extension error checking */
+ if (cpu->cfg.ext_g && !(cpu->cfg.ext_i && cpu->cfg.ext_m &&
+ cpu->cfg.ext_a && cpu->cfg.ext_f &&
+ cpu->cfg.ext_d &&
+ cpu->cfg.ext_icsr && cpu->cfg.ext_ifencei)) {
+ warn_report("Setting G will also set IMAFD_Zicsr_Zifencei");
+ cpu->cfg.ext_i = true;
+ cpu->cfg.ext_m = true;
+ cpu->cfg.ext_a = true;
+ cpu->cfg.ext_f = true;
+ cpu->cfg.ext_d = true;
+ cpu->cfg.ext_icsr = true;
+ cpu->cfg.ext_ifencei = true;
+ }
+
+ if (cpu->cfg.ext_i && cpu->cfg.ext_e) {
+ error_setg(errp,
+ "I and E extensions are incompatible");
+ return;
+ }
+
+ if (!cpu->cfg.ext_i && !cpu->cfg.ext_e) {
+ error_setg(errp,
+ "Either I or E extension must be set");
+ return;
+ }
+
+ if (cpu->cfg.ext_s && !cpu->cfg.ext_u) {
+ error_setg(errp,
+ "Setting S extension without U extension is illegal");
+ return;
+ }
+
+ if (cpu->cfg.ext_h && !cpu->cfg.ext_i) {
+ error_setg(errp,
+ "H depends on an I base integer ISA with 32 x registers");
+ return;
+ }
+
+ if (cpu->cfg.ext_h && !cpu->cfg.ext_s) {
+ error_setg(errp, "H extension implicitly requires S-mode");
+ return;
+ }
+
+ if (cpu->cfg.ext_f && !cpu->cfg.ext_icsr) {
+ error_setg(errp, "F extension requires Zicsr");
+ return;
+ }
+
+ if ((cpu->cfg.ext_zawrs) && !cpu->cfg.ext_a) {
+ error_setg(errp, "Zawrs extension requires A extension");
+ return;
+ }
+
+ if ((cpu->cfg.ext_zfh || cpu->cfg.ext_zfhmin) && !cpu->cfg.ext_f) {
+ error_setg(errp, "Zfh/Zfhmin extensions require F extension");
+ return;
+ }
+
+ if (cpu->cfg.ext_d && !cpu->cfg.ext_f) {
+ error_setg(errp, "D extension requires F extension");
+ return;
+ }
+
+ if (cpu->cfg.ext_v && !cpu->cfg.ext_d) {
+ error_setg(errp, "V extension requires D extension");
+ return;
+ }
+
+ if ((cpu->cfg.ext_zve32f || cpu->cfg.ext_zve64f) && !cpu->cfg.ext_f) {
+ error_setg(errp, "Zve32f/Zve64f extensions require F extension");
+ return;
+ }
+
+ /* Set the ISA extensions, checks should have happened above */
+ if (cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinx ||
+ cpu->cfg.ext_zhinxmin) {
+ cpu->cfg.ext_zfinx = true;
+ }
+
+ if (cpu->cfg.ext_zfinx) {
+ if (!cpu->cfg.ext_icsr) {
+ error_setg(errp, "Zfinx extension requires Zicsr");
+ return;
+ }
+ if (cpu->cfg.ext_f) {
+ error_setg(errp,
+ "Zfinx cannot be supported together with F extension");
+ return;
+ }
+ }
+
+ if (cpu->cfg.ext_zk) {
+ cpu->cfg.ext_zkn = true;
+ cpu->cfg.ext_zkr = true;
+ cpu->cfg.ext_zkt = true;
+ }
+
+ if (cpu->cfg.ext_zkn) {
+ cpu->cfg.ext_zbkb = true;
+ cpu->cfg.ext_zbkc = true;
+ cpu->cfg.ext_zbkx = true;
+ cpu->cfg.ext_zkne = true;
+ cpu->cfg.ext_zknd = true;
+ cpu->cfg.ext_zknh = true;
+ }
+
+ if (cpu->cfg.ext_zks) {
+ cpu->cfg.ext_zbkb = true;
+ cpu->cfg.ext_zbkc = true;
+ cpu->cfg.ext_zbkx = true;
+ cpu->cfg.ext_zksed = true;
+ cpu->cfg.ext_zksh = true;
+ }
+
+ if (cpu->cfg.ext_i) {
+ ext |= RVI;
+ }
+ if (cpu->cfg.ext_e) {
+ ext |= RVE;
+ }
+ if (cpu->cfg.ext_m) {
+ ext |= RVM;
+ }
+ if (cpu->cfg.ext_a) {
+ ext |= RVA;
+ }
+ if (cpu->cfg.ext_f) {
+ ext |= RVF;
+ }
+ if (cpu->cfg.ext_d) {
+ ext |= RVD;
+ }
+ if (cpu->cfg.ext_c) {
+ ext |= RVC;
+ }
+ if (cpu->cfg.ext_s) {
+ ext |= RVS;
+ }
+ if (cpu->cfg.ext_u) {
+ ext |= RVU;
+ }
+ if (cpu->cfg.ext_h) {
+ ext |= RVH;
+ }
+ if (cpu->cfg.ext_v) {
+ int vext_version = VEXT_VERSION_1_00_0;
+ ext |= RVV;
+ if (!is_power_of_2(cpu->cfg.vlen)) {
+ error_setg(errp,
+ "Vector extension VLEN must be power of 2");
+ return;
+ }
+ if (cpu->cfg.vlen > RV_VLEN_MAX || cpu->cfg.vlen < 128) {
+ error_setg(errp,
+ "Vector extension implementation only supports VLEN "
+ "in the range [128, %d]", RV_VLEN_MAX);
+ return;
+ }
+ if (!is_power_of_2(cpu->cfg.elen)) {
+ error_setg(errp,
+ "Vector extension ELEN must be power of 2");
+ return;
+ }
+ if (cpu->cfg.elen > 64 || cpu->cfg.elen < 8) {
+ error_setg(errp,
+ "Vector extension implementation only supports ELEN "
+ "in the range [8, 64]");
+ return;
+ }
+ if (cpu->cfg.vext_spec) {
+ if (!g_strcmp0(cpu->cfg.vext_spec, "v1.0")) {
+ vext_version = VEXT_VERSION_1_00_0;
+ } else {
+ error_setg(errp,
+ "Unsupported vector spec version '%s'",
+ cpu->cfg.vext_spec);
+ return;
+ }
+ } else {
+ qemu_log("vector version is not specified, "
+ "use the default value v1.0\n");
+ }
+ set_vext_version(env, vext_version);
+ }
+ if (cpu->cfg.ext_j) {
+ ext |= RVJ;
+ }
+
+ set_misa(env, env->misa_mxl, ext);
+}
+
static void riscv_cpu_realize(DeviceState *dev, Error **errp)
{
CPUState *cs = CPU(dev);
@@ -660,9 +867,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
(env->priv_ver < isa_edata_arr[i].min_version)) {
isa_ext_update_enabled(cpu, &isa_edata_arr[i], false);
#ifndef CONFIG_USER_ONLY
- warn_report("disabling %s extension for hart 0x%lx because "
- "privilege spec version does not match",
- isa_edata_arr[i].name, (unsigned long)env->mhartid);
+ warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx
+ " because privilege spec version does not match",
+ isa_edata_arr[i].name, env->mhartid);
#else
warn_report("disabling %s extension because "
"privilege spec version does not match",
@@ -714,200 +921,10 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
}
assert(env->misa_mxl_max == env->misa_mxl);
- /* If only MISA_EXT is unset for misa, then set it from properties */
- if (env->misa_ext == 0) {
- uint32_t ext = 0;
-
- /* Do some ISA extension error checking */
- if (cpu->cfg.ext_g && !(cpu->cfg.ext_i && cpu->cfg.ext_m &&
- cpu->cfg.ext_a && cpu->cfg.ext_f &&
- cpu->cfg.ext_d &&
- cpu->cfg.ext_icsr && cpu->cfg.ext_ifencei)) {
- warn_report("Setting G will also set IMAFD_Zicsr_Zifencei");
- cpu->cfg.ext_i = true;
- cpu->cfg.ext_m = true;
- cpu->cfg.ext_a = true;
- cpu->cfg.ext_f = true;
- cpu->cfg.ext_d = true;
- cpu->cfg.ext_icsr = true;
- cpu->cfg.ext_ifencei = true;
- }
-
- if (cpu->cfg.ext_i && cpu->cfg.ext_e) {
- error_setg(errp,
- "I and E extensions are incompatible");
- return;
- }
-
- if (!cpu->cfg.ext_i && !cpu->cfg.ext_e) {
- error_setg(errp,
- "Either I or E extension must be set");
- return;
- }
-
- if (cpu->cfg.ext_s && !cpu->cfg.ext_u) {
- error_setg(errp,
- "Setting S extension without U extension is illegal");
- return;
- }
-
- if (cpu->cfg.ext_h && !cpu->cfg.ext_i) {
- error_setg(errp,
- "H depends on an I base integer ISA with 32 x registers");
- return;
- }
-
- if (cpu->cfg.ext_h && !cpu->cfg.ext_s) {
- error_setg(errp, "H extension implicitly requires S-mode");
- return;
- }
-
- if (cpu->cfg.ext_f && !cpu->cfg.ext_icsr) {
- error_setg(errp, "F extension requires Zicsr");
- return;
- }
-
- if ((cpu->cfg.ext_zawrs) && !cpu->cfg.ext_a) {
- error_setg(errp, "Zawrs extension requires A extension");
- return;
- }
-
- if ((cpu->cfg.ext_zfh || cpu->cfg.ext_zfhmin) && !cpu->cfg.ext_f) {
- error_setg(errp, "Zfh/Zfhmin extensions require F extension");
- return;
- }
-
- if (cpu->cfg.ext_d && !cpu->cfg.ext_f) {
- error_setg(errp, "D extension requires F extension");
- return;
- }
-
- if (cpu->cfg.ext_v && !cpu->cfg.ext_d) {
- error_setg(errp, "V extension requires D extension");
- return;
- }
-
- if ((cpu->cfg.ext_zve32f || cpu->cfg.ext_zve64f) && !cpu->cfg.ext_f) {
- error_setg(errp, "Zve32f/Zve64f extensions require F extension");
- return;
- }
-
- /* Set the ISA extensions, checks should have happened above */
- if (cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinx ||
- cpu->cfg.ext_zhinxmin) {
- cpu->cfg.ext_zfinx = true;
- }
-
- if (cpu->cfg.ext_zfinx) {
- if (!cpu->cfg.ext_icsr) {
- error_setg(errp, "Zfinx extension requires Zicsr");
- return;
- }
- if (cpu->cfg.ext_f) {
- error_setg(errp,
- "Zfinx cannot be supported together with F extension");
- return;
- }
- }
-
- if (cpu->cfg.ext_zk) {
- cpu->cfg.ext_zkn = true;
- cpu->cfg.ext_zkr = true;
- cpu->cfg.ext_zkt = true;
- }
-
- if (cpu->cfg.ext_zkn) {
- cpu->cfg.ext_zbkb = true;
- cpu->cfg.ext_zbkc = true;
- cpu->cfg.ext_zbkx = true;
- cpu->cfg.ext_zkne = true;
- cpu->cfg.ext_zknd = true;
- cpu->cfg.ext_zknh = true;
- }
-
- if (cpu->cfg.ext_zks) {
- cpu->cfg.ext_zbkb = true;
- cpu->cfg.ext_zbkc = true;
- cpu->cfg.ext_zbkx = true;
- cpu->cfg.ext_zksed = true;
- cpu->cfg.ext_zksh = true;
- }
-
- if (cpu->cfg.ext_i) {
- ext |= RVI;
- }
- if (cpu->cfg.ext_e) {
- ext |= RVE;
- }
- if (cpu->cfg.ext_m) {
- ext |= RVM;
- }
- if (cpu->cfg.ext_a) {
- ext |= RVA;
- }
- if (cpu->cfg.ext_f) {
- ext |= RVF;
- }
- if (cpu->cfg.ext_d) {
- ext |= RVD;
- }
- if (cpu->cfg.ext_c) {
- ext |= RVC;
- }
- if (cpu->cfg.ext_s) {
- ext |= RVS;
- }
- if (cpu->cfg.ext_u) {
- ext |= RVU;
- }
- if (cpu->cfg.ext_h) {
- ext |= RVH;
- }
- if (cpu->cfg.ext_v) {
- int vext_version = VEXT_VERSION_1_00_0;
- ext |= RVV;
- if (!is_power_of_2(cpu->cfg.vlen)) {
- error_setg(errp,
- "Vector extension VLEN must be power of 2");
- return;
- }
- if (cpu->cfg.vlen > RV_VLEN_MAX || cpu->cfg.vlen < 128) {
- error_setg(errp,
- "Vector extension implementation only supports VLEN "
- "in the range [128, %d]", RV_VLEN_MAX);
- return;
- }
- if (!is_power_of_2(cpu->cfg.elen)) {
- error_setg(errp,
- "Vector extension ELEN must be power of 2");
- return;
- }
- if (cpu->cfg.elen > 64 || cpu->cfg.vlen < 8) {
- error_setg(errp,
- "Vector extension implementation only supports ELEN "
- "in the range [8, 64]");
- return;
- }
- if (cpu->cfg.vext_spec) {
- if (!g_strcmp0(cpu->cfg.vext_spec, "v1.0")) {
- vext_version = VEXT_VERSION_1_00_0;
- } else {
- error_setg(errp,
- "Unsupported vector spec version '%s'",
- cpu->cfg.vext_spec);
- return;
- }
- } else {
- qemu_log("vector version is not specified, "
- "use the default value v1.0\n");
- }
- set_vext_version(env, vext_version);
- }
- if (cpu->cfg.ext_j) {
- ext |= RVJ;
- }
-
- set_misa(env, env->misa_mxl, ext);
+ riscv_cpu_validate_set_extensions(cpu, &local_err);
+ if (local_err != NULL) {
+ error_propagate(errp, local_err);
+ return;
}
#ifndef CONFIG_USER_ONLY
@@ -1083,10 +1100,44 @@ static Property riscv_cpu_extensions[] = {
DEFINE_PROP_END_OF_LIST(),
};
+/*
+ * Register CPU props based on env.misa_ext. If a non-zero
+ * value was set, register only the required cpu->cfg.ext_*
+ * properties and leave. env.misa_ext = 0 means that we want
+ * all the default properties to be registered.
+ */
static void register_cpu_props(DeviceState *dev)
{
+ RISCVCPU *cpu = RISCV_CPU(OBJECT(dev));
+ uint32_t misa_ext = cpu->env.misa_ext;
Property *prop;
+ /*
+ * If misa_ext is not zero, set cfg properties now to
+ * allow them to be read during riscv_cpu_realize()
+ * later on.
+ */
+ if (cpu->env.misa_ext != 0) {
+ cpu->cfg.ext_i = misa_ext & RVI;
+ cpu->cfg.ext_e = misa_ext & RVE;
+ cpu->cfg.ext_m = misa_ext & RVM;
+ cpu->cfg.ext_a = misa_ext & RVA;
+ cpu->cfg.ext_f = misa_ext & RVF;
+ cpu->cfg.ext_d = misa_ext & RVD;
+ cpu->cfg.ext_v = misa_ext & RVV;
+ cpu->cfg.ext_c = misa_ext & RVC;
+ cpu->cfg.ext_s = misa_ext & RVS;
+ cpu->cfg.ext_u = misa_ext & RVU;
+ cpu->cfg.ext_h = misa_ext & RVH;
+ cpu->cfg.ext_j = misa_ext & RVJ;
+
+ /*
+ * We don't want to set the default riscv_cpu_extensions
+ * in this case.
+ */
+ return;
+ }
+
for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
qdev_property_add_static(dev, prop);
}
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f5609b6..bcf0826 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -63,6 +63,10 @@
#define RV(x) ((target_ulong)1 << (x - 'A'))
+/*
+ * Consider updating register_cpu_props() when adding
+ * new MISA bits here.
+ */
#define RVI RV('I')
#define RVE RV('E') /* E and I are mutually exclusive */
#define RVM RV('M')
@@ -309,10 +313,6 @@ struct CPUArchState {
target_ulong sscratch;
target_ulong mscratch;
- /* temporary htif regs */
- uint64_t mfromhost;
- uint64_t mtohost;
-
/* Sstc CSRs */
uint64_t stimecmp;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 0db2c23..62e6c4a 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1037,6 +1037,9 @@ static RISCVException write_stimecmp(CPURISCVState *env, int csrno,
RISCVCPU *cpu = env_archcpu(env);
if (riscv_cpu_virt_enabled(env)) {
+ if (env->hvictl & HVICTL_VTI) {
+ return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
return write_vstimecmp(env, csrno, val);
}
@@ -1057,6 +1060,9 @@ static RISCVException write_stimecmph(CPURISCVState *env, int csrno,
RISCVCPU *cpu = env_archcpu(env);
if (riscv_cpu_virt_enabled(env)) {
+ if (env->hvictl & HVICTL_VTI) {
+ return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
return write_vstimecmph(env, csrno, val);
}
@@ -2305,22 +2311,15 @@ static RISCVException rmw_vsie64(CPURISCVState *env, int csrno,
uint64_t new_val, uint64_t wr_mask)
{
RISCVException ret;
- uint64_t rval, vsbits, mask = env->hideleg & VS_MODE_INTERRUPTS;
+ uint64_t rval, mask = env->hideleg & VS_MODE_INTERRUPTS;
/* Bring VS-level bits to correct position */
- vsbits = new_val & (VS_MODE_INTERRUPTS >> 1);
- new_val &= ~(VS_MODE_INTERRUPTS >> 1);
- new_val |= vsbits << 1;
- vsbits = wr_mask & (VS_MODE_INTERRUPTS >> 1);
- wr_mask &= ~(VS_MODE_INTERRUPTS >> 1);
- wr_mask |= vsbits << 1;
+ new_val = (new_val & (VS_MODE_INTERRUPTS >> 1)) << 1;
+ wr_mask = (wr_mask & (VS_MODE_INTERRUPTS >> 1)) << 1;
ret = rmw_mie64(env, csrno, &rval, new_val, wr_mask & mask);
if (ret_val) {
- rval &= mask;
- vsbits = rval & VS_MODE_INTERRUPTS;
- rval &= ~VS_MODE_INTERRUPTS;
- *ret_val = rval | (vsbits >> 1);
+ *ret_val = (rval & mask) >> 1;
}
return ret;
@@ -2521,22 +2520,16 @@ static RISCVException rmw_vsip64(CPURISCVState *env, int csrno,
uint64_t new_val, uint64_t wr_mask)
{
RISCVException ret;
- uint64_t rval, vsbits, mask = env->hideleg & vsip_writable_mask;
+ uint64_t rval, mask = env->hideleg & VS_MODE_INTERRUPTS;
/* Bring VS-level bits to correct position */
- vsbits = new_val & (VS_MODE_INTERRUPTS >> 1);
- new_val &= ~(VS_MODE_INTERRUPTS >> 1);
- new_val |= vsbits << 1;
- vsbits = wr_mask & (VS_MODE_INTERRUPTS >> 1);
- wr_mask &= ~(VS_MODE_INTERRUPTS >> 1);
- wr_mask |= vsbits << 1;
-
- ret = rmw_mip64(env, csrno, &rval, new_val, wr_mask & mask);
+ new_val = (new_val & (VS_MODE_INTERRUPTS >> 1)) << 1;
+ wr_mask = (wr_mask & (VS_MODE_INTERRUPTS >> 1)) << 1;
+
+ ret = rmw_mip64(env, csrno, &rval, new_val,
+ wr_mask & mask & vsip_writable_mask);
if (ret_val) {
- rval &= mask;
- vsbits = rval & VS_MODE_INTERRUPTS;
- rval &= ~VS_MODE_INTERRUPTS;
- *ret_val = rval | (vsbits >> 1);
+ *ret_val = (rval & mask) >> 1;
}
return ret;
diff --git a/target/riscv/fpu_helper.c b/target/riscv/fpu_helper.c
index 5699c95..449d236 100644
--- a/target/riscv/fpu_helper.c
+++ b/target/riscv/fpu_helper.c
@@ -81,9 +81,41 @@ void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
set_float_rounding_mode(softrm, &env->fp_status);
}
-void helper_set_rod_rounding_mode(CPURISCVState *env)
+void helper_set_rounding_mode_chkfrm(CPURISCVState *env, uint32_t rm)
{
- set_float_rounding_mode(float_round_to_odd, &env->fp_status);
+ int softrm;
+
+ /* Always validate frm, even if rm != DYN. */
+ if (unlikely(env->frm >= 5)) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ }
+ if (rm == RISCV_FRM_DYN) {
+ rm = env->frm;
+ }
+ switch (rm) {
+ case RISCV_FRM_RNE:
+ softrm = float_round_nearest_even;
+ break;
+ case RISCV_FRM_RTZ:
+ softrm = float_round_to_zero;
+ break;
+ case RISCV_FRM_RDN:
+ softrm = float_round_down;
+ break;
+ case RISCV_FRM_RUP:
+ softrm = float_round_up;
+ break;
+ case RISCV_FRM_RMM:
+ softrm = float_round_ties_away;
+ break;
+ case RISCV_FRM_ROD:
+ softrm = float_round_to_odd;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ set_float_rounding_mode(softrm, &env->fp_status);
}
static uint64_t do_fmadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 227c712..58a30f0 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -3,7 +3,7 @@ DEF_HELPER_2(raise_exception, noreturn, env, i32)
/* Floating Point - rounding mode */
DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_WG, void, env, i32)
-DEF_HELPER_FLAGS_1(set_rod_rounding_mode, TCG_CALL_NO_WG, void, env)
+DEF_HELPER_FLAGS_2(set_rounding_mode_chkfrm, TCG_CALL_NO_WG, void, env, i32)
/* Floating Point - fused */
DEF_HELPER_FLAGS_4(fmadd_s, TCG_CALL_NO_RWG, i64, env, i64, i64, i64)
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
index d455ace..bbb5c3a 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -2679,13 +2679,9 @@ static bool do_opfv(DisasContext *s, arg_rmr *a,
int rm)
{
if (checkfn(s, a)) {
- if (rm != RISCV_FRM_DYN) {
- gen_set_rm(s, RISCV_FRM_DYN);
- }
-
uint32_t data = 0;
TCGLabel *over = gen_new_label();
- gen_set_rm(s, rm);
+ gen_set_rm_chkfrm(s, rm);
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over);
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over);
@@ -2882,17 +2878,13 @@ static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
{ \
if (CHECK(s, a)) { \
- if (FRM != RISCV_FRM_DYN) { \
- gen_set_rm(s, RISCV_FRM_DYN); \
- } \
- \
uint32_t data = 0; \
static gen_helper_gvec_3_ptr * const fns[2] = { \
gen_helper_##HELPER##_h, \
gen_helper_##HELPER##_w, \
}; \
TCGLabel *over = gen_new_label(); \
- gen_set_rm(s, FRM); \
+ gen_set_rm_chkfrm(s, FRM); \
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
\
@@ -3005,17 +2997,13 @@ static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
{ \
if (CHECK(s, a)) { \
- if (FRM != RISCV_FRM_DYN) { \
- gen_set_rm(s, RISCV_FRM_DYN); \
- } \
- \
uint32_t data = 0; \
static gen_helper_gvec_3_ptr * const fns[2] = { \
gen_helper_##HELPER##_h, \
gen_helper_##HELPER##_w, \
}; \
TCGLabel *over = gen_new_label(); \
- gen_set_rm(s, FRM); \
+ gen_set_rm_chkfrm(s, FRM); \
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
\
@@ -3060,10 +3048,6 @@ static bool opxfv_narrow_check(DisasContext *s, arg_rmr *a)
static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
{ \
if (opxfv_narrow_check(s, a)) { \
- if (FRM != RISCV_FRM_DYN) { \
- gen_set_rm(s, RISCV_FRM_DYN); \
- } \
- \
uint32_t data = 0; \
static gen_helper_gvec_3_ptr * const fns[3] = { \
gen_helper_##HELPER##_b, \
@@ -3071,7 +3055,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \
gen_helper_##HELPER##_w, \
}; \
TCGLabel *over = gen_new_label(); \
- gen_set_rm(s, FRM); \
+ gen_set_rm_chkfrm(s, FRM); \
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); \
tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); \
\
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 65a8549..c6ce318 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -333,8 +333,8 @@ static const VMStateDescription vmstate_pmu_ctr_state = {
const VMStateDescription vmstate_riscv_cpu = {
.name = "cpu",
- .version_id = 5,
- .minimum_version_id = 5,
+ .version_id = 6,
+ .minimum_version_id = 6,
.post_load = riscv_cpu_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
@@ -384,8 +384,6 @@ const VMStateDescription vmstate_riscv_cpu = {
VMSTATE_UINTTL_ARRAY(env.mhpmeventh_val, RISCVCPU, RV_MAX_MHPMEVENTS),
VMSTATE_UINTTL(env.sscratch, RISCVCPU),
VMSTATE_UINTTL(env.mscratch, RISCVCPU),
- VMSTATE_UINT64(env.mfromhost, RISCVCPU),
- VMSTATE_UINT64(env.mtohost, RISCVCPU),
VMSTATE_UINT64(env.stimecmp, RISCVCPU),
VMSTATE_END_OF_LIST()
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index df38db7..01cc30a 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -114,6 +114,8 @@ typedef struct DisasContext {
bool pm_base_enabled;
/* Use icount trigger for native debug */
bool itrigger;
+ /* FRM is known to contain a valid value. */
+ bool frm_valid;
/* TCG of the current insn_start */
TCGOp *insn_start;
} DisasContext;
@@ -670,9 +672,9 @@ static void gen_set_rm(DisasContext *ctx, int rm)
}
ctx->frm = rm;
- if (rm == RISCV_FRM_ROD) {
- gen_helper_set_rod_rounding_mode(cpu_env);
- return;
+ if (rm == RISCV_FRM_DYN) {
+ /* The helper will return only if frm valid. */
+ ctx->frm_valid = true;
}
/* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
@@ -680,6 +682,19 @@ static void gen_set_rm(DisasContext *ctx, int rm)
gen_helper_set_rounding_mode(cpu_env, tcg_constant_i32(rm));
}
+static void gen_set_rm_chkfrm(DisasContext *ctx, int rm)
+{
+ if (ctx->frm == rm && ctx->frm_valid) {
+ return;
+ }
+ ctx->frm = rm;
+ ctx->frm_valid = true;
+
+ /* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
+ decode_save_opc(ctx);
+ gen_helper_set_rounding_mode_chkfrm(cpu_env, tcg_constant_i32(rm));
+}
+
static int ex_plus_1(DisasContext *ctx, int nf)
{
return nf + 1;