target/i386: fix exceptions for MOV to DR
Use raise_exception_ra (without error code) when raising the illegal opcode operation; raise #GP when setting bits 63:32 of DR6 or DR7. Move helper_get_dr to sysemu/ since it is a privileged instruction that is not needed on user-mode emulators. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
acf23ffb58
commit
533883fd7e
@ -268,6 +268,8 @@ typedef enum X86Seg {
|
||||
#define DR7_TYPE_IO_RW 0x2
|
||||
#define DR7_TYPE_DATA_RW 0x3
|
||||
|
||||
#define DR_RESERVED_MASK 0xffffffff00000000ULL
|
||||
|
||||
#define PG_PRESENT_BIT 0
|
||||
#define PG_RW_BIT 1
|
||||
#define PG_USER_BIT 2
|
||||
|
@ -46,9 +46,8 @@ DEF_HELPER_1(clts, void, env)
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
DEF_HELPER_FLAGS_3(set_dr, TCG_CALL_NO_WG, void, env, int, tl)
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
DEF_HELPER_FLAGS_2(get_dr, TCG_CALL_NO_WG, tl, env, int)
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
DEF_HELPER_1(sysenter, void, env)
|
||||
DEF_HELPER_2(sysexit, void, env, int)
|
||||
|
@ -140,8 +140,6 @@
|
||||
#define SVM_MSRPM_SIZE (1ULL << 13)
|
||||
#define SVM_IOPM_SIZE ((1ULL << 13) + 1)
|
||||
|
||||
#define SVM_DR_RESERVED_MASK 0xffffffff00000000ULL
|
||||
|
||||
struct QEMU_PACKED vmcb_control_area {
|
||||
uint16_t intercept_cr_read;
|
||||
uint16_t intercept_cr_write;
|
||||
|
@ -37,24 +37,3 @@ void helper_rechecking_single_step(CPUX86State *env)
|
||||
helper_single_step(env);
|
||||
}
|
||||
}
|
||||
|
||||
target_ulong helper_get_dr(CPUX86State *env, int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0: case 1: case 2: case 3: case 6: case 7:
|
||||
return env->dr[reg];
|
||||
case 4:
|
||||
if (env->cr[4] & CR4_DE_MASK) {
|
||||
break;
|
||||
} else {
|
||||
return env->dr[6];
|
||||
}
|
||||
case 5:
|
||||
if (env->cr[4] & CR4_DE_MASK) {
|
||||
break;
|
||||
} else {
|
||||
return env->dr[7];
|
||||
}
|
||||
}
|
||||
raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
|
||||
}
|
||||
|
@ -234,10 +234,30 @@ void breakpoint_handler(CPUState *cs)
|
||||
}
|
||||
}
|
||||
|
||||
target_ulong helper_get_dr(CPUX86State *env, int reg)
|
||||
{
|
||||
if (reg >= 4 && reg < 6) {
|
||||
if (env->cr[4] & CR4_DE_MASK) {
|
||||
raise_exception_ra(env, EXCP06_ILLOP, GETPC());
|
||||
} else {
|
||||
reg += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return env->dr[reg];
|
||||
}
|
||||
|
||||
void helper_set_dr(CPUX86State *env, int reg, target_ulong t0)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0: case 1: case 2: case 3:
|
||||
if (reg >= 4 && reg < 6) {
|
||||
if (env->cr[4] & CR4_DE_MASK) {
|
||||
raise_exception_ra(env, EXCP06_ILLOP, GETPC());
|
||||
} else {
|
||||
reg += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (reg < 4) {
|
||||
if (hw_breakpoint_enabled(env->dr[7], reg)
|
||||
&& hw_breakpoint_type(env->dr[7], reg) != DR7_TYPE_IO_RW) {
|
||||
hw_breakpoint_remove(env, reg);
|
||||
@ -246,25 +266,16 @@ void helper_set_dr(CPUX86State *env, int reg, target_ulong t0)
|
||||
} else {
|
||||
env->dr[reg] = t0;
|
||||
}
|
||||
return;
|
||||
case 4:
|
||||
if (env->cr[4] & CR4_DE_MASK) {
|
||||
break;
|
||||
} else {
|
||||
if (t0 & DR_RESERVED_MASK) {
|
||||
raise_exception_err_ra(env, EXCP0D_GPF, 0, GETPC());
|
||||
}
|
||||
/* fallthru */
|
||||
case 6:
|
||||
env->dr[6] = t0 | DR6_FIXED_1;
|
||||
return;
|
||||
case 5:
|
||||
if (env->cr[4] & CR4_DE_MASK) {
|
||||
break;
|
||||
if (reg == 6) {
|
||||
env->dr[6] = t0 | DR6_FIXED_1;
|
||||
} else {
|
||||
cpu_x86_update_dr7(env, t0);
|
||||
}
|
||||
/* fallthru */
|
||||
case 7:
|
||||
cpu_x86_update_dr7(env, t0);
|
||||
return;
|
||||
}
|
||||
raise_exception_err_ra(env, EXCP06_ILLOP, 0, GETPC());
|
||||
}
|
||||
|
||||
/* Check if Port I/O is trapped by a breakpoint. */
|
||||
|
@ -270,10 +270,10 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend)
|
||||
env->vm_vmcb + offsetof(struct vmcb, save.dr6));
|
||||
|
||||
#ifdef TARGET_X86_64
|
||||
if (env->dr[6] & SVM_DR_RESERVED_MASK) {
|
||||
if (env->dr[6] & DR_RESERVED_MASK) {
|
||||
cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
|
||||
}
|
||||
if (env->dr[7] & SVM_DR_RESERVED_MASK) {
|
||||
if (env->dr[7] & DR_RESERVED_MASK) {
|
||||
cpu_vmexit(env, SVM_EXIT_ERR, 0, GETPC());
|
||||
}
|
||||
#endif
|
||||
|
@ -206,6 +206,7 @@ STUB_HELPER(outw, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
|
||||
STUB_HELPER(outl, TCGv_env env, TCGv_i32 port, TCGv_i32 val)
|
||||
STUB_HELPER(rdmsr, TCGv_env env)
|
||||
STUB_HELPER(read_crN, TCGv ret, TCGv_env env, TCGv_i32 reg)
|
||||
STUB_HELPER(get_dr, TCGv ret, TCGv_env env, TCGv_i32 reg)
|
||||
STUB_HELPER(set_dr, TCGv_env env, TCGv_i32 reg, TCGv val)
|
||||
STUB_HELPER(stgi, TCGv_env env)
|
||||
STUB_HELPER(svm_check_intercept, TCGv_env env, TCGv_i32 type)
|
||||
|
Loading…
Reference in New Issue
Block a user