]> Git Repo - qemu.git/blobdiff - target-i386/helper.c
target-i386: Move user-mode exception actions out of user-exec.c
[qemu.git] / target-i386 / helper.c
index 575583942a1643714a9e72546f4369a50f721806..1c250b82452d9fd4c8a2c2e3019dbe9aeaebaf5b 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "qemu/osdep.h"
 #include "cpu.h"
+#include "exec/exec-all.h"
 #include "sysemu/kvm.h"
 #include "kvm_i386.h"
 #ifndef CONFIG_USER_ONLY
@@ -700,6 +701,8 @@ int x86_cpu_handle_mmu_fault(CPUState *cs, vaddr addr,
     env->error_code = (is_write << PG_ERROR_W_BIT);
     env->error_code |= PG_ERROR_U_MASK;
     cs->exception_index = EXCP0E_PAGE;
+    env->exception_is_int = 0;
+    env->exception_next_eip = -1;
     return 1;
 }
 
@@ -919,29 +922,31 @@ do_check_protect_pse36:
          !((env->cr[4] & CR4_SMEP_MASK) && (ptep & PG_USER_MASK)))) {
         prot |= PAGE_EXEC;
     }
-
-    if ((prot & (1 << is_write1)) == 0) {
-        goto do_fault_protect;
-    }
-
     if ((env->cr[4] & CR4_PKE_MASK) && (env->hflags & HF_LMA_MASK) &&
         (ptep & PG_USER_MASK) && env->pkru) {
         uint32_t pk = (pte & PG_PKRU_MASK) >> PG_PKRU_BIT;
         uint32_t pkru_ad = (env->pkru >> pk * 2) & 1;
         uint32_t pkru_wd = (env->pkru >> pk * 2) & 2;
+        uint32_t pkru_prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
 
         if (pkru_ad) {
-            prot &= ~(PAGE_READ | PAGE_WRITE);
+            pkru_prot &= ~(PAGE_READ | PAGE_WRITE);
         } else if (pkru_wd && (is_user || env->cr[0] & CR0_WP_MASK)) {
-            prot &= ~PAGE_WRITE;
+            pkru_prot &= ~PAGE_WRITE;
         }
-        if ((prot & (1 << is_write1)) == 0) {
+
+        prot &= pkru_prot;
+        if ((pkru_prot & (1 << is_write1)) == 0) {
             assert(is_write1 != 2);
             error_code |= PG_ERROR_PK_MASK;
             goto do_fault_protect;
         }
     }
 
+    if ((prot & (1 << is_write1)) == 0) {
+        goto do_fault_protect;
+    }
+
     /* yes, it can! */
     is_dirty = is_write && !(pte & PG_DIRTY_MASK);
     if (!(pte & PG_ACCESSED_MASK) || is_dirty) {
This page took 0.024202 seconds and 4 git commands to generate.