]> git.proxmox.com Git - qemu.git/blobdiff - target-i386/op_helper.c
x86: use qemu_log_mask on triple faults (Chris Wright)
[qemu.git] / target-i386 / op_helper.c
index bb24353360f484af886930b9ee0318fcf60e3919..25e079b8fdf193b167f9d90542e01d146b38314b 100644 (file)
 
 
 #ifdef DEBUG_PCALL
-#  define LOG_PCALL(...) do {            \
-     if (loglevel & CPU_LOG_PCALL)       \
-       fprintf(logfile, ## __VA_ARGS__); \
-   } while (0)
-#  define LOG_PCALL_STATE(env) do {                             \
-    if (loglevel & CPU_LOG_PCALL)                               \
-        cpu_dump_state((env), logfile, fprintf, X86_DUMP_CCOP); \
-   } while (0)
+#  define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__)
+#  define LOG_PCALL_STATE(env) \
+          log_cpu_state_mask(CPU_LOG_PCALL, (env), X86_DUMP_CCOP)
 #else
 #  define LOG_PCALL(...) do { } while (0)
 #  define LOG_PCALL_STATE(env) do { } while (0)
@@ -43,8 +38,7 @@
 #if 0
 #define raise_exception_err(a, b)\
 do {\
-    if (logfile)\
-        fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
+    qemu_log("raise_exception line=%d\n", __LINE__);\
     (raise_exception_err)(a, b);\
 } while (0)
 #endif
