@@ -1281,6 +1281,38 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
}
}
}
+
+static void riscv_cpu_asid_finalized_features(RISCVCPU *cpu, Error **errp)
+{
+ bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32;
+ target_ulong asid_mask, asid_shift;
+ target_ulong calc_mask;
+
+ if (rv32) {
+ asid_mask = SATP32_ASID;
+ asid_shift = SATP32_ASID_SHIFT;
+ } else {
+ asid_mask = SATP64_ASID;
+ asid_shift = SATP64_ASID_SHIFT;
+ }
+
+ if (cpu->cfg.asid_bits < 0) {
+ cpu->env.asid_clear = 0;
+ return;
+ }
+
+ calc_mask = ((target_ulong)1 << cpu->cfg.asid_bits) - 1;
+ calc_mask <<= asid_shift;
+
+ if (calc_mask > asid_mask) {
+ error_setg(errp, "invalid ASID bits [0 %d]",
+ __builtin_clz(asid_mask >> asid_shift));
+ return;
+ }
+
+ cpu->env.asid_clear = calc_mask ^ asid_mask;
+}
+
#endif
static void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
@@ -1293,6 +1325,12 @@ static void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
error_propagate(errp, local_err);
return;
}
+
+ riscv_cpu_asid_finalized_features(cpu, &local_err);
+ if (local_err != NULL) {
+ error_propagate(errp, local_err);
+ return;
+ }
#endif
}
@@ -1648,6 +1686,10 @@ static Property riscv_cpu_extensions[] = {
DEFINE_PROP_BOOL("zicboz", RISCVCPU, cfg.ext_icboz, true),
DEFINE_PROP_UINT16("cboz_blocksize", RISCVCPU, cfg.cboz_blocksize, 64),
+#ifndef CONFIG_USER_ONLY
+ DEFINE_PROP_INT32("asid-bits", RISCVCPU, cfg.asid_bits, -1),
+#endif
+
DEFINE_PROP_BOOL("zmmul", RISCVCPU, cfg.ext_zmmul, false),
DEFINE_PROP_BOOL("zca", RISCVCPU, cfg.ext_zca, false),
@@ -194,6 +194,7 @@ struct CPUArchState {
uint64_t mideleg;
target_ulong satp; /* since: priv-1.10.0 */
+ target_ulong asid_clear; /* always clear these bits in satp */
target_ulong stval;
target_ulong medeleg;
@@ -617,11 +617,13 @@ typedef enum {
/* RV32 satp CSR field masks */
#define SATP32_MODE 0x80000000
#define SATP32_ASID 0x7fc00000
+#define SATP32_ASID_SHIFT 22
#define SATP32_PPN 0x003fffff
/* RV64 satp CSR field masks */
#define SATP64_MODE 0xF000000000000000ULL
#define SATP64_ASID 0x0FFFF00000000000ULL
+#define SATP64_ASID_SHIFT 44
#define SATP64_PPN 0x00000FFFFFFFFFFFULL
/* VM modes (satp.mode) privileged ISA 1.10 */
@@ -128,6 +128,7 @@ struct RISCVCPUConfig {
bool short_isa_string;
#ifndef CONFIG_USER_ONLY
+ int32_t asid_bits;
RISCVSATPMap satp_mode;
#endif
};
@@ -2731,6 +2731,7 @@ static RISCVException write_satp(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
+ val &= ~env->asid_clear;
if (riscv_cpu_mxl(env) == MXL_RV32) {
vm = validate_vm(env, get_field(val, SATP32_MODE));
mask = (val ^ env->satp) & (SATP32_MODE | SATP32_ASID | SATP32_PPN);
Add a config to the cpu state to control the size of the ASID area in the SATP CSR to enable testing with smaller than the default (which is currently maximum for both rv32 and rv64). It also adds the ability to stop the ASID feature by using 0 to disable it. For example, an rv64 with only 8 asid bits: -cpu rv64,asid-bits=8 or no asids: -cpu rv64,asid-bits=0 Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk> --- target/riscv/cpu.c | 42 +++++++++++++++++++++++++++++++++++++++++ target/riscv/cpu.h | 1 + target/riscv/cpu_bits.h | 2 ++ target/riscv/cpu_cfg.h | 1 + target/riscv/csr.c | 1 + 5 files changed, 47 insertions(+)