target/riscv: Reduce overhead of MSTATUS_SUM change

Kernel needs to access user mode memory e.g. during syscalls, the window
is usually opened up for a very limited time through MSTATUS.SUM, the
overhead is too much if tlb_flush() gets called for every SUM change.

This patch creates a separate MMU index for S+SUM, so that it's not
necessary to flush tlb anymore when SUM changes. This is similar to how
ARM handles Privileged Access Never (PAN).

Result of 'pipe 10' from unixbench boosts from 223656 to 1705006. Many
other syscalls benefit a lot from this too.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Fei Wu <fei2.wu@intel.com>
Message-Id: <20230324054154.414846-3-fei2.wu@intel.com>
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
Tested-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Message-Id: <20230325105429.1142530-8-richard.henderson@linaro.org>
Message-Id: <20230412114333.118895-8-richard.henderson@linaro.org>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Fei Wu 2023-04-12 13:43:15 +02:00 committed by Alistair Francis
parent 47debc7280
commit c8f8a9957e
6 changed files with 35 additions and 10 deletions

View file

@ -21,6 +21,7 @@
#include "qemu/log.h"
#include "qemu/main-loop.h"
#include "cpu.h"
#include "internals.h"
#include "pmu.h"
#include "exec/exec-all.h"
#include "instmap.h"
@ -36,7 +37,19 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
#ifdef CONFIG_USER_ONLY
return 0;
#else
return env->priv;
if (ifetch) {
return env->priv;
}
/* All priv -> mmu_idx mapping are here */
int mode = env->priv;
if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) {
mode = get_field(env->mstatus, MSTATUS_MPP);
}
if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) {
return MMUIdx_S_SUM;
}
return mode;
#endif
}
@ -588,7 +601,7 @@ void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
bool riscv_cpu_two_stage_lookup(int mmu_idx)
{
return mmu_idx & TB_FLAGS_PRIV_HYP_ACCESS_MASK;
return mmu_idx & MMU_HYP_ACCESS_BIT;
}
int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)