]> xenbits.xensource.com Git - qemu-xen.git/commitdiff
target/i386: fix exceptions for MOV to DR
authorPaolo Bonzini <pbonzini@redhat.com>
Tue, 6 Jul 2021 15:53:29 +0000 (17:53 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 9 Jul 2021 16:21:34 +0000 (18:21 +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
target/i386/helper.h
target/i386/svm.h
target/i386/tcg/bpt_helper.c
target/i386/tcg/sysemu/bpt_helper.c
target/i386/tcg/sysemu/svm_helper.c
target/i386/tcg/translate.c

index 0f7ddbfeaeb9cb83b7b69c8bcb2c85e312b8c26a..8f3747dd28580269369fd2bfbbb17d8eb591558f 100644 (file)
@@ -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
index f3d8c3f949ad0ae372f5697d68ba78686fc0df19..574ff756156f71d83eec0aafc3101d3a33067e4a 100644 (file)
@@ -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)
index 4bde9f34750527b4b3f2b7457db7d4e78bc9a8f2..adc058dc76dca39ef59ba9baf87a1b9eed2affb8 100644 (file)
 #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;
index 83cd89581ed9dba8d4b134406fd312f398a7d82c..b6c1fff16e51420a8843ab26a8dad397d44bccef 100644 (file)
@@ -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());
-}
index 9bdf7e170b675c3a106bc764b8813959a4da8739..805118c6b5c31965ab8f9c29a37006a4a34912e8 100644 (file)
@@ -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.  */
index 047f31628e0ca3b17c750a49c1f523e9ad71babd..00618cff23d7a4aeb409ce72abf6dddc29b02b72 100644 (file)
@@ -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
index b21873ed232e2a7495efbc39628c71c790c31d5f..9e445b9bf069db7950892613ba94b77df258021a 100644 (file)
@@ -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)