Skip to content

Commit

Permalink
target/i386: use separate MMU indexes for 32-bit accesses
Browse files Browse the repository at this point in the history
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 <pbonzini@redhat.com>
(cherry picked from commit 90f6415)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
(Mjt: move changes for x86_cpu_mmu_index() to cpu_mmu_index() due to missing
 v8.2.0-1030-gace0c5fe59 "target/i386: Populate CPUClass.mmu_index")
  • Loading branch information
bonzini authored and Michael Tokarev committed Mar 21, 2024
1 parent 6332f3c commit 6b9875b
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 14 deletions.
44 changes: 31 additions & 13 deletions target/i386/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion target/i386/tcg/sysemu/excp_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down

0 comments on commit 6b9875b

Please sign in to comment.