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----- 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>
This commit is contained in:
commit
d67a6e054b
@ -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
|
||||
|
@ -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";
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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, ®);
|
||||
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, ®);
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -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',
|
||||
))
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
79
target/riscv/th_csr.c
Normal file
79
target/riscv/th_csr.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user