#define HSTATUS_WPRI HSTATUS64_WPRI
#endif
+#define HCOUNTEREN_CY (1 << 0)
+#define HCOUNTEREN_TM (1 << 1)
+#define HCOUNTEREN_IR (1 << 2)
+#define HCOUNTEREN_HPM3 (1 << 3)
+
/* Privilege modes */
#define PRV_U 0
#define PRV_S 1
#define RISCV_EXCP_STORE_PAGE_FAULT 0xf /* since: priv-1.10.0 */
#define RISCV_EXCP_INST_GUEST_PAGE_FAULT 0x14
#define RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT 0x15
+#define RISCV_EXCP_VIRT_INSTRUCTION_FAULT 0x16
#define RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT 0x17
#define RISCV_EXCP_INT_FLAG 0x80000000
/* The Counters extensions is not enabled */
return -RISCV_EXCP_ILLEGAL_INST;
}
+
+ if (riscv_cpu_virt_enabled(env)) {
+ switch (csrno) {
+ case CSR_CYCLE:
+ if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
+ get_field(env->mcounteren, HCOUNTEREN_CY)) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+ case CSR_TIME:
+ if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
+ get_field(env->mcounteren, HCOUNTEREN_TM)) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+ case CSR_INSTRET:
+ if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
+ get_field(env->mcounteren, HCOUNTEREN_IR)) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+ case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31:
+ if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3)) &&
+ get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3))) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+#if defined(TARGET_RISCV32)
+ case CSR_CYCLEH:
+ if (!get_field(env->hcounteren, HCOUNTEREN_CY) &&
+ get_field(env->mcounteren, HCOUNTEREN_CY)) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+ case CSR_TIMEH:
+ if (!get_field(env->hcounteren, HCOUNTEREN_TM) &&
+ get_field(env->mcounteren, HCOUNTEREN_TM)) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+ case CSR_INSTRETH:
+ if (!get_field(env->hcounteren, HCOUNTEREN_IR) &&
+ get_field(env->mcounteren, HCOUNTEREN_IR)) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+ case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
+ if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3H)) &&
+ get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3H))) {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
+ }
+ break;
+#endif
+ }
+ }
#endif
return 0;
}
if ((env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
env->priv == PRV_M) {
return 0;
+ } else {
+ return -RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
}
}
(1ULL << (RISCV_EXCP_STORE_PAGE_FAULT)) |
(1ULL << (RISCV_EXCP_INST_GUEST_PAGE_FAULT)) |
(1ULL << (RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT)) |
+ (1ULL << (RISCV_EXCP_VIRT_INSTRUCTION_FAULT)) |
(1ULL << (RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT));
static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE |
SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS |
}
/* check predicate */
- if (!csr_ops[csrno].predicate || csr_ops[csrno].predicate(env, csrno) < 0) {
+ if (!csr_ops[csrno].predicate) {
return -RISCV_EXCP_ILLEGAL_INST;
}
+ ret = csr_ops[csrno].predicate(env, csrno);
+ if (ret < 0) {
+ return ret;
+ }
/* execute combined read/write operation if it exists */
if (csr_ops[csrno].op) {
/* Hypervisor functions */
#ifndef CONFIG_USER_ONLY
DEF_HELPER_1(hyp_tlb_flush, void, env)
+DEF_HELPER_1(hyp_gvma_tlb_flush, void, env)
DEF_HELPER_4(hyp_load, tl, env, tl, tl, tl)
DEF_HELPER_5(hyp_store, void, env, tl, tl, tl, tl)
DEF_HELPER_4(hyp_x_load, tl, env, tl, tl, tl)
{
REQUIRE_EXT(ctx, RVH);
#ifndef CONFIG_USER_ONLY
- gen_helper_hyp_tlb_flush(cpu_env);
+ gen_helper_hyp_gvma_tlb_flush(cpu_env);
return true;
#endif
return false;
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
}
+ if (riscv_has_ext(env, RVH) && riscv_cpu_virt_enabled(env) &&
+ get_field(env->hstatus, HSTATUS_VTSR)) {
+ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
+ }
+
mstatus = env->mstatus;
if (riscv_has_ext(env, RVH) && !riscv_cpu_virt_enabled(env)) {
if ((env->priv == PRV_S &&
get_field(env->mstatus, MSTATUS_TW)) ||
riscv_cpu_virt_enabled(env)) {
- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
} else {
cs->halted = 1;
cs->exception_index = EXCP_HLT;
(env->priv == PRV_S &&
get_field(env->mstatus, MSTATUS_TVM))) {
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ } else if (riscv_has_ext(env, RVH) && riscv_cpu_virt_enabled(env) &&
+ get_field(env->hstatus, HSTATUS_VTVM)) {
+ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
} else {
tlb_flush(cs);
}
{
CPUState *cs = env_cpu(env);
+ if (env->priv == PRV_S && riscv_cpu_virt_enabled(env)) {
+ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
+ }
+
if (env->priv == PRV_M ||
(env->priv == PRV_S && !riscv_cpu_virt_enabled(env))) {
tlb_flush(cs);
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
}
+void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
+{
+ if (env->priv == PRV_S && !riscv_cpu_virt_enabled(env) &&
+ get_field(env->mstatus, MSTATUS_TVM)) {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ }
+
+ helper_hyp_tlb_flush(env);
+}
+
target_ulong helper_hyp_load(CPURISCVState *env, target_ulong address,
target_ulong attrs, target_ulong memop)
{
return pte;
}
- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ if (riscv_cpu_virt_enabled(env)) {
+ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
+ } else {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ }
return 0;
}
return;
}
- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ if (riscv_cpu_virt_enabled(env)) {
+ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
+ } else {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ }
}
target_ulong helper_hyp_x_load(CPURISCVState *env, target_ulong address,
return pte;
}
- riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ if (riscv_cpu_virt_enabled(env)) {
+ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
+ } else {
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+ }
return 0;
}