@@ -383,6 +383,10 @@ struct CPUArchState {
uint64_t kvm_timer_compare;
uint64_t kvm_timer_state;
uint64_t kvm_timer_frequency;
+
+#define MAX_CACHED_SUM_U_ADDR_NUM 4
+ uint64_t sum_u_count;
+ uint64_t sum_u_addr[MAX_CACHED_SUM_U_ADDR_NUM];
};
OBJECT_DECLARE_CPU_TYPE(RISCVCPU, RISCVCPUClass, RISCV_CPU)
@@ -1068,6 +1068,13 @@ restart:
(access_type == MMU_DATA_STORE || (pte & PTE_D))) {
*prot |= PAGE_WRITE;
}
+ if ((pte & PTE_U) && (mode == PRV_S) &&
+ get_field(env->mstatus, MSTATUS_SUM)) {
+ if (env->sum_u_count < MAX_CACHED_SUM_U_ADDR_NUM) {
+ env->sum_u_addr[env->sum_u_count] = addr;
+ }
+ ++env->sum_u_count;
+ }
return TRANSLATE_SUCCESS;
}
}
@@ -1246,9 +1246,21 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
/* flush tlb on mstatus fields that affect VM */
if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
- MSTATUS_MPRV | MSTATUS_SUM)) {
+ MSTATUS_MPRV)) {
tlb_flush(env_cpu(env));
+ env->sum_u_count = 0;
+ } else if ((mstatus & MSTATUS_SUM) && !(val & MSTATUS_SUM)) {
+ if (env->sum_u_count > MAX_CACHED_SUM_U_ADDR_NUM) {
+ tlb_flush_by_mmuidx(env_cpu(env), 1 << PRV_S | 1 << PRV_M);
+ } else {
+ for (int i = 0; i < env->sum_u_count; ++i) {
+ tlb_flush_page_by_mmuidx(env_cpu(env), env->sum_u_addr[i],
+ 1 << PRV_S | 1 << PRV_M);
+ }
+ }
+ env->sum_u_count = 0;
}
+
mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE |
MSTATUS_SPP | MSTATUS_MPRV | MSTATUS_SUM |
MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |