qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PULL 41/48] target/i386: fix exceptions for MOV to DR


From: Paolo Bonzini
Subject: [PULL 41/48] target/i386: fix exceptions for MOV to DR
Date: Thu, 8 Jul 2021 17:17:41 +0200

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>
---
 target/i386/cpu.h                   |  2 ++
 target/i386/helper.h                |  3 +-
 target/i386/svm.h                   |  2 --
 target/i386/tcg/bpt_helper.c        | 21 -------------
 target/i386/tcg/sysemu/bpt_helper.c | 47 ++++++++++++++++++-----------
 target/i386/tcg/sysemu/svm_helper.c |  4 +--
 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)
-- 
2.31.1





reply via email to

[Prev in Thread] Current Thread [Next in Thread]