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 <pbonzini@redhat.com>
(cherry picked from commit 90f641531c
)
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-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.
)
This commit is contained in:
parent
6332f3c12f
commit
ad003650d5
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user