@@ -1212,32 +1206,32 @@ void do_interrupt_user(int intno, int is_int, int error_code,
 void do_interrupt(int intno, int is_int, int error_code,
                   target_ulong next_eip, int is_hw)
 {
-    if (loglevel & CPU_LOG_INT) {
+    if (qemu_loglevel_mask(CPU_LOG_INT)) {
         if ((env->cr[0] & CR0_PE_MASK)) {
             static int count;
-            fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
+            qemu_log("%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
                     count, intno, error_code, is_int,
                     env->hflags & HF_CPL_MASK,
                     env->segs[R_CS].selector, EIP,
                     (int)env->segs[R_CS].base + EIP,
                     env->segs[R_SS].selector, ESP);
             if (intno == 0x0e) {
-                fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);
+                qemu_log(" CR2=" TARGET_FMT_lx, env->cr[2]);
             } else {
-                fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);
+                qemu_log(" EAX=" TARGET_FMT_lx, EAX);
             }
-            fprintf(logfile, "\n");
-            cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
+            qemu_log("\n");
+            log_cpu_state(env, X86_DUMP_CCOP);
 #if 0
             {
                 int i;
                 uint8_t *ptr;
-                fprintf(logfile, "       code=");
+                qemu_log("       code=");
                 ptr = env->segs[R_CS].base + env->eip;
                 for(i = 0; i < 16; i++) {
-                    fprintf(logfile, " %02x", ldub(ptr + i));
+                    qemu_log(" %02x", ldub(ptr + i));
                 }
-                fprintf(logfile, "\n");
+                qemu_log("\n");
             }
 #endif
             count++;
@@ -1257,6 +1251,9 @@ void do_interrupt(int intno, int is_int, int error_code,
     }
 }
 
+/* This should come from sysemu.h - if we could include it here... */
+void qemu_system_reset_request(void);
+
 /*
  * Check nested exceptions and change to double or triple fault if
  * needed. It should only be called, if this is not an interrupt.
@@ -1270,12 +1267,20 @@ static int check_exception(int intno, int *error_code)
     int second_contributory = intno == 0 ||
                                (intno >= 10 && intno <= 13);
 
-    if (loglevel & CPU_LOG_INT)
-        fprintf(logfile, "check_exception old: 0x%x new 0x%x\n",
+    qemu_log_mask(CPU_LOG_INT, "check_exception old: 0x%x new 0x%x\n",
                 env->old_exception, intno);
 
-    if (env->old_exception == EXCP08_DBLE)
-        cpu_abort(env, "triple fault");
+#if !defined(CONFIG_USER_ONLY)
+    if (env->old_exception == EXCP08_DBLE) {
+        if (env->hflags & HF_SVMI_MASK)
+            helper_vmexit(SVM_EXIT_SHUTDOWN, 0); /* does not return */
+
+        qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
+
+        qemu_system_reset_request();
+        return EXCP_HLT;
+    }
+#endif
 
     if ((first_contributory && second_contributory)
         || (env->old_exception == EXCP0E_PAGE &&
@@ -1297,8 +1302,8 @@ static int check_exception(int intno, int *error_code)
  * EIP value AFTER the interrupt instruction. It is only relevant if
  * is_int is TRUE.
  */
-static void noreturn raise_interrupt(int intno, int is_int, int error_code,
-                                     int next_eip_addend)
+static void QEMU_NORETURN raise_interrupt(int intno, int is_int, int error_code,
+                                          int next_eip_addend)
 {
     if (!is_int) {
         helper_svm_check_intercept_param(SVM_EXIT_EXCP_BASE + intno, error_code);
@@ -1352,10 +1357,8 @@ void do_smm_enter(void)
     SegmentCache *dt;
     int i, offset;
 
-    if (loglevel & CPU_LOG_INT) {
-        fprintf(logfile, "SMM: enter\n");
-        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
-    }
+    qemu_log_mask(CPU_LOG_INT, "SMM: enter\n");
+    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
 
     env->hflags |= HF_SMM_MASK;
     cpu_smm_update(env);
@@ -1595,10 +1598,8 @@ void helper_rsm(void)
     env->hflags &= ~HF_SMM_MASK;
     cpu_smm_update(env);
 
-    if (loglevel & CPU_LOG_INT) {
-        fprintf(logfile, "SMM: after RSM\n");
-        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
-    }
+    qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n");
+    log_cpu_state_mask(CPU_LOG_INT, env, X86_DUMP_CCOP);
 }
 
 #endif /* !CONFIG_USER_ONLY */
@@ -1911,7 +1912,7 @@ void helper_cpuid(void)
 
     helper_svm_check_intercept_param(SVM_EXIT_CPUID, 0);
 
-    cpu_x86_cpuid(env, (uint32_t)EAX, &eax, &ebx, &ecx, &edx);
+    cpu_x86_cpuid(env, (uint32_t)EAX, (uint32_t)ECX, &eax, &ebx, &ecx, &edx);
     EAX = eax;
     EBX = ebx;
     ECX = ecx;
@@ -2156,7 +2157,7 @@ void helper_load_seg(int seg_reg, int selector)
                        get_seg_limit(e1, e2),
                        e2);
 #if 0
-        fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
+        qemu_log("load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
                 selector, (unsigned long)sc->base, sc->limit, sc->flags);
 #endif
     }
@@ -3028,6 +3029,8 @@ void helper_wrmsr(void)
                 update_mask |= MSR_EFER_NXE;
             if (env->cpuid_ext3_features & CPUID_EXT3_SVM)
                 update_mask |= MSR_EFER_SVME;
+            if (env->cpuid_ext2_features & CPUID_EXT2_FFXSR)
+                update_mask |= MSR_EFER_FFXSR;
             cpu_load_efer(env, (env->efer & ~update_mask) |
                           (val & update_mask));
         }
@@ -3061,6 +3064,46 @@ void helper_wrmsr(void)
         env->kernelgsbase = val;
         break;
 #endif
+    case MSR_MTRRphysBase(0):
+    case MSR_MTRRphysBase(1):
+    case MSR_MTRRphysBase(2):
+    case MSR_MTRRphysBase(3):
+    case MSR_MTRRphysBase(4):
+    case MSR_MTRRphysBase(5):
+    case MSR_MTRRphysBase(6):
+    case MSR_MTRRphysBase(7):
+        env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base = val;
+        break;
+    case MSR_MTRRphysMask(0):
+    case MSR_MTRRphysMask(1):
+    case MSR_MTRRphysMask(2):
+    case MSR_MTRRphysMask(3):
+    case MSR_MTRRphysMask(4):
+    case MSR_MTRRphysMask(5):
+    case MSR_MTRRphysMask(6):
+    case MSR_MTRRphysMask(7):
+        env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask = val;
+        break;
+    case MSR_MTRRfix64K_00000:
+        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix64K_00000] = val;
+        break;
+    case MSR_MTRRfix16K_80000:
+    case MSR_MTRRfix16K_A0000:
+        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1] = val;
+        break;
+    case MSR_MTRRfix4K_C0000:
+    case MSR_MTRRfix4K_C8000:
+    case MSR_MTRRfix4K_D0000:
+    case MSR_MTRRfix4K_D8000:
+    case MSR_MTRRfix4K_E0000:
+    case MSR_MTRRfix4K_E8000:
+    case MSR_MTRRfix4K_F0000:
+    case MSR_MTRRfix4K_F8000:
+        env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3] = val;
+        break;
+    case MSR_MTRRdefType:
+        env->mtrr_deftype = val;
+        break;
     default:
         /* XXX: exception ? */
         break;
@@ -3133,6 +3176,53 @@ void helper_rdmsr(void)
         }
         break;
 #endif
+    case MSR_MTRRphysBase(0):
+    case MSR_MTRRphysBase(1):
+    case MSR_MTRRphysBase(2):
+    case MSR_MTRRphysBase(3):
+    case MSR_MTRRphysBase(4):
+    case MSR_MTRRphysBase(5):
+    case MSR_MTRRphysBase(6):
+    case MSR_MTRRphysBase(7):
+        val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysBase(0)) / 2].base;
+        break;
+    case MSR_MTRRphysMask(0):
+    case MSR_MTRRphysMask(1):
+    case MSR_MTRRphysMask(2):
+    case MSR_MTRRphysMask(3):
+    case MSR_MTRRphysMask(4):
+    case MSR_MTRRphysMask(5):
+    case MSR_MTRRphysMask(6):
+    case MSR_MTRRphysMask(7):
+        val = env->mtrr_var[((uint32_t)ECX - MSR_MTRRphysMask(0)) / 2].mask;
+        break;
+    case MSR_MTRRfix64K_00000:
+        val = env->mtrr_fixed[0];
+        break;
+    case MSR_MTRRfix16K_80000:
+    case MSR_MTRRfix16K_A0000:
+        val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix16K_80000 + 1];
+        break;
+    case MSR_MTRRfix4K_C0000:
+    case MSR_MTRRfix4K_C8000:
+    case MSR_MTRRfix4K_D0000:
+    case MSR_MTRRfix4K_D8000:
+    case MSR_MTRRfix4K_E0000:
+    case MSR_MTRRfix4K_E8000:
+    case MSR_MTRRfix4K_F0000:
+    case MSR_MTRRfix4K_F8000:
+        val = env->mtrr_fixed[(uint32_t)ECX - MSR_MTRRfix4K_C0000 + 3];
+        break;
+    case MSR_MTRRdefType:
+        val = env->mtrr_deftype;
+        break;
+    case MSR_MTRRcap:
+        if (env->cpuid_features & CPUID_MTRR)
+            val = MSR_MTRRcap_VCNT | MSR_MTRRcap_FIXRANGE_SUPPORT | MSR_MTRRcap_WC_SUPPORTED;
+        else
+            /* XXX: exception ? */
+            val = 0;
+        break;
     default:
         /* XXX: exception ? */
         val = 0;
@@ -4263,10 +4353,15 @@ void helper_fxsave(target_ulong ptr, int data64)
         else
             nb_xmm_regs = 8;
         addr = ptr + 0xa0;
-        for(i = 0; i < nb_xmm_regs; i++) {
-            stq(addr, env->xmm_regs[i].XMM_Q(0));
-            stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
-            addr += 16;
+        /* Fast FXSAVE leaves out the XMM registers */
+        if (!(env->efer & MSR_EFER_FFXSR)
+          || (env->hflags & HF_CPL_MASK)
+          || !(env->hflags & HF_LMA_MASK)) {
+            for(i = 0; i < nb_xmm_regs; i++) {
+                stq(addr, env->xmm_regs[i].XMM_Q(0));
+                stq(addr + 8, env->xmm_regs[i].XMM_Q(1));
+                addr += 16;
+            }
         }
     }
 }
@@ -4303,10 +4398,15 @@ void helper_fxrstor(target_ulong ptr, int data64)
         else
             nb_xmm_regs = 8;
         addr = ptr + 0xa0;
-        for(i = 0; i < nb_xmm_regs; i++) {
-            env->xmm_regs[i].XMM_Q(0) = ldq(addr);
-            env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
-            addr += 16;
+        /* Fast FXRESTORE leaves out the XMM registers */
+        if (!(env->efer & MSR_EFER_FFXSR)
+          || (env->hflags & HF_CPL_MASK)
+          || !(env->hflags & HF_LMA_MASK)) {
+            for(i = 0; i < nb_xmm_regs; i++) {
+                env->xmm_regs[i].XMM_Q(0) = ldq(addr);
+                env->xmm_regs[i].XMM_Q(1) = ldq(addr + 8);
+                addr += 16;
+            }
         }
     }
 }
@@ -4774,8 +4874,7 @@ void helper_vmrun(int aflag, int next_eip_addend)
     else
         addr = (uint32_t)EAX;
 
-    if (loglevel & CPU_LOG_TB_IN_ASM)
-        fprintf(logfile,"vmrun! " TARGET_FMT_lx "\n", addr);
+    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmrun! " TARGET_FMT_lx "\n", addr);
 
     env->vm_vmcb = addr;
 
