diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2014-03-28 11:43:45 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-06-05 16:10:34 +0200 |
commit | 8a201bd47e4724c5783033aedbdd126a5df7a251 (patch) | |
tree | 1f4d90bf910f1eea3544286c076a0f5deddcaf86 | |
parent | 81cf8d8adc64203567e03326c13ea4abec9fe5df (diff) | |
download | hqemu-8a201bd47e4724c5783033aedbdd126a5df7a251.zip hqemu-8a201bd47e4724c5783033aedbdd126a5df7a251.tar.gz |
target-i386: fix kernel accesses with SMAP and CPL = 3
With SMAP, implicit kernel accesses from user mode always behave as
if AC=0. To do this, kernel mode is not anymore a separate MMU mode.
Instead, KERNEL_IDX is renamed to KSMAP_IDX and the kernel mode accessors
wrap KSMAP_IDX and KNOSMAP_IDX.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | target-i386/cpu.h | 15 | ||||
-rw-r--r-- | target-i386/helper.c | 8 | ||||
-rw-r--r-- | target-i386/seg_helper.c | 18 |
3 files changed, 33 insertions, 8 deletions
diff --git a/target-i386/cpu.h b/target-i386/cpu.h index f88b675..b80df66 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1153,17 +1153,24 @@ static inline CPUX86State *cpu_init(const char *cpu_model) #define cpudef_setup x86_cpudef_setup /* MMU modes definitions */ -#define MMU_MODE0_SUFFIX _kernel +#define MMU_MODE0_SUFFIX _ksmap #define MMU_MODE1_SUFFIX _user #define MMU_MODE2_SUFFIX _knosmap /* SMAP disabled or CPL<3 && AC=1 */ -#define MMU_KERNEL_IDX 0 +#define MMU_KSMAP_IDX 0 #define MMU_USER_IDX 1 #define MMU_KNOSMAP_IDX 2 -static inline int cpu_mmu_index (CPUX86State *env) +static inline int cpu_mmu_index(CPUX86State *env) { return (env->hflags & HF_CPL_MASK) == 3 ? MMU_USER_IDX : ((env->hflags & HF_SMAP_MASK) && (env->eflags & AC_MASK)) - ? MMU_KNOSMAP_IDX : MMU_KERNEL_IDX; + ? MMU_KNOSMAP_IDX : MMU_KSMAP_IDX; +} + +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; } #define CC_DST (env->cc_dst) diff --git a/target-i386/helper.c b/target-i386/helper.c index 88bbe65..6d8e350 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -648,7 +648,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, } break; - case MMU_KERNEL_IDX: + case MMU_KSMAP_IDX: if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) && (ptep & PG_USER_MASK)) { goto do_fault_protect; @@ -710,7 +710,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, } break; - case MMU_KERNEL_IDX: + case MMU_KSMAP_IDX: if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) && (ptep & PG_USER_MASK)) { goto do_fault_protect; @@ -765,7 +765,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, } break; - case MMU_KERNEL_IDX: + case MMU_KSMAP_IDX: if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) && (pde & PG_USER_MASK)) { goto do_fault_protect; @@ -822,7 +822,7 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr, } break; - case MMU_KERNEL_IDX: + case MMU_KSMAP_IDX: if (is_write1 != 2 && (env->cr[4] & CR4_SMAP_MASK) && (ptep & PG_USER_MASK)) { goto do_fault_protect; diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c index 31c5508..934cc2b 100644 --- a/target-i386/seg_helper.c +++ b/target-i386/seg_helper.c @@ -34,6 +34,24 @@ # define LOG_PCALL_STATE(cpu) do { } while (0) #endif +#ifndef CONFIG_USER_ONLY +#define CPU_MMU_INDEX (cpu_mmu_index_kernel(env)) +#define MEMSUFFIX _kernel +#define DATA_SIZE 1 +#include "exec/cpu_ldst_template.h" + +#define DATA_SIZE 2 +#include "exec/cpu_ldst_template.h" + +#define DATA_SIZE 4 +#include "exec/cpu_ldst_template.h" + +#define DATA_SIZE 8 +#include "exec/cpu_ldst_template.h" +#undef CPU_MMU_INDEX +#undef MEMSUFFIX +#endif + /* return non zero if error */ static inline int load_segment(CPUX86State *env, uint32_t *e1_ptr, uint32_t *e2_ptr, int selector) |