diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2021-07-06 17:53:29 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2021-07-09 18:21:34 +0200 |
commit | 533883fd7ec18a99b28815583bce6f78b2c9643b (patch) | |
tree | 3031faf5dbf97c914e1b05f7c1d40b3cb5d792fd /target/i386 | |
parent | acf23ffb58322179841cb68ff0fd595fede59618 (diff) |
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>
Diffstat (limited to 'target/i386')
-rw-r--r-- | target/i386/cpu.h | 2 | ||||
-rw-r--r-- | target/i386/helper.h | 3 | ||||
-rw-r--r-- | target/i386/svm.h | 2 | ||||
-rw-r--r-- | target/i386/tcg/bpt_helper.c | 21 | ||||
-rw-r--r-- | target/i386/tcg/sysemu/bpt_helper.c | 47 | ||||
-rw-r--r-- | target/i386/tcg/sysemu/svm_helper.c | 4 | ||||
-rw-r--r-- | target/i386/tcg/translate.c | 1 |
7 files changed, 35 insertions, 45 deletions
diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 0f7ddbfeae..8f3747dd28 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -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 diff --git a/target/i386/helper.h b/target/i386/helper.h index f3d8c3f949..574ff75615 100644 --- a/target/i386/helper.h +++ b/target/i386/helper.h @@ -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) diff --git a/target/i386/svm.h b/target/i386/svm.h index 4bde9f3475..adc058dc76 100644 --- a/target/i386/svm.h +++ b/target/i386/svm.h @@ -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; diff --git a/target/i386/tcg/bpt_helper.c b/target/i386/tcg/bpt_helper.c index 83cd89581e..b6c1fff16e 100644 --- a/target/i386/tcg/bpt_helper.c +++ b/target/i386/tcg/bpt_helper.c @@ -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()); -} diff --git a/target/i386/tcg/sysemu/bpt_helper.c b/target/i386/tcg/sysemu/bpt_helper.c index 9bdf7e170b..805118c6b5 100644 --- a/target/i386/tcg/sysemu/bpt_helper.c +++ b/target/i386/tcg/sysemu/bpt_helper.c @@ -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. */ diff --git a/target/i386/tcg/sysemu/svm_helper.c b/target/i386/tcg/sysemu/svm_helper.c index 047f31628e..00618cff23 100644 --- a/target/i386/tcg/sysemu/svm_helper.c +++ b/target/i386/tcg/sysemu/svm_helper.c @@ -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 diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index b21873ed23..9e445b9bf0 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -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) |