@@ -4895,8 +4994,7 @@ void helper_vmrun(int aflag, int next_eip_addend)
         uint32_t event_inj_err = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj_err));
         stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.event_inj), event_inj & ~SVM_EVTINJ_VALID);
 
-        if (loglevel & CPU_LOG_TB_IN_ASM)
-            fprintf(logfile, "Injecting(%#hx): ", valid_err);
+        qemu_log_mask(CPU_LOG_TB_IN_ASM, "Injecting(%#hx): ", valid_err);
         /* FIXME: need to implement valid_err */
         switch (event_inj & SVM_EVTINJ_TYPE_MASK) {
         case SVM_EVTINJ_TYPE_INTR:
@@ -4904,8 +5002,7 @@ void helper_vmrun(int aflag, int next_eip_addend)
                 env->error_code = event_inj_err;
                 env->exception_is_int = 0;
                 env->exception_next_eip = -1;
-                if (loglevel & CPU_LOG_TB_IN_ASM)
-                    fprintf(logfile, "INTR");
+                qemu_log_mask(CPU_LOG_TB_IN_ASM, "INTR");
                 /* XXX: is it always correct ? */
                 do_interrupt(vector, 0, 0, 0, 1);
                 break;
@@ -4914,8 +5011,7 @@ void helper_vmrun(int aflag, int next_eip_addend)
                 env->error_code = event_inj_err;
                 env->exception_is_int = 0;
                 env->exception_next_eip = EIP;
-                if (loglevel & CPU_LOG_TB_IN_ASM)
-                    fprintf(logfile, "NMI");
+                qemu_log_mask(CPU_LOG_TB_IN_ASM, "NMI");
                 cpu_loop_exit();
                 break;
         case SVM_EVTINJ_TYPE_EXEPT:
@@ -4923,8 +5019,7 @@ void helper_vmrun(int aflag, int next_eip_addend)
                 env->error_code = event_inj_err;
                 env->exception_is_int = 0;
                 env->exception_next_eip = -1;
-                if (loglevel & CPU_LOG_TB_IN_ASM)
-                    fprintf(logfile, "EXEPT");
+                qemu_log_mask(CPU_LOG_TB_IN_ASM, "EXEPT");
                 cpu_loop_exit();
                 break;
         case SVM_EVTINJ_TYPE_SOFT:
@@ -4932,13 +5027,11 @@ void helper_vmrun(int aflag, int next_eip_addend)
                 env->error_code = event_inj_err;
                 env->exception_is_int = 1;
                 env->exception_next_eip = EIP;
-                if (loglevel & CPU_LOG_TB_IN_ASM)
-                    fprintf(logfile, "SOFT");
+                qemu_log_mask(CPU_LOG_TB_IN_ASM, "SOFT");
                 cpu_loop_exit();
                 break;
         }
-        if (loglevel & CPU_LOG_TB_IN_ASM)
-            fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code);
+        qemu_log_mask(CPU_LOG_TB_IN_ASM, " %#x %#x\n", env->exception_index, env->error_code);
     }
 }
 
@@ -4958,8 +5051,7 @@ void helper_vmload(int aflag)
     else
         addr = (uint32_t)EAX;
 
-    if (loglevel & CPU_LOG_TB_IN_ASM)
-        fprintf(logfile,"vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
+    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmload! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
                 addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
                 env->segs[R_FS].base);
 
@@ -4994,8 +5086,7 @@ void helper_vmsave(int aflag)
     else
         addr = (uint32_t)EAX;
 
-    if (loglevel & CPU_LOG_TB_IN_ASM)
-        fprintf(logfile,"vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
+    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmsave! " TARGET_FMT_lx "\nFS: %016" PRIx64 " | " TARGET_FMT_lx "\n",
                 addr, ldq_phys(addr + offsetof(struct vmcb, save.fs.base)),
                 env->segs[R_FS].base);
 
@@ -5143,8 +5234,7 @@ void helper_vmexit(uint32_t exit_code, uint64_t exit_info_1)
 {
     uint32_t int_ctl;
 
-    if (loglevel & CPU_LOG_TB_IN_ASM)
-        fprintf(logfile,"vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
+    qemu_log_mask(CPU_LOG_TB_IN_ASM, "vmexit(%08x, %016" PRIx64 ", %016" PRIx64 ", " TARGET_FMT_lx ")!\n",
                 exit_code, exit_info_1,
                 ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
                 EIP);