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:
Richard Henderson 2024-06-03 20:21:51 -05:00
commit d67a6e054b
26 changed files with 543 additions and 101 deletions

View File

@ -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

View File

@ -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";

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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),

View File

@ -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 */

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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),

View File

@ -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 */

View File

@ -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;

View File

@ -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)

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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',
))

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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
View 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);
}
}
}

View File

@ -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)

View File

@ -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);
}