aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2024-06-03 20:21:51 -0500
committerRichard Henderson <richard.henderson@linaro.org>2024-06-03 20:21:51 -0500
commitd67a6e054b92e5e1cbb7b0bd5782a670cc7f0df7 (patch)
tree376c4c406e969f3405ab0583509d45ffa0d74775
parent3ab42e46acf867c45bc929fcc37693e327a35a24 (diff)
parent915758c537b5fe09575291f4acd87e2d377a93de (diff)
downloadqemu-d67a6e054b92e5e1cbb7b0bd5782a670cc7f0df7.zip
qemu-d67a6e054b92e5e1cbb7b0bd5782a670cc7f0df7.tar.gz
qemu-d67a6e054b92e5e1cbb7b0bd5782a670cc7f0df7.tar.bz2
Merge tag 'pull-riscv-to-apply-20240603' of https://github.com/alistair23/qemu into staging
RISC-V PR for 9.1 * APLICs add child earlier than realize * Fix exposure of Zkr * Raise exceptions on wrs.nto * Implement SBI debug console (DBCN) calls for KVM * Support 64-bit addresses for initrd * Change RISCV_EXCP_SEMIHOST exception number to 63 * Tolerate KVM disable ext errors * Set tval in breakpoints * Add support for Zve32x extension * Add support for Zve64x extension * Relax vector register check in RISCV gdbstub * Fix the element agnostic Vector function problem * Fix Zvkb extension config * Implement dynamic establishment of custom decoder * Add th.sxstatus CSR emulation * Fix Zvfhmin checking for vfwcvt.f.f.v and vfncvt.f.f.w instructions * Check single width operator for vector fp widen instructions * Check single width operator for vfncvt.rod.f.f.w * Remove redudant SEW checking for vector fp narrow/widen instructions * Prioritize pmp errors in raise_mmu_exception() * Do not set mtval2 for non guest-page faults * Remove experimental prefix from "B" extension * Fixup CBO extension register calculation * Fix the hart bit setting of AIA * Fix reg_width in ricsv_gen_dynamic_vector_feature() * Decode all of the pmpcfg and pmpaddr CSRs # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEaukCtqfKh31tZZKWr3yVEwxTgBMFAmZdVzcACgkQr3yVEwxT # gBPxSBAAsuzhDCbaOl9jXhIL6Q0IDHULz4U16AZypHYID7T6rDaNoRmNVdqBKZuM # IMby8qm5XFmcUGM9itcM7IKV2BNHuWSye3/Y7GOYZQyToR7U6lvLpAm4pNj4AgTC # PLV2VPt1XLZRSthkgwp6ylBXzdNSiZMWggqTb7QbyfR5hJfG+VsZjTGaIwyZbtKI # +CJG6gZSPv6JGNtwnJq+v0VBEkj1ryo/gg2EAAzA+EWU4nw5mJCLWoDLrYZalTv9 # vCTqJuMViTjeHqAm/IIMoFzYR94+ug0usqcmnx/E7ALTOsmBh5K+KWndAW4vqAlP # mZOONfr3h7zc81jThC961kjGVPiTjTGbHHlKwlB2JEggwctcVqGRyWeM9wHSUr2W # S6F56hpForzVW9IkCt/fDUxamr23303s5miIsronrwiihqkNpxKYAuqPTXFGkFKg # ilBLGcbHcWxNmjpfIEXnTjDB6qFEceWqbjJejrsKusoSPkKQm0ktIZZUwCbTsu45 # 0ScYrBieUPjDWDFYlmWrr5byekyCXCzfpBgq8qo60FA+aP29Nx+GlFR0eWTXXY4V # O5/WTKjQM4+/uNYIuFDCFPV1Ja5GERDhXoNkjkY5ErsSZL2c2UEp3UTxzbEl5dOm # NRH7C26Z/xVMDwT08kDDq0t8Rkz4836txPO7y+aPbtvGfENRI8E= # =mtVb # -----END PGP SIGNATURE----- # gpg: Signature made Mon 03 Jun 2024 12:40:07 AM CDT # gpg: using RSA key 6AE902B6A7CA877D6D659296AF7C95130C538013 # gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 6AE9 02B6 A7CA 877D 6D65 9296 AF7C 9513 0C53 8013 * tag 'pull-riscv-to-apply-20240603' of https://github.com/alistair23/qemu: (27 commits) disas/riscv: Decode all of the pmpcfg and pmpaddr CSRs riscv, gdbstub.c: fix reg_width in ricsv_gen_dynamic_vector_feature() target/riscv/kvm.c: Fix the hart bit setting of AIA target/riscv: rvzicbo: Fixup CBO extension register calculation target/riscv: Remove experimental prefix from "B" extension target/riscv: do not set mtval2 for non guest-page faults target/riscv: prioritize pmp errors in raise_mmu_exception() target/riscv: rvv: Remove redudant SEW checking for vector fp narrow/widen instructions target/riscv: rvv: Check single width operator for vfncvt.rod.f.f.w target/riscv: rvv: Check single width operator for vector fp widen instructions target/riscv: rvv: Fix Zvfhmin checking for vfwcvt.f.f.v and vfncvt.f.f.w instructions riscv: thead: Add th.sxstatus CSR emulation target/riscv: Implement dynamic establishment of custom decoder target/riscv/cpu.c: fix Zvkb extension config target/riscv: Fix the element agnostic function problem target/riscv: Relax vector register check in RISCV gdbstub target/riscv: Add support for Zve64x extension target/riscv: Add support for Zve32x extension trans_privileged.c.inc: set (m|s)tval on ebreak breakpoint target/riscv/debug: set tval=pc in breakpoint exceptions ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--MAINTAINERS1
-rw-r--r--disas/riscv.c65
-rw-r--r--hw/intc/riscv_aplic.c8
-rw-r--r--hw/riscv/boot.c4
-rw-r--r--target/riscv/cpu.c10
-rw-r--r--target/riscv/cpu.h7
-rw-r--r--target/riscv/cpu_bits.h2
-rw-r--r--target/riscv/cpu_cfg.h2
-rw-r--r--target/riscv/cpu_helper.c37
-rw-r--r--target/riscv/csr.c20
-rw-r--r--target/riscv/debug.c3
-rw-r--r--target/riscv/gdbstub.c8
-rw-r--r--target/riscv/helper.h1
-rw-r--r--target/riscv/insn_trans/trans_privileged.c.inc2
-rw-r--r--target/riscv/insn_trans/trans_rvv.c.inc46
-rw-r--r--target/riscv/insn_trans/trans_rvzawrs.c.inc29
-rw-r--r--target/riscv/insn_trans/trans_rvzicbo.c.inc16
-rw-r--r--target/riscv/kvm/kvm-cpu.c157
-rw-r--r--target/riscv/meson.build1
-rw-r--r--target/riscv/op_helper.c11
-rw-r--r--target/riscv/sbi_ecall_interface.h17
-rw-r--r--target/riscv/tcg/tcg-cpu.c50
-rw-r--r--target/riscv/tcg/tcg-cpu.h15
-rw-r--r--target/riscv/th_csr.c79
-rw-r--r--target/riscv/translate.c31
-rw-r--r--target/riscv/vector_internals.c22
26 files changed, 543 insertions, 101 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 448dc95..e9d861e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -343,6 +343,7 @@ L: qemu-riscv@nongnu.org
S: Supported
F: target/riscv/insn_trans/trans_xthead.c.inc
F: target/riscv/xthead*.decode
+F: target/riscv/th_*
F: disas/riscv-xthead*
RISC-V XVentanaCondOps extension
diff --git a/disas/riscv.c b/disas/riscv.c
index e236c8b..297cfa2 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -2190,7 +2190,22 @@ static const char *csr_name(int csrno)
case 0x0383: return "mibound";
case 0x0384: return "mdbase";
case 0x0385: return "mdbound";
- case 0x03a0: return "pmpcfg3";
+ case 0x03a0: return "pmpcfg0";
+ case 0x03a1: return "pmpcfg1";
+ case 0x03a2: return "pmpcfg2";
+ case 0x03a3: return "pmpcfg3";
+ case 0x03a4: return "pmpcfg4";
+ case 0x03a5: return "pmpcfg5";
+ case 0x03a6: return "pmpcfg6";
+ case 0x03a7: return "pmpcfg7";
+ case 0x03a8: return "pmpcfg8";
+ case 0x03a9: return "pmpcfg9";
+ case 0x03aa: return "pmpcfg10";
+ case 0x03ab: return "pmpcfg11";
+ case 0x03ac: return "pmpcfg12";
+ case 0x03ad: return "pmpcfg13";
+ case 0x03ae: return "pmpcfg14";
+ case 0x03af: return "pmpcfg15";
case 0x03b0: return "pmpaddr0";
case 0x03b1: return "pmpaddr1";
case 0x03b2: return "pmpaddr2";
@@ -2207,6 +2222,54 @@ static const char *csr_name(int csrno)
case 0x03bd: return "pmpaddr13";
case 0x03be: return "pmpaddr14";
case 0x03bf: return "pmpaddr15";
+ case 0x03c0: return "pmpaddr16";
+ case 0x03c1: return "pmpaddr17";
+ case 0x03c2: return "pmpaddr18";
+ case 0x03c3: return "pmpaddr19";
+ case 0x03c4: return "pmpaddr20";
+ case 0x03c5: return "pmpaddr21";
+ case 0x03c6: return "pmpaddr22";
+ case 0x03c7: return "pmpaddr23";
+ case 0x03c8: return "pmpaddr24";
+ case 0x03c9: return "pmpaddr25";
+ case 0x03ca: return "pmpaddr26";
+ case 0x03cb: return "pmpaddr27";
+ case 0x03cc: return "pmpaddr28";
+ case 0x03cd: return "pmpaddr29";
+ case 0x03ce: return "pmpaddr30";
+ case 0x03cf: return "pmpaddr31";
+ case 0x03d0: return "pmpaddr32";
+ case 0x03d1: return "pmpaddr33";
+ case 0x03d2: return "pmpaddr34";
+ case 0x03d3: return "pmpaddr35";
+ case 0x03d4: return "pmpaddr36";
+ case 0x03d5: return "pmpaddr37";
+ case 0x03d6: return "pmpaddr38";
+ case 0x03d7: return "pmpaddr39";
+ case 0x03d8: return "pmpaddr40";
+ case 0x03d9: return "pmpaddr41";
+ case 0x03da: return "pmpaddr42";
+ case 0x03db: return "pmpaddr43";
+ case 0x03dc: return "pmpaddr44";
+ case 0x03dd: return "pmpaddr45";
+ case 0x03de: return "pmpaddr46";
+ case 0x03df: return "pmpaddr47";
+ case 0x03e0: return "pmpaddr48";
+ case 0x03e1: return "pmpaddr49";
+ case 0x03e2: return "pmpaddr50";
+ case 0x03e3: return "pmpaddr51";
+ case 0x03e4: return "pmpaddr52";
+ case 0x03e5: return "pmpaddr53";
+ case 0x03e6: return "pmpaddr54";
+ case 0x03e7: return "pmpaddr55";
+ case 0x03e8: return "pmpaddr56";
+ case 0x03e9: return "pmpaddr57";
+ case 0x03ea: return "pmpaddr58";
+ case 0x03eb: return "pmpaddr59";
+ case 0x03ec: return "pmpaddr60";
+ case 0x03ed: return "pmpaddr61";
+ case 0x03ee: return "pmpaddr62";
+ case 0x03ef: return "pmpaddr63";
case 0x0780: return "mtohost";
case 0x0781: return "mfromhost";
case 0x0782: return "mreset";
diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index fc5df0d..32edd6d 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -1000,16 +1000,16 @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size,
qdev_prop_set_bit(dev, "msimode", msimode);
qdev_prop_set_bit(dev, "mmode", mmode);
+ if (parent) {
+ riscv_aplic_add_child(parent, dev);
+ }
+
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
if (!is_kvm_aia(msimode)) {
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr);
}
- if (parent) {
- riscv_aplic_add_child(parent, dev);
- }
-
if (!msimode) {
for (i = 0; i < num_harts; i++) {
CPUState *cpu = cpu_by_arch_id(hartid_base + i);
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 09878e7..47281ca 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -209,8 +209,8 @@ static void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry)
/* Some RISC-V machines (e.g. opentitan) don't have a fdt. */
if (fdt) {
end = start + size;
- qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", start);
- qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", end);
+ qemu_fdt_setprop_u64(fdt, "/chosen", "linux,initrd-start", start);
+ qemu_fdt_setprop_u64(fdt, "/chosen", "linux,initrd-end", end);
}
}
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index eb1a2e7..cee6fc4 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -153,8 +153,10 @@ const RISCVIsaExtData isa_edata_arr[] = {
ISA_EXT_DATA_ENTRY(zvbb, PRIV_VERSION_1_12_0, ext_zvbb),
ISA_EXT_DATA_ENTRY(zvbc, PRIV_VERSION_1_12_0, ext_zvbc),
ISA_EXT_DATA_ENTRY(zve32f, PRIV_VERSION_1_10_0, ext_zve32f),
+ ISA_EXT_DATA_ENTRY(zve32x, PRIV_VERSION_1_10_0, ext_zve32x),
ISA_EXT_DATA_ENTRY(zve64f, PRIV_VERSION_1_10_0, ext_zve64f),
ISA_EXT_DATA_ENTRY(zve64d, PRIV_VERSION_1_10_0, ext_zve64d),
+ ISA_EXT_DATA_ENTRY(zve64x, PRIV_VERSION_1_10_0, ext_zve64x),
ISA_EXT_DATA_ENTRY(zvfbfmin, PRIV_VERSION_1_12_0, ext_zvfbfmin),
ISA_EXT_DATA_ENTRY(zvfbfwma, PRIV_VERSION_1_12_0, ext_zvfbfwma),
ISA_EXT_DATA_ENTRY(zvfh, PRIV_VERSION_1_12_0, ext_zvfh),
@@ -545,6 +547,7 @@ static void rv64_thead_c906_cpu_init(Object *obj)
cpu->cfg.mvendorid = THEAD_VENDOR_ID;
#ifndef CONFIG_USER_ONLY
set_satp_mode_max_supported(cpu, VM_1_10_SV39);
+ th_register_custom_csrs(cpu);
#endif
/* inherited from parent obj via riscv_cpu_init() */
@@ -1132,6 +1135,7 @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
error_propagate(errp, local_err);
return;
}
+ riscv_tcg_cpu_finalize_dynamic_decoder(cpu);
} else if (kvm_enabled()) {
riscv_kvm_cpu_finalize_features(cpu, &local_err);
if (local_err != NULL) {
@@ -1396,7 +1400,7 @@ static const MISAExtInfo misa_ext_info_arr[] = {
MISA_EXT_INFO(RVJ, "x-j", "Dynamic translated languages"),
MISA_EXT_INFO(RVV, "v", "Vector operations"),
MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
- MISA_EXT_INFO(RVB, "x-b", "Bit manipulation (Zba_Zbb_Zbs)")
+ MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
};
static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)
@@ -1472,8 +1476,10 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
MULTI_EXT_CFG_BOOL("zfh", ext_zfh, false),
MULTI_EXT_CFG_BOOL("zfhmin", ext_zfhmin, false),
MULTI_EXT_CFG_BOOL("zve32f", ext_zve32f, false),
+ MULTI_EXT_CFG_BOOL("zve32x", ext_zve32x, false),
MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false),
MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false),
+ MULTI_EXT_CFG_BOOL("zve64x", ext_zve64x, false),
MULTI_EXT_CFG_BOOL("zvfbfmin", ext_zvfbfmin, false),
MULTI_EXT_CFG_BOOL("zvfbfwma", ext_zvfbfwma, false),
MULTI_EXT_CFG_BOOL("zvfh", ext_zvfh, false),
@@ -1535,7 +1541,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
/* Vector cryptography extensions */
MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false),
- MULTI_EXT_CFG_BOOL("zvkb", ext_zvkg, false),
+ MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false),
MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false),
MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false),
MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 2d0c02c..12d8b53 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -455,6 +455,7 @@ struct ArchCPU {
uint32_t pmu_avail_ctrs;
/* Mapping of events to counters */
GHashTable *pmu_event_ctr_map;
+ const GPtrArray *decoders;
};
/**
@@ -819,7 +820,13 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
+target_ulong riscv_new_csr_seed(target_ulong new_value,
+ target_ulong write_mask);
+
uint8_t satp_mode_max_from_map(uint32_t map);
const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
+/* Implemented in th_csr.c */
+void th_register_custom_csrs(RISCVCPU *cpu);
+
#endif /* RISCV_CPU_H */
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index fc2068e..74318a9 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -670,11 +670,11 @@ typedef enum RISCVException {
RISCV_EXCP_INST_PAGE_FAULT = 0xc, /* since: priv-1.10.0 */
RISCV_EXCP_LOAD_PAGE_FAULT = 0xd, /* since: priv-1.10.0 */
RISCV_EXCP_STORE_PAGE_FAULT = 0xf, /* since: priv-1.10.0 */
- RISCV_EXCP_SEMIHOST = 0x10,
RISCV_EXCP_INST_GUEST_PAGE_FAULT = 0x14,
RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT = 0x15,
RISCV_EXCP_VIRT_INSTRUCTION_FAULT = 0x16,
RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT = 0x17,
+ RISCV_EXCP_SEMIHOST = 0x3f,
} RISCVException;
#define RISCV_EXCP_INT_FLAG 0x80000000
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index cb75015..e1e4f32 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -91,8 +91,10 @@ struct RISCVCPUConfig {
bool ext_zhinx;
bool ext_zhinxmin;
bool ext_zve32f;
+ bool ext_zve32x;
bool ext_zve64f;
bool ext_zve64d;
+ bool ext_zve64x;
bool ext_zvbb;
bool ext_zvbc;
bool ext_zvkb;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 8ad546a..a02497d 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -73,7 +73,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
*pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
*cs_base = 0;
- if (cpu->cfg.ext_zve32f) {
+ if (cpu->cfg.ext_zve32x) {
/*
* If env->vl equals to VLMAX, we can use generic vector operation
* expanders (GVEC) to accerlate the vector operations.
@@ -1177,28 +1177,30 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
switch (access_type) {
case MMU_INST_FETCH:
- if (env->virt_enabled && !first_stage) {
+ if (pmp_violation) {
+ cs->exception_index = RISCV_EXCP_INST_ACCESS_FAULT;
+ } else if (env->virt_enabled && !first_stage) {
cs->exception_index = RISCV_EXCP_INST_GUEST_PAGE_FAULT;
} else {
- cs->exception_index = pmp_violation ?
- RISCV_EXCP_INST_ACCESS_FAULT : RISCV_EXCP_INST_PAGE_FAULT;
+ cs->exception_index = RISCV_EXCP_INST_PAGE_FAULT;
}
break;
case MMU_DATA_LOAD:
- if (two_stage && !first_stage) {
+ if (pmp_violation) {
+ cs->exception_index = RISCV_EXCP_LOAD_ACCESS_FAULT;
+ } else if (two_stage && !first_stage) {
cs->exception_index = RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT;
} else {
- cs->exception_index = pmp_violation ?
- RISCV_EXCP_LOAD_ACCESS_FAULT : RISCV_EXCP_LOAD_PAGE_FAULT;
+ cs->exception_index = RISCV_EXCP_LOAD_PAGE_FAULT;
}
break;
case MMU_DATA_STORE:
- if (two_stage && !first_stage) {
+ if (pmp_violation) {
+ cs->exception_index = RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
+ } else if (two_stage && !first_stage) {
cs->exception_index = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT;
} else {
- cs->exception_index = pmp_violation ?
- RISCV_EXCP_STORE_AMO_ACCESS_FAULT :
- RISCV_EXCP_STORE_PAGE_FAULT;
+ cs->exception_index = RISCV_EXCP_STORE_PAGE_FAULT;
}
break;
default:
@@ -1374,17 +1376,17 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
__func__, pa, ret, prot_pmp, tlb_size);
prot &= prot_pmp;
- }
-
- if (ret != TRANSLATE_SUCCESS) {
+ } else {
/*
* Guest physical address translation failed, this is a HS
* level exception
*/
first_stage_error = false;
- env->guest_phys_fault_addr = (im_address |
- (address &
- (TARGET_PAGE_SIZE - 1))) >> 2;
+ if (ret != TRANSLATE_PMP_FAIL) {
+ env->guest_phys_fault_addr = (im_address |
+ (address &
+ (TARGET_PAGE_SIZE - 1))) >> 2;
+ }
}
}
} else {
@@ -1718,6 +1720,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
tval = env->bins;
break;
case RISCV_EXCP_BREAKPOINT:
+ tval = env->badaddr;
if (cs->watchpoint_hit) {
tval = cs->watchpoint_hit->hitaddr;
cs->watchpoint_hit = NULL;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 7260964..58ef707 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -93,7 +93,7 @@ static RISCVException fs(CPURISCVState *env, int csrno)
static RISCVException vs(CPURISCVState *env, int csrno)
{
- if (riscv_cpu_cfg(env)->ext_zve32f) {
+ if (riscv_cpu_cfg(env)->ext_zve32x) {
#if !defined(CONFIG_USER_ONLY)
if (!env->debugger && !riscv_cpu_vector_enabled(env)) {
return RISCV_EXCP_ILLEGAL_INST;
@@ -4267,10 +4267,8 @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno,
#endif
/* Crypto Extension */
-static RISCVException rmw_seed(CPURISCVState *env, int csrno,
- target_ulong *ret_value,
- target_ulong new_value,
- target_ulong write_mask)
+target_ulong riscv_new_csr_seed(target_ulong new_value,
+ target_ulong write_mask)
{
uint16_t random_v;
Error *random_e = NULL;
@@ -4294,6 +4292,18 @@ static RISCVException rmw_seed(CPURISCVState *env, int csrno,
rval = random_v | SEED_OPST_ES16;
}
+ return rval;
+}
+
+static RISCVException rmw_seed(CPURISCVState *env, int csrno,
+ target_ulong *ret_value,
+ target_ulong new_value,
+ target_ulong write_mask)
+{
+ target_ulong rval;
+
+ rval = riscv_new_csr_seed(new_value, write_mask);
+
if (ret_value) {
*ret_value = rval;
}
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index e30d99c..b110370 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -798,6 +798,7 @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) {
/* check U/S/M bit against current privilege level */
if ((ctrl >> 3) & BIT(env->priv)) {
+ env->badaddr = pc;
return true;
}
}
@@ -810,11 +811,13 @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
if (env->virt_enabled) {
/* check VU/VS bit against current privilege level */
if ((ctrl >> 23) & BIT(env->priv)) {
+ env->badaddr = pc;
return true;
}
} else {
/* check U/S/M bit against current privilege level */
if ((ctrl >> 3) & BIT(env->priv)) {
+ env->badaddr = pc;
return true;
}
}
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index be7a02c..c07df97 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -288,7 +288,7 @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState *cs, int base_reg)
static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
{
RISCVCPU *cpu = RISCV_CPU(cs);
- int reg_width = cpu->cfg.vlenb;
+ int bitsize = cpu->cfg.vlenb << 3;
GDBFeatureBuilder builder;
int i;
@@ -298,7 +298,7 @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
/* First define types and totals in a whole VL */
for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
- int count = reg_width / vec_lanes[i].size;
+ int count = bitsize / vec_lanes[i].size;
gdb_feature_builder_append_tag(
&builder, "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>",
vec_lanes[i].id, vec_lanes[i].gdb_type, count);
@@ -316,7 +316,7 @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
/* Define vector registers */
for (i = 0; i < 32; i++) {
gdb_feature_builder_append_reg(&builder, g_strdup_printf("v%d", i),
- reg_width, i, "riscv_vector", "vector");
+ bitsize, i, "riscv_vector", "vector");
}
gdb_feature_builder_end(&builder);
@@ -338,7 +338,7 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
gdb_find_static_feature("riscv-32bit-fpu.xml"),
0);
}
- if (env->misa_ext & RVV) {
+ if (cpu->cfg.ext_zve32x) {
gdb_register_coprocessor(cs, riscv_gdb_get_vector,
riscv_gdb_set_vector,
ricsv_gen_dynamic_vector_feature(cs, cs->gdb_num_regs),
diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 8a63523..451261c 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -132,6 +132,7 @@ DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
DEF_HELPER_1(sret, tl, env)
DEF_HELPER_1(mret, tl, env)
DEF_HELPER_1(wfi, void, env)
+DEF_HELPER_1(wrs_nto, void, env)
DEF_HELPER_1(tlb_flush, void, env)
DEF_HELPER_1(tlb_flush_all, void, env)
/* Native Debug */
diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
index 620ab54..bc5263a 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -62,6 +62,8 @@ static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
if (pre == 0x01f01013 && ebreak == 0x00100073 && post == 0x40705013) {
generate_exception(ctx, RISCV_EXCP_SEMIHOST);
} else {
+ tcg_gen_st_tl(tcg_constant_tl(ebreak_addr), tcg_env,
+ offsetof(CPURISCVState, badaddr));
generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
}
return true;
diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc
index 7d84e7d..3a3896b 100644
--- a/target/riscv/insn_trans/trans_rvv.c.inc
+++ b/target/riscv/insn_trans/trans_rvv.c.inc
@@ -50,6 +50,22 @@ static bool require_rvf(DisasContext *s)
}
}
+static bool require_rvfmin(DisasContext *s)
+{
+ if (s->mstatus_fs == EXT_STATUS_DISABLED) {
+ return false;
+ }
+
+ switch (s->sew) {
+ case MO_16:
+ return s->cfg_ptr->ext_zvfhmin;
+ case MO_32:
+ return s->cfg_ptr->ext_zve32f;
+ default:
+ return false;
+ }
+}
+
static bool require_scale_rvf(DisasContext *s)
{
if (s->mstatus_fs == EXT_STATUS_DISABLED) {
@@ -75,8 +91,6 @@ static bool require_scale_rvfmin(DisasContext *s)
}
switch (s->sew) {
- case MO_8:
- return s->cfg_ptr->ext_zvfhmin;
case MO_16:
return s->cfg_ptr->ext_zve32f;
case MO_32:
@@ -149,7 +163,7 @@ static bool do_vsetvl(DisasContext *s, int rd, int rs1, TCGv s2)
{
TCGv s1, dst;
- if (!require_rvv(s) || !s->cfg_ptr->ext_zve32f) {
+ if (!require_rvv(s) || !s->cfg_ptr->ext_zve32x) {
return false;
}
@@ -179,7 +193,7 @@ static bool do_vsetivli(DisasContext *s, int rd, TCGv s1, TCGv s2)
{
TCGv dst;
- if (!require_rvv(s) || !s->cfg_ptr->ext_zve32f) {
+ if (!require_rvv(s) || !s->cfg_ptr->ext_zve32x) {
return false;
}
@@ -2317,8 +2331,8 @@ GEN_OPFVF_TRANS(vfrsub_vf, opfvf_check)
static bool opfvv_widen_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
+ require_rvf(s) &&
require_scale_rvf(s) &&
- (s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_dss(s, a->rd, a->rs1, a->rs2, a->vm);
}
@@ -2356,8 +2370,8 @@ GEN_OPFVV_WIDEN_TRANS(vfwsub_vv, opfvv_widen_check)
static bool opfvf_widen_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
+ require_rvf(s) &&
require_scale_rvf(s) &&
- (s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_ds(s, a->rd, a->rs2, a->vm);
}
@@ -2388,8 +2402,8 @@ GEN_OPFVF_WIDEN_TRANS(vfwsub_vf)
static bool opfwv_widen_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
+ require_rvf(s) &&
require_scale_rvf(s) &&
- (s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_dds(s, a->rd, a->rs1, a->rs2, a->vm);
}
@@ -2427,8 +2441,8 @@ GEN_OPFWV_WIDEN_TRANS(vfwsub_wv)
static bool opfwf_widen_check(DisasContext *s, arg_rmrr *a)
{
return require_rvv(s) &&
+ require_rvf(s) &&
require_scale_rvf(s) &&
- (s->sew != MO_8) &&
vext_check_isa_ill(s) &&
vext_check_dd(s, a->rd, a->rs2, a->vm);
}
@@ -2685,8 +2699,8 @@ static bool opxfv_widen_check(DisasContext *s, arg_rmr *a)
static bool opffv_widen_check(DisasContext *s, arg_rmr *a)
{
return opfv_widen_check(s, a) &&
- require_scale_rvfmin(s) &&
- (s->sew != MO_8);
+ require_rvfmin(s) &&
+ require_scale_rvfmin(s);
}
#define GEN_OPFV_WIDEN_TRANS(NAME, CHECK, HELPER, FRM) \
@@ -2790,15 +2804,15 @@ static bool opfxv_narrow_check(DisasContext *s, arg_rmr *a)
static bool opffv_narrow_check(DisasContext *s, arg_rmr *a)
{
return opfv_narrow_check(s, a) &&
- require_scale_rvfmin(s) &&
- (s->sew != MO_8);
+ require_rvfmin(s) &&
+ require_scale_rvfmin(s);
}
static bool opffv_rod_narrow_check(DisasContext *s, arg_rmr *a)
{
return opfv_narrow_check(s, a) &&
- require_scale_rvf(s) &&
- (s->sew != MO_8);
+ require_rvf(s) &&
+ require_scale_rvf(s);
}
#define GEN_OPFV_NARROW_TRANS(NAME, CHECK, HELPER, FRM) \
@@ -2925,8 +2939,8 @@ GEN_OPFVV_TRANS(vfredmin_vs, freduction_check)
static bool freduction_widen_check(DisasContext *s, arg_rmrr *a)
{
return reduction_widen_check(s, a) &&
- require_scale_rvf(s) &&
- (s->sew != MO_8);
+ require_rvf(s) &&
+ require_scale_rvf(s);
}
GEN_OPFVV_WIDEN_TRANS(vfwredusum_vs, freduction_widen_check)
diff --git a/target/riscv/insn_trans/trans_rvzawrs.c.inc b/target/riscv/insn_trans/trans_rvzawrs.c.inc
index 32efbff..0eef033 100644
--- a/target/riscv/insn_trans/trans_rvzawrs.c.inc
+++ b/target/riscv/insn_trans/trans_rvzawrs.c.inc
@@ -16,7 +16,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
-static bool trans_wrs(DisasContext *ctx)
+static bool trans_wrs_sto(DisasContext *ctx, arg_wrs_sto *a)
{
if (!ctx->cfg_ptr->ext_zawrs) {
return false;
@@ -40,12 +40,23 @@ static bool trans_wrs(DisasContext *ctx)
return true;
}
-#define GEN_TRANS_WRS(insn) \
-static bool trans_ ## insn(DisasContext *ctx, arg_ ## insn *a) \
-{ \
- (void)a; \
- return trans_wrs(ctx); \
-}
+static bool trans_wrs_nto(DisasContext *ctx, arg_wrs_nto *a)
+{
+ if (!ctx->cfg_ptr->ext_zawrs) {
+ return false;
+ }
-GEN_TRANS_WRS(wrs_nto)
-GEN_TRANS_WRS(wrs_sto)
+ /*
+ * Depending on the mode of execution, mstatus.TW and hstatus.VTW, wrs.nto
+ * should raise an exception when the implementation-specific bounded time
+ * limit has expired. Our time limit is zero, so we either return
+ * immediately, as does our implementation of wrs.sto, or raise an
+ * exception, as handled by the wrs.nto helper.
+ */
+#ifndef CONFIG_USER_ONLY
+ gen_helper_wrs_nto(tcg_env);
+#endif
+
+ /* We only get here when helper_wrs_nto() doesn't raise an exception. */
+ return trans_wrs_sto(ctx, NULL);
+}
diff --git a/target/riscv/insn_trans/trans_rvzicbo.c.inc b/target/riscv/insn_trans/trans_rvzicbo.c.inc
index d5d7095..15711c3 100644
--- a/target/riscv/insn_trans/trans_rvzicbo.c.inc
+++ b/target/riscv/insn_trans/trans_rvzicbo.c.inc
@@ -31,27 +31,35 @@
static bool trans_cbo_clean(DisasContext *ctx, arg_cbo_clean *a)
{
REQUIRE_ZICBOM(ctx);
- gen_helper_cbo_clean_flush(tcg_env, cpu_gpr[a->rs1]);
+ TCGv src = get_address(ctx, a->rs1, 0);
+
+ gen_helper_cbo_clean_flush(tcg_env, src);
return true;
}
static bool trans_cbo_flush(DisasContext *ctx, arg_cbo_flush *a)
{
REQUIRE_ZICBOM(ctx);
- gen_helper_cbo_clean_flush(tcg_env, cpu_gpr[a->rs1]);
+ TCGv src = get_address(ctx, a->rs1, 0);
+
+ gen_helper_cbo_clean_flush(tcg_env, src);
return true;
}
static bool trans_cbo_inval(DisasContext *ctx, arg_cbo_inval *a)
{
REQUIRE_ZICBOM(ctx);
- gen_helper_cbo_inval(tcg_env, cpu_gpr[a->rs1]);
+ TCGv src = get_address(ctx, a->rs1, 0);
+
+ gen_helper_cbo_inval(tcg_env, src);
return true;
}
static bool trans_cbo_zero(DisasContext *ctx, arg_cbo_zero *a)
{
REQUIRE_ZICBOZ(ctx);
- gen_helper_cbo_zero(tcg_env, cpu_gpr[a->rs1]);
+ TCGv src = get_address(ctx, a->rs1, 0);
+
+ gen_helper_cbo_zero(tcg_env, src);
return true;
}
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index eaa3612..235e2cd 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -409,6 +409,12 @@ static KVMCPUConfig kvm_v_vlenb = {
KVM_REG_RISCV_VECTOR_CSR_REG(vlenb)
};
+static KVMCPUConfig kvm_sbi_dbcn = {
+ .name = "sbi_dbcn",
+ .kvm_reg_id = KVM_REG_RISCV | KVM_REG_SIZE_U64 |
+ KVM_REG_RISCV_SBI_EXT | KVM_RISCV_SBI_EXT_DBCN
+};
+
static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
{
CPURISCVState *env = &cpu->env;
@@ -427,10 +433,14 @@ static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
reg = kvm_cpu_cfg_get(cpu, multi_ext_cfg);
ret = kvm_set_one_reg(cs, id, &reg);
if (ret != 0) {
- error_report("Unable to %s extension %s in KVM, error %d",
- reg ? "enable" : "disable",
- multi_ext_cfg->name, ret);
- exit(EXIT_FAILURE);
+ if (!reg && ret == -EINVAL) {
+ warn_report("KVM cannot disable extension %s",
+ multi_ext_cfg->name);
+ } else {
+ error_report("Unable to enable extension %s in KVM, error %d",
+ multi_ext_cfg->name, ret);
+ exit(EXIT_FAILURE);
+ }
}
}
}
@@ -1037,6 +1047,20 @@ static int uint64_cmp(const void *a, const void *b)
return 0;
}
+static void kvm_riscv_check_sbi_dbcn_support(RISCVCPU *cpu,
+ KVMScratchCPU *kvmcpu,
+ struct kvm_reg_list *reglist)
+{
+ struct kvm_reg_list *reg_search;
+
+ reg_search = bsearch(&kvm_sbi_dbcn.kvm_reg_id, reglist->reg, reglist->n,
+ sizeof(uint64_t), uint64_cmp);
+
+ if (reg_search) {
+ kvm_sbi_dbcn.supported = true;
+ }
+}
+
static void kvm_riscv_read_vlenb(RISCVCPU *cpu, KVMScratchCPU *kvmcpu,
struct kvm_reg_list *reglist)
{
@@ -1142,6 +1166,8 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu)
if (riscv_has_ext(&cpu->env, RVV)) {
kvm_riscv_read_vlenb(cpu, kvmcpu, reglist);
}
+
+ kvm_riscv_check_sbi_dbcn_support(cpu, kvmcpu, reglist);
}
static void riscv_init_kvm_registers(Object *cpu_obj)
@@ -1316,6 +1342,17 @@ static int kvm_vcpu_set_machine_ids(RISCVCPU *cpu, CPUState *cs)
return ret;
}
+static int kvm_vcpu_enable_sbi_dbcn(RISCVCPU *cpu, CPUState *cs)
+{
+ target_ulong reg = 1;
+
+ if (!kvm_sbi_dbcn.supported) {
+ return 0;
+ }
+
+ return kvm_set_one_reg(cs, kvm_sbi_dbcn.kvm_reg_id, &reg);
+}
+
int kvm_arch_init_vcpu(CPUState *cs)
{
int ret = 0;
@@ -1333,6 +1370,8 @@ int kvm_arch_init_vcpu(CPUState *cs)
kvm_riscv_update_cpu_misa_ext(cpu, cs);
kvm_riscv_update_cpu_cfg_isa_ext(cpu, cs);
+ ret = kvm_vcpu_enable_sbi_dbcn(cpu, cs);
+
return ret;
}
@@ -1390,6 +1429,79 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cs)
return true;
}
+static void kvm_riscv_handle_sbi_dbcn(CPUState *cs, struct kvm_run *run)
+{
+ g_autofree uint8_t *buf = NULL;
+ RISCVCPU *cpu = RISCV_CPU(cs);
+ target_ulong num_bytes;
+ uint64_t addr;
+ unsigned char ch;
+ int ret;
+
+ switch (run->riscv_sbi.function_id) {
+ case SBI_EXT_DBCN_CONSOLE_READ:
+ case SBI_EXT_DBCN_CONSOLE_WRITE:
+ num_bytes = run->riscv_sbi.args[0];
+
+ if (num_bytes == 0) {
+ run->riscv_sbi.ret[0] = SBI_SUCCESS;
+ run->riscv_sbi.ret[1] = 0;
+ break;
+ }
+
+ addr = run->riscv_sbi.args[1];
+
+ /*
+ * Handle the case where a 32 bit CPU is running in a
+ * 64 bit addressing env.
+ */
+ if (riscv_cpu_mxl(&cpu->env) == MXL_RV32) {
+ addr |= (uint64_t)run->riscv_sbi.args[2] << 32;
+ }
+
+ buf = g_malloc0(num_bytes);
+
+ if (run->riscv_sbi.function_id == SBI_EXT_DBCN_CONSOLE_READ) {
+ ret = qemu_chr_fe_read_all(serial_hd(0)->be, buf, num_bytes);
+ if (ret < 0) {
+ error_report("SBI_EXT_DBCN_CONSOLE_READ: error when "
+ "reading chardev");
+ exit(1);
+ }
+
+ cpu_physical_memory_write(addr, buf, ret);
+ } else {
+ cpu_physical_memory_read(addr, buf, num_bytes);
+
+ ret = qemu_chr_fe_write_all(serial_hd(0)->be, buf, num_bytes);
+ if (ret < 0) {
+ error_report("SBI_EXT_DBCN_CONSOLE_WRITE: error when "
+ "writing chardev");
+ exit(1);
+ }
+ }
+
+ run->riscv_sbi.ret[0] = SBI_SUCCESS;
+ run->riscv_sbi.ret[1] = ret;
+ break;
+ case SBI_EXT_DBCN_CONSOLE_WRITE_BYTE:
+ ch = run->riscv_sbi.args[0];
+ ret = qemu_chr_fe_write(serial_hd(0)->be, &ch, sizeof(ch));
+
+ if (ret < 0) {
+ error_report("SBI_EXT_DBCN_CONSOLE_WRITE_BYTE: error when "
+ "writing chardev");
+ exit(1);
+ }
+
+ run->riscv_sbi.ret[0] = SBI_SUCCESS;
+ run->riscv_sbi.ret[1] = 0;
+ break;
+ default:
+ run->riscv_sbi.ret[0] = SBI_ERR_NOT_SUPPORTED;
+ }
+}
+
static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
{
int ret = 0;
@@ -1408,6 +1520,9 @@ static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
}
ret = 0;
break;
+ case SBI_EXT_DBCN:
+ kvm_riscv_handle_sbi_dbcn(cs, run);
+ break;
default:
qemu_log_mask(LOG_UNIMP,
"%s: un-handled SBI EXIT, specific reasons is %lu\n",
@@ -1418,6 +1533,28 @@ static int kvm_riscv_handle_sbi(CPUState *cs, struct kvm_run *run)
return ret;
}
+static int kvm_riscv_handle_csr(CPUState *cs, struct kvm_run *run)
+{
+ target_ulong csr_num = run->riscv_csr.csr_num;
+ target_ulong new_value = run->riscv_csr.new_value;
+ target_ulong write_mask = run->riscv_csr.write_mask;
+ int ret = 0;
+
+ switch (csr_num) {
+ case CSR_SEED:
+ run->riscv_csr.ret_value = riscv_new_csr_seed(new_value, write_mask);
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "%s: un-handled CSR EXIT for CSR %lx\n",
+ __func__, csr_num);
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
{
int ret = 0;
@@ -1425,6 +1562,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
case KVM_EXIT_RISCV_SBI:
ret = kvm_riscv_handle_sbi(cs, run);
break;
+ case KVM_EXIT_RISCV_CSR:
+ ret = kvm_riscv_handle_csr(cs, run);
+ break;
default:
qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n",
__func__, run->exit_reason);
@@ -1637,7 +1777,14 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
}
}
- hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
+
+ if (max_hart_per_socket > 1) {
+ max_hart_per_socket--;
+ hart_bits = find_last_bit(&max_hart_per_socket, BITS_PER_LONG) + 1;
+ } else {
+ hart_bits = 0;
+ }
+
ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
KVM_DEV_RISCV_AIA_CONFIG_HART_BITS,
&hart_bits, true, NULL);
diff --git a/target/riscv/meson.build b/target/riscv/meson.build
index a5e0734..a4bd61e 100644
--- a/target/riscv/meson.build
+++ b/target/riscv/meson.build
@@ -33,6 +33,7 @@ riscv_system_ss.add(files(
'monitor.c',
'machine.c',
'pmu.c',
+ 'th_csr.c',
'time_helper.c',
'riscv-qmp-cmds.c',
))
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index f414aae..2baf5bc 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -380,6 +380,17 @@ void helper_wfi(CPURISCVState *env)
}
}
+void helper_wrs_nto(CPURISCVState *env)
+{
+ if (env->virt_enabled && (env->priv == PRV_S || env->priv == PRV_U) &&
+ get_field(env->hstatus, HSTATUS_VTW) &&
+ !get_field(env->mstatus, MSTATUS_TW)) {
+ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
+ } else if (env->priv != PRV_M && get_field(env->mstatus, MSTATUS_TW)) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ }
+}
+
void helper_tlb_flush(CPURISCVState *env)
{
CPUState *cs = env_cpu(env);
diff --git a/target/riscv/sbi_ecall_interface.h b/target/riscv/sbi_ecall_interface.h
index 43899d0..7dfe5f7 100644
--- a/target/riscv/sbi_ecall_interface.h
+++ b/target/riscv/sbi_ecall_interface.h
@@ -12,6 +12,17 @@
/* clang-format off */
+#define SBI_SUCCESS 0
+#define SBI_ERR_FAILED -1
+#define SBI_ERR_NOT_SUPPORTED -2
+#define SBI_ERR_INVALID_PARAM -3
+#define SBI_ERR_DENIED -4
+#define SBI_ERR_INVALID_ADDRESS -5
+#define SBI_ERR_ALREADY_AVAILABLE -6
+#define SBI_ERR_ALREADY_STARTED -7
+#define SBI_ERR_ALREADY_STOPPED -8
+#define SBI_ERR_NO_SHMEM -9
+
/* SBI Extension IDs */
#define SBI_EXT_0_1_SET_TIMER 0x0
#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1
@@ -27,6 +38,7 @@
#define SBI_EXT_IPI 0x735049
#define SBI_EXT_RFENCE 0x52464E43
#define SBI_EXT_HSM 0x48534D
+#define SBI_EXT_DBCN 0x4442434E
/* SBI function IDs for BASE extension */
#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
@@ -57,6 +69,11 @@
#define SBI_EXT_HSM_HART_STOP 0x1
#define SBI_EXT_HSM_HART_GET_STATUS 0x2
+/* SBI function IDs for DBCN extension */
+#define SBI_EXT_DBCN_CONSOLE_WRITE 0x0
+#define SBI_EXT_DBCN_CONSOLE_READ 0x1
+#define SBI_EXT_DBCN_CONSOLE_WRITE_BYTE 0x2
+
#define SBI_HSM_HART_STATUS_STARTED 0x0
#define SBI_HSM_HART_STATUS_STOPPED 0x1
#define SBI_HSM_HART_STATUS_START_PENDING 0x2
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 40054a3..683f604 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -498,22 +498,31 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
/* The Zve64d extension depends on the Zve64f extension */
if (cpu->cfg.ext_zve64d) {
+ if (!riscv_has_ext(env, RVD)) {
+ error_setg(errp, "Zve64d/V extensions require D extension");
+ return;
+ }
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64f), true);
}
- /* The Zve64f extension depends on the Zve32f extension */
+ /* The Zve64f extension depends on the Zve64x and Zve32f extensions */
if (cpu->cfg.ext_zve64f) {
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64x), true);
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32f), true);
}
- if (cpu->cfg.ext_zve64d && !riscv_has_ext(env, RVD)) {
- error_setg(errp, "Zve64d/V extensions require D extension");
- return;
+ /* The Zve64x extension depends on the Zve32x extension */
+ if (cpu->cfg.ext_zve64x) {
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32x), true);
}
- if (cpu->cfg.ext_zve32f && !riscv_has_ext(env, RVF)) {
- error_setg(errp, "Zve32f/Zve64f extensions require F extension");
- return;
+ /* The Zve32f extension depends on the Zve32x extension */
+ if (cpu->cfg.ext_zve32f) {
+ if (!riscv_has_ext(env, RVF)) {
+ error_setg(errp, "Zve32f/Zve64f extensions require F extension");
+ return;
+ }
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32x), true);
}
if (cpu->cfg.ext_zvfh) {
@@ -658,22 +667,18 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbc), true);
}
- /*
- * In principle Zve*x would also suffice here, were they supported
- * in qemu
- */
if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkb || cpu->cfg.ext_zvkg ||
cpu->cfg.ext_zvkned || cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed ||
- cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32f) {
+ cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32x) {
error_setg(errp,
"Vector crypto extensions require V or Zve* extensions");
return;
}
- if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64f) {
+ if ((cpu->cfg.ext_zvbc || cpu->cfg.ext_zvknhb) && !cpu->cfg.ext_zve64x) {
error_setg(
errp,
- "Zvbc and Zvknhb extensions require V or Zve64{f,d} extensions");
+ "Zvbc and Zvknhb extensions require V or Zve64x extensions");
return;
}
@@ -858,6 +863,21 @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
}
}
+void riscv_tcg_cpu_finalize_dynamic_decoder(RISCVCPU *cpu)
+{
+ GPtrArray *dynamic_decoders;
+ dynamic_decoders = g_ptr_array_sized_new(decoder_table_size);
+ for (size_t i = 0; i < decoder_table_size; ++i) {
+ if (decoder_table[i].guard_func &&
+ decoder_table[i].guard_func(&cpu->cfg)) {
+ g_ptr_array_add(dynamic_decoders,
+ (gpointer)decoder_table[i].riscv_cpu_decode_fn);
+ }
+ }
+
+ cpu->decoders = dynamic_decoders;
+}
+
bool riscv_cpu_tcg_compatible(RISCVCPU *cpu)
{
return object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_CPU_HOST) == NULL;
@@ -1281,7 +1301,7 @@ static void riscv_init_max_cpu_extensions(Object *obj)
const RISCVCPUMultiExtConfig *prop;
/* Enable RVG, RVJ and RVV that are disabled by default */
- riscv_cpu_set_misa_ext(env, env->misa_ext | RVG | RVJ | RVV);
+ riscv_cpu_set_misa_ext(env, env->misa_ext | RVB | RVG | RVJ | RVV);
for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
isa_ext_update_enabled(cpu, prop->offset, true);
diff --git a/target/riscv/tcg/tcg-cpu.h b/target/riscv/tcg/tcg-cpu.h
index f7b3241..ce94253 100644
--- a/target/riscv/tcg/tcg-cpu.h
+++ b/target/riscv/tcg/tcg-cpu.h
@@ -26,4 +26,19 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp);
void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp);
bool riscv_cpu_tcg_compatible(RISCVCPU *cpu);
+struct DisasContext;
+struct RISCVCPUConfig;
+typedef struct RISCVDecoder {
+ bool (*guard_func)(const struct RISCVCPUConfig *);
+ bool (*riscv_cpu_decode_fn)(struct DisasContext *, uint32_t);
+} RISCVDecoder;
+
+typedef bool (*riscv_cpu_decode_fn)(struct DisasContext *, uint32_t);
+
+extern const size_t decoder_table_size;
+
+extern const RISCVDecoder decoder_table[];
+
+void riscv_tcg_cpu_finalize_dynamic_decoder(RISCVCPU *cpu);
+
#endif
diff --git a/target/riscv/th_csr.c b/target/riscv/th_csr.c
new file mode 100644
index 0000000..6c970d4
--- /dev/null
+++ b/target/riscv/th_csr.c
@@ -0,0 +1,79 @@
+/*
+ * T-Head-specific CSRs.
+ *
+ * Copyright (c) 2024 VRULL GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "cpu_vendorid.h"
+
+#define CSR_TH_SXSTATUS 0x5c0
+
+/* TH_SXSTATUS bits */
+#define TH_SXSTATUS_UCME BIT(16)
+#define TH_SXSTATUS_MAEE BIT(21)
+#define TH_SXSTATUS_THEADISAEE BIT(22)
+
+typedef struct {
+ int csrno;
+ int (*insertion_test)(RISCVCPU *cpu);
+ riscv_csr_operations csr_ops;
+} riscv_csr;
+
+static RISCVException smode(CPURISCVState *env, int csrno)
+{
+ if (riscv_has_ext(env, RVS)) {
+ return RISCV_EXCP_NONE;
+ }
+
+ return RISCV_EXCP_ILLEGAL_INST;
+}
+
+static int test_thead_mvendorid(RISCVCPU *cpu)
+{
+ if (cpu->cfg.mvendorid != THEAD_VENDOR_ID) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static RISCVException read_th_sxstatus(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+ /* We don't set MAEE here, because QEMU does not implement MAEE. */
+ *val = TH_SXSTATUS_UCME | TH_SXSTATUS_THEADISAEE;
+ return RISCV_EXCP_NONE;
+}
+
+static riscv_csr th_csr_list[] = {
+ {
+ .csrno = CSR_TH_SXSTATUS,
+ .insertion_test = test_thead_mvendorid,
+ .csr_ops = { "th.sxstatus", smode, read_th_sxstatus }
+ }
+};
+
+void th_register_custom_csrs(RISCVCPU *cpu)
+{
+ for (size_t i = 0; i < ARRAY_SIZE(th_csr_list); i++) {
+ int csrno = th_csr_list[i].csrno;
+ riscv_csr_operations *csr_ops = &th_csr_list[i].csr_ops;
+ if (!th_csr_list[i].insertion_test(cpu)) {
+ riscv_set_csr_ops(csrno, csr_ops);
+ }
+ }
+}
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 2c27fd4..4cd6480 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -35,6 +35,8 @@
#include "exec/helper-info.c.inc"
#undef HELPER_H
+#include "tcg/tcg-cpu.h"
+
/* global register indices */
static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
@@ -114,6 +116,7 @@ typedef struct DisasContext {
/* FRM is known to contain a valid value. */
bool frm_valid;
bool insn_start_updated;
+ const GPtrArray *decoders;
} DisasContext;
static inline bool has_ext(DisasContext *ctx, uint32_t ext)
@@ -1123,21 +1126,16 @@ static inline int insn_len(uint16_t first_word)
return (first_word & 3) == 3 ? 4 : 2;
}
+const RISCVDecoder decoder_table[] = {
+ { always_true_p, decode_insn32 },
+ { has_xthead_p, decode_xthead},
+ { has_XVentanaCondOps_p, decode_XVentanaCodeOps},
+};
+
+const size_t decoder_table_size = ARRAY_SIZE(decoder_table);
+
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
{
- /*
- * A table with predicate (i.e., guard) functions and decoder functions
- * that are tested in-order until a decoder matches onto the opcode.
- */
- static const struct {
- bool (*guard_func)(const RISCVCPUConfig *);
- bool (*decode_func)(DisasContext *, uint32_t);
- } decoders[] = {
- { always_true_p, decode_insn32 },
- { has_xthead_p, decode_xthead },
- { has_XVentanaCondOps_p, decode_XVentanaCodeOps },
- };
-
ctx->virt_inst_excp = false;
ctx->cur_insn_len = insn_len(opcode);
/* Check for compressed insn */
@@ -1158,9 +1156,9 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
ctx->base.pc_next + 2));
ctx->opcode = opcode32;
- for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
- if (decoders[i].guard_func(ctx->cfg_ptr) &&
- decoders[i].decode_func(ctx, opcode32)) {
+ for (guint i = 0; i < ctx->decoders->len; ++i) {
+ riscv_cpu_decode_fn func = g_ptr_array_index(ctx->decoders, i);
+ if (func(ctx, opcode32)) {
return;
}
}
@@ -1205,6 +1203,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER);
ctx->zero = tcg_constant_tl(0);
ctx->virt_inst_excp = false;
+ ctx->decoders = cpu->decoders;
}
static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
diff --git a/target/riscv/vector_internals.c b/target/riscv/vector_internals.c
index 996c21e..05b2d01 100644
--- a/target/riscv/vector_internals.c
+++ b/target/riscv/vector_internals.c
@@ -30,6 +30,28 @@ void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt,
if (tot - cnt == 0) {
return ;
}
+
+ if (HOST_BIG_ENDIAN) {
+ /*
+ * Deal the situation when the elements are insdie
+ * only one uint64 block including setting the
+ * masked-off element.
+ */
+ if (((tot - 1) ^ cnt) < 8) {
+ memset(base + H1(tot - 1), -1, tot - cnt);
+ return;
+ }
+ /*
+ * Otherwise, at least cross two uint64_t blocks.
+ * Set first unaligned block.
+ */
+ if (cnt % 8 != 0) {
+ uint32_t j = ROUND_UP(cnt, 8);
+ memset(base + H1(j - 1), -1, j - cnt);
+ cnt = j;
+ }
+ /* Set other 64bit aligend blocks */
+ }
memset(base + cnt, -1, tot - cnt);
}