From ad003650d539b9ad28a3c4f7580b2a7f1dacf8e5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 2 Jan 2024 15:40:18 +0100 Subject: [PATCH] target/i386: use separate MMU indexes for 32-bit accesses Accesses from a 32-bit environment (32-bit code segment for instruction accesses, EFER.LMA==0 for processor accesses) have to mask away the upper 32 bits of the address. While a bit wasteful, the easiest way to do so is to use separate MMU indexes. These days, QEMU anyway is compiled with a fixed value for NB_MMU_MODES. Split MMU_USER_IDX, MMU_KSMAP_IDX and MMU_KNOSMAP_IDX in two. Signed-off-by: Paolo Bonzini (cherry picked from commit 90f641531c782c873a05895f411c05fbbbef3c49) Signed-off-by: Michael Tokarev (Mjt: move changes for x86_cpu_mmu_index() to cpu_mmu_index() due to missing v8.2.0-1030-gace0c5fe5950 "target/i386: Populate CPUClass.mmu_index" Increase NB_MMU_MODES from 5 to 8 in target/i386/cpu-param.h due to missing v7.2.0-2640-gffd824f3f32d "include/exec: Set default NB_MMU_MODES to 16" v7.2.0-2647-g6787318a5d86 "target/i386: Remove NB_MMU_MODES define" which relaxed upper limit of MMU index for i386, since this commit starts using MMU_NESTED_IDX=7. Thanks Zhao Liu and Paolo Bonzini for the analisys and suggestions. ) --- target/i386/cpu-param.h | 2 +- target/i386/cpu.h | 44 ++++++++++++++++++++-------- target/i386/tcg/sysemu/excp_helper.c | 3 +- 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/target/i386/cpu-param.h b/target/i386/cpu-param.h index f579b16bd27..e21e472e1ed 100644 --- a/target/i386/cpu-param.h +++ b/target/i386/cpu-param.h @@ -23,7 +23,7 @@ # define TARGET_VIRT_ADDR_SPACE_BITS 32 #endif #define TARGET_PAGE_BITS 12 -#define NB_MMU_MODES 5 +#define NB_MMU_MODES 8 #ifndef CONFIG_USER_ONLY # define TARGET_TB_PCREL 1 diff --git a/target/i386/cpu.h b/target/i386/cpu.h index f175e18768d..73eee08f3fd 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2182,27 +2182,42 @@ uint64_t cpu_get_tsc(CPUX86State *env); #define cpu_list x86_cpu_list /* MMU modes definitions */ -#define MMU_KSMAP_IDX 0 -#define MMU_USER_IDX 1 -#define MMU_KNOSMAP_IDX 2 -#define MMU_NESTED_IDX 3 -#define MMU_PHYS_IDX 4 +#define MMU_KSMAP64_IDX 0 +#define MMU_KSMAP32_IDX 1 +#define MMU_USER64_IDX 2 +#define MMU_USER32_IDX 3 +#define MMU_KNOSMAP64_IDX 4 +#define MMU_KNOSMAP32_IDX 5 +#define MMU_PHYS_IDX 6 +#define MMU_NESTED_IDX 7 + +#ifdef CONFIG_USER_ONLY +#ifdef TARGET_X86_64 +#define MMU_USER_IDX MMU_USER64_IDX +#else +#define MMU_USER_IDX MMU_USER32_IDX +#endif +#endif static inline int cpu_mmu_index(CPUX86State *env, bool ifetch) { - return (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER_IDX : - (!(env->hflags & HF_SMAP_MASK) || (env->eflags & AC_MASK)) - ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX; + int mmu_index_32 = (env->hflags & HF_CS64_MASK) ? 1 : 0; + int mmu_index_base = + (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER64_IDX : + !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP64_IDX : + (env->eflags & AC_MASK) ? MMU_KNOSMAP64_IDX : MMU_KSMAP64_IDX; + + return mmu_index_base + mmu_index_32; } static inline bool is_mmu_index_smap(int mmu_index) { - return mmu_index == MMU_KSMAP_IDX; + return (mmu_index & ~1) == MMU_KSMAP64_IDX; } static inline bool is_mmu_index_user(int mmu_index) { - return mmu_index == MMU_USER_IDX; + return (mmu_index & ~1) == MMU_USER64_IDX; } static inline bool is_mmu_index_32(int mmu_index) @@ -2213,9 +2228,12 @@ static inline bool is_mmu_index_32(int mmu_index) static inline int cpu_mmu_index_kernel(CPUX86State *env) { - return !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP_IDX : - ((env->hflags & HF_CPL_MASK) < 3 && (env->eflags & AC_MASK)) - ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX; + int mmu_index_32 = (env->hflags & HF_LMA_MASK) ? 1 : 0; + int mmu_index_base = + !(env->hflags & HF_SMAP_MASK) ? MMU_KNOSMAP64_IDX : + ((env->hflags & HF_CPL_MASK) < 3 && (env->eflags & AC_MASK)) ? MMU_KNOSMAP64_IDX : MMU_KSMAP64_IDX; + + return mmu_index_base + mmu_index_32; } #define CC_DST (env->cc_dst) diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c index 553a60d9763..5f13252d687 100644 --- a/target/i386/tcg/sysemu/excp_helper.c +++ b/target/i386/tcg/sysemu/excp_helper.c @@ -541,7 +541,8 @@ static bool get_physical_address(CPUX86State *env, vaddr addr, if (likely(use_stage2)) { in.cr3 = env->nested_cr3; in.pg_mode = env->nested_pg_mode; - in.mmu_idx = MMU_USER_IDX; + in.mmu_idx = + env->nested_pg_mode & PG_MODE_LMA ? MMU_USER64_IDX : MMU_USER32_IDX; in.ptw_idx = MMU_PHYS_IDX; if (!mmu_translate(env, &in, out, err)) { -- 2.39.5