aboutsummaryrefslogtreecommitdiff
path: root/target/i386
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2021-07-06 17:53:29 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2021-07-09 18:21:34 +0200
commit533883fd7ec18a99b28815583bce6f78b2c9643b (patch)
tree3031faf5dbf97c914e1b05f7c1d40b3cb5d792fd /target/i386
parentacf23ffb58322179841cb68ff0fd595fede59618 (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.h2
-rw-r--r--target/i386/helper.h3
-rw-r--r--target/i386/svm.h2
-rw-r--r--target/i386/tcg/bpt_helper.c21
-rw-r--r--target/i386/tcg/sysemu/bpt_helper.c47
-rw-r--r--target/i386/tcg/sysemu/svm_helper.c4
-rw-r--r--target/i386/tcg/translate.c1
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)