mirror of https://gitee.com/openkylin/qemu.git
target/i386: Throw a #SS when loading a non-canonical IST
Loading a non-canonical address into rsp when handling an interrupt or performing a far call should raise a #SS not a #GP. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/870 Signed-off-by: Gareth Webb <gareth.webb@umbralsoftware.co.uk> Message-Id: <164529651121.25406.15337137068584246397-0@git.sr.ht> [Move get_pg_mode to seg_helper.c for user-mode emulators. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
991ec97625
commit
50fcc7cbb6
|
@ -28,6 +28,42 @@
|
|||
#include "helper-tcg.h"
|
||||
#include "seg_helper.h"
|
||||
|
||||
int get_pg_mode(CPUX86State *env)
|
||||
{
|
||||
int pg_mode = 0;
|
||||
if (!(env->cr[0] & CR0_PG_MASK)) {
|
||||
return 0;
|
||||
}
|
||||
if (env->cr[0] & CR0_WP_MASK) {
|
||||
pg_mode |= PG_MODE_WP;
|
||||
}
|
||||
if (env->cr[4] & CR4_PAE_MASK) {
|
||||
pg_mode |= PG_MODE_PAE;
|
||||
if (env->efer & MSR_EFER_NXE) {
|
||||
pg_mode |= PG_MODE_NXE;
|
||||
}
|
||||
}
|
||||
if (env->cr[4] & CR4_PSE_MASK) {
|
||||
pg_mode |= PG_MODE_PSE;
|
||||
}
|
||||
if (env->cr[4] & CR4_SMEP_MASK) {
|
||||
pg_mode |= PG_MODE_SMEP;
|
||||
}
|
||||
if (env->hflags & HF_LMA_MASK) {
|
||||
pg_mode |= PG_MODE_LMA;
|
||||
if (env->cr[4] & CR4_PKE_MASK) {
|
||||
pg_mode |= PG_MODE_PKE;
|
||||
}
|
||||
if (env->cr[4] & CR4_PKS_MASK) {
|
||||
pg_mode |= PG_MODE_PKS;
|
||||
}
|
||||
if (env->cr[4] & CR4_LA57_MASK) {
|
||||
pg_mode |= PG_MODE_LA57;
|
||||
}
|
||||
}
|
||||
return pg_mode;
|
||||
}
|
||||
|
||||
/* return non zero if error */
|
||||
static inline int load_segment_ra(CPUX86State *env, uint32_t *e1_ptr,
|
||||
uint32_t *e2_ptr, int selector,
|
||||
|
@ -794,7 +830,9 @@ static void do_interrupt_protected(CPUX86State *env, int intno, int is_int,
|
|||
static inline target_ulong get_rsp_from_tss(CPUX86State *env, int level)
|
||||
{
|
||||
X86CPU *cpu = env_archcpu(env);
|
||||
int index;
|
||||
int index, pg_mode;
|
||||
target_ulong rsp;
|
||||
int32_t sext;
|
||||
|
||||
#if 0
|
||||
printf("TR: base=" TARGET_FMT_lx " limit=%x\n",
|
||||
|
@ -808,7 +846,17 @@ static inline target_ulong get_rsp_from_tss(CPUX86State *env, int level)
|
|||
if ((index + 7) > env->tr.limit) {
|
||||
raise_exception_err(env, EXCP0A_TSS, env->tr.selector & 0xfffc);
|
||||
}
|
||||
return cpu_ldq_kernel(env, env->tr.base + index);
|
||||
|
||||
rsp = cpu_ldq_kernel(env, env->tr.base + index);
|
||||
|
||||
/* test virtual address sign extension */
|
||||
pg_mode = get_pg_mode(env);
|
||||
sext = (int64_t)rsp >> (pg_mode & PG_MODE_LA57 ? 56 : 47);
|
||||
if (sext != 0 && sext != -1) {
|
||||
raise_exception_err(env, EXCP0C_STACK, 0);
|
||||
}
|
||||
|
||||
return rsp;
|
||||
}
|
||||
|
||||
/* 64 bit interrupt */
|
||||
|
|
|
@ -22,42 +22,6 @@
|
|||
#include "exec/exec-all.h"
|
||||
#include "tcg/helper-tcg.h"
|
||||
|
||||
int get_pg_mode(CPUX86State *env)
|
||||
{
|
||||
int pg_mode = 0;
|
||||
if (!(env->cr[0] & CR0_PG_MASK)) {
|
||||
return 0;
|
||||
}
|
||||
if (env->cr[0] & CR0_WP_MASK) {
|
||||
pg_mode |= PG_MODE_WP;
|
||||
}
|
||||
if (env->cr[4] & CR4_PAE_MASK) {
|
||||
pg_mode |= PG_MODE_PAE;
|
||||
if (env->efer & MSR_EFER_NXE) {
|
||||
pg_mode |= PG_MODE_NXE;
|
||||
}
|
||||
}
|
||||
if (env->cr[4] & CR4_PSE_MASK) {
|
||||
pg_mode |= PG_MODE_PSE;
|
||||
}
|
||||
if (env->cr[4] & CR4_SMEP_MASK) {
|
||||
pg_mode |= PG_MODE_SMEP;
|
||||
}
|
||||
if (env->hflags & HF_LMA_MASK) {
|
||||
pg_mode |= PG_MODE_LMA;
|
||||
if (env->cr[4] & CR4_PKE_MASK) {
|
||||
pg_mode |= PG_MODE_PKE;
|
||||
}
|
||||
if (env->cr[4] & CR4_PKS_MASK) {
|
||||
pg_mode |= PG_MODE_PKS;
|
||||
}
|
||||
if (env->cr[4] & CR4_LA57_MASK) {
|
||||
pg_mode |= PG_MODE_LA57;
|
||||
}
|
||||
}
|
||||
return pg_mode;
|
||||
}
|
||||
|
||||
#define PG_ERROR_OK (-1)
|
||||
|
||||
typedef hwaddr (*MMUTranslateFunc)(CPUState *cs, hwaddr gphys, MMUAccessType access_type,
|
||||
|
|
Loading…
Reference in New Issue