10c36af8cSClaudio Fontana /* 20c36af8cSClaudio Fontana * i386 CPU dump to FILE 30c36af8cSClaudio Fontana * 40c36af8cSClaudio Fontana * Copyright (c) 2003 Fabrice Bellard 50c36af8cSClaudio Fontana * 60c36af8cSClaudio Fontana * This library is free software; you can redistribute it and/or 70c36af8cSClaudio Fontana * modify it under the terms of the GNU Lesser General Public 80c36af8cSClaudio Fontana * License as published by the Free Software Foundation; either 90c36af8cSClaudio Fontana * version 2 of the License, or (at your option) any later version. 100c36af8cSClaudio Fontana * 110c36af8cSClaudio Fontana * This library is distributed in the hope that it will be useful, 120c36af8cSClaudio Fontana * but WITHOUT ANY WARRANTY; without even the implied warranty of 130c36af8cSClaudio Fontana * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 140c36af8cSClaudio Fontana * Lesser General Public License for more details. 150c36af8cSClaudio Fontana * 160c36af8cSClaudio Fontana * You should have received a copy of the GNU Lesser General Public 170c36af8cSClaudio Fontana * License along with this library; if not, see <http://www.gnu.org/licenses/>. 180c36af8cSClaudio Fontana */ 190c36af8cSClaudio Fontana 200c36af8cSClaudio Fontana #include "qemu/osdep.h" 210c36af8cSClaudio Fontana #include "cpu.h" 220c36af8cSClaudio Fontana #include "qemu/qemu-print.h" 230c36af8cSClaudio Fontana #ifndef CONFIG_USER_ONLY 240c36af8cSClaudio Fontana #include "hw/i386/apic_internal.h" 250c36af8cSClaudio Fontana #endif 260c36af8cSClaudio Fontana 270c36af8cSClaudio Fontana /***********************************************************/ 280c36af8cSClaudio Fontana /* x86 debug */ 290c36af8cSClaudio Fontana 300c36af8cSClaudio Fontana static const char *cc_op_str[CC_OP_NB] = { 31*e36b976dSPaolo Bonzini [CC_OP_DYNAMIC] = "DYNAMIC", 320c36af8cSClaudio Fontana 33*e36b976dSPaolo Bonzini [CC_OP_EFLAGS] = "EFLAGS", 34*e36b976dSPaolo Bonzini [CC_OP_ADCX] = "ADCX", 35*e36b976dSPaolo Bonzini [CC_OP_ADOX] = "ADOX", 36*e36b976dSPaolo Bonzini [CC_OP_ADCOX] = "ADCOX", 370c36af8cSClaudio Fontana 38*e36b976dSPaolo Bonzini [CC_OP_MULB] = "MULB", 39*e36b976dSPaolo Bonzini [CC_OP_MULW] = "MULW", 40*e36b976dSPaolo Bonzini [CC_OP_MULL] = "MULL", 41*e36b976dSPaolo Bonzini [CC_OP_MULQ] = "MULQ", 420c36af8cSClaudio Fontana 43*e36b976dSPaolo Bonzini [CC_OP_ADDB] = "ADDB", 44*e36b976dSPaolo Bonzini [CC_OP_ADDW] = "ADDW", 45*e36b976dSPaolo Bonzini [CC_OP_ADDL] = "ADDL", 46*e36b976dSPaolo Bonzini [CC_OP_ADDQ] = "ADDQ", 470c36af8cSClaudio Fontana 48*e36b976dSPaolo Bonzini [CC_OP_ADCB] = "ADCB", 49*e36b976dSPaolo Bonzini [CC_OP_ADCW] = "ADCW", 50*e36b976dSPaolo Bonzini [CC_OP_ADCL] = "ADCL", 51*e36b976dSPaolo Bonzini [CC_OP_ADCQ] = "ADCQ", 520c36af8cSClaudio Fontana 53*e36b976dSPaolo Bonzini [CC_OP_SUBB] = "SUBB", 54*e36b976dSPaolo Bonzini [CC_OP_SUBW] = "SUBW", 55*e36b976dSPaolo Bonzini [CC_OP_SUBL] = "SUBL", 56*e36b976dSPaolo Bonzini [CC_OP_SUBQ] = "SUBQ", 570c36af8cSClaudio Fontana 58*e36b976dSPaolo Bonzini [CC_OP_SBBB] = "SBBB", 59*e36b976dSPaolo Bonzini [CC_OP_SBBW] = "SBBW", 60*e36b976dSPaolo Bonzini [CC_OP_SBBL] = "SBBL", 61*e36b976dSPaolo Bonzini [CC_OP_SBBQ] = "SBBQ", 620c36af8cSClaudio Fontana 63*e36b976dSPaolo Bonzini [CC_OP_LOGICB] = "LOGICB", 64*e36b976dSPaolo Bonzini [CC_OP_LOGICW] = "LOGICW", 65*e36b976dSPaolo Bonzini [CC_OP_LOGICL] = "LOGICL", 66*e36b976dSPaolo Bonzini [CC_OP_LOGICQ] = "LOGICQ", 670c36af8cSClaudio Fontana 68*e36b976dSPaolo Bonzini [CC_OP_INCB] = "INCB", 69*e36b976dSPaolo Bonzini [CC_OP_INCW] = "INCW", 70*e36b976dSPaolo Bonzini [CC_OP_INCL] = "INCL", 71*e36b976dSPaolo Bonzini [CC_OP_INCQ] = "INCQ", 720c36af8cSClaudio Fontana 73*e36b976dSPaolo Bonzini [CC_OP_DECB] = "DECB", 74*e36b976dSPaolo Bonzini [CC_OP_DECW] = "DECW", 75*e36b976dSPaolo Bonzini [CC_OP_DECL] = "DECL", 76*e36b976dSPaolo Bonzini [CC_OP_DECQ] = "DECQ", 770c36af8cSClaudio Fontana 78*e36b976dSPaolo Bonzini [CC_OP_SHLB] = "SHLB", 79*e36b976dSPaolo Bonzini [CC_OP_SHLW] = "SHLW", 80*e36b976dSPaolo Bonzini [CC_OP_SHLL] = "SHLL", 81*e36b976dSPaolo Bonzini [CC_OP_SHLQ] = "SHLQ", 820c36af8cSClaudio Fontana 83*e36b976dSPaolo Bonzini [CC_OP_SARB] = "SARB", 84*e36b976dSPaolo Bonzini [CC_OP_SARW] = "SARW", 85*e36b976dSPaolo Bonzini [CC_OP_SARL] = "SARL", 86*e36b976dSPaolo Bonzini [CC_OP_SARQ] = "SARQ", 870c36af8cSClaudio Fontana 88*e36b976dSPaolo Bonzini [CC_OP_BMILGB] = "BMILGB", 89*e36b976dSPaolo Bonzini [CC_OP_BMILGW] = "BMILGW", 90*e36b976dSPaolo Bonzini [CC_OP_BMILGL] = "BMILGL", 91*e36b976dSPaolo Bonzini [CC_OP_BMILGQ] = "BMILGQ", 920c36af8cSClaudio Fontana 93*e36b976dSPaolo Bonzini [CC_OP_POPCNT] = "POPCNT", 94*e36b976dSPaolo Bonzini [CC_OP_CLR] = "CLR", 950c36af8cSClaudio Fontana }; 960c36af8cSClaudio Fontana 970c36af8cSClaudio Fontana static void 980c36af8cSClaudio Fontana cpu_x86_dump_seg_cache(CPUX86State *env, FILE *f, 990c36af8cSClaudio Fontana const char *name, struct SegmentCache *sc) 1000c36af8cSClaudio Fontana { 1010c36af8cSClaudio Fontana #ifdef TARGET_X86_64 1020c36af8cSClaudio Fontana if (env->hflags & HF_CS64_MASK) { 1030c36af8cSClaudio Fontana qemu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name, 1040c36af8cSClaudio Fontana sc->selector, sc->base, sc->limit, 1050c36af8cSClaudio Fontana sc->flags & 0x00ffff00); 1060c36af8cSClaudio Fontana } else 1070c36af8cSClaudio Fontana #endif 1080c36af8cSClaudio Fontana { 1090c36af8cSClaudio Fontana qemu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector, 1100c36af8cSClaudio Fontana (uint32_t)sc->base, sc->limit, 1110c36af8cSClaudio Fontana sc->flags & 0x00ffff00); 1120c36af8cSClaudio Fontana } 1130c36af8cSClaudio Fontana 1140c36af8cSClaudio Fontana if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK)) 1150c36af8cSClaudio Fontana goto done; 1160c36af8cSClaudio Fontana 1170c36af8cSClaudio Fontana qemu_fprintf(f, " DPL=%d ", 1180c36af8cSClaudio Fontana (sc->flags & DESC_DPL_MASK) >> DESC_DPL_SHIFT); 1190c36af8cSClaudio Fontana if (sc->flags & DESC_S_MASK) { 1200c36af8cSClaudio Fontana if (sc->flags & DESC_CS_MASK) { 1210c36af8cSClaudio Fontana qemu_fprintf(f, (sc->flags & DESC_L_MASK) ? "CS64" : 1220c36af8cSClaudio Fontana ((sc->flags & DESC_B_MASK) ? "CS32" : "CS16")); 1230c36af8cSClaudio Fontana qemu_fprintf(f, " [%c%c", (sc->flags & DESC_C_MASK) ? 'C' : '-', 1240c36af8cSClaudio Fontana (sc->flags & DESC_R_MASK) ? 'R' : '-'); 1250c36af8cSClaudio Fontana } else { 1260c36af8cSClaudio Fontana qemu_fprintf(f, (sc->flags & DESC_B_MASK 1270c36af8cSClaudio Fontana || env->hflags & HF_LMA_MASK) 1280c36af8cSClaudio Fontana ? "DS " : "DS16"); 1290c36af8cSClaudio Fontana qemu_fprintf(f, " [%c%c", (sc->flags & DESC_E_MASK) ? 'E' : '-', 1300c36af8cSClaudio Fontana (sc->flags & DESC_W_MASK) ? 'W' : '-'); 1310c36af8cSClaudio Fontana } 1320c36af8cSClaudio Fontana qemu_fprintf(f, "%c]", (sc->flags & DESC_A_MASK) ? 'A' : '-'); 1330c36af8cSClaudio Fontana } else { 1340c36af8cSClaudio Fontana static const char *sys_type_name[2][16] = { 1350c36af8cSClaudio Fontana { /* 32 bit mode */ 1360c36af8cSClaudio Fontana "Reserved", "TSS16-avl", "LDT", "TSS16-busy", 1370c36af8cSClaudio Fontana "CallGate16", "TaskGate", "IntGate16", "TrapGate16", 1380c36af8cSClaudio Fontana "Reserved", "TSS32-avl", "Reserved", "TSS32-busy", 1390c36af8cSClaudio Fontana "CallGate32", "Reserved", "IntGate32", "TrapGate32" 1400c36af8cSClaudio Fontana }, 1410c36af8cSClaudio Fontana { /* 64 bit mode */ 1420c36af8cSClaudio Fontana "<hiword>", "Reserved", "LDT", "Reserved", "Reserved", 1430c36af8cSClaudio Fontana "Reserved", "Reserved", "Reserved", "Reserved", 1440c36af8cSClaudio Fontana "TSS64-avl", "Reserved", "TSS64-busy", "CallGate64", 1450c36af8cSClaudio Fontana "Reserved", "IntGate64", "TrapGate64" 1460c36af8cSClaudio Fontana } 1470c36af8cSClaudio Fontana }; 1480c36af8cSClaudio Fontana qemu_fprintf(f, "%s", 1490c36af8cSClaudio Fontana sys_type_name[(env->hflags & HF_LMA_MASK) ? 1 : 0] 1500c36af8cSClaudio Fontana [(sc->flags & DESC_TYPE_MASK) >> DESC_TYPE_SHIFT]); 1510c36af8cSClaudio Fontana } 1520c36af8cSClaudio Fontana done: 1530c36af8cSClaudio Fontana qemu_fprintf(f, "\n"); 1540c36af8cSClaudio Fontana } 1550c36af8cSClaudio Fontana 1560c36af8cSClaudio Fontana #ifndef CONFIG_USER_ONLY 1570c36af8cSClaudio Fontana 1580c36af8cSClaudio Fontana /* ARRAY_SIZE check is not required because 1590c36af8cSClaudio Fontana * DeliveryMode(dm) has a size of 3 bit. 1600c36af8cSClaudio Fontana */ 1610c36af8cSClaudio Fontana static inline const char *dm2str(uint32_t dm) 1620c36af8cSClaudio Fontana { 1630c36af8cSClaudio Fontana static const char *str[] = { 1640c36af8cSClaudio Fontana "Fixed", 1650c36af8cSClaudio Fontana "...", 1660c36af8cSClaudio Fontana "SMI", 1670c36af8cSClaudio Fontana "...", 1680c36af8cSClaudio Fontana "NMI", 1690c36af8cSClaudio Fontana "INIT", 1700c36af8cSClaudio Fontana "...", 1710c36af8cSClaudio Fontana "ExtINT" 1720c36af8cSClaudio Fontana }; 1730c36af8cSClaudio Fontana return str[dm]; 1740c36af8cSClaudio Fontana } 1750c36af8cSClaudio Fontana 1760c36af8cSClaudio Fontana static void dump_apic_lvt(const char *name, uint32_t lvt, bool is_timer) 1770c36af8cSClaudio Fontana { 1780c36af8cSClaudio Fontana uint32_t dm = (lvt & APIC_LVT_DELIV_MOD) >> APIC_LVT_DELIV_MOD_SHIFT; 1790c36af8cSClaudio Fontana qemu_printf("%s\t 0x%08x %s %-5s %-6s %-7s %-12s %-6s", 1800c36af8cSClaudio Fontana name, lvt, 1810c36af8cSClaudio Fontana lvt & APIC_LVT_INT_POLARITY ? "active-lo" : "active-hi", 1820c36af8cSClaudio Fontana lvt & APIC_LVT_LEVEL_TRIGGER ? "level" : "edge", 1830c36af8cSClaudio Fontana lvt & APIC_LVT_MASKED ? "masked" : "", 1840c36af8cSClaudio Fontana lvt & APIC_LVT_DELIV_STS ? "pending" : "", 1850c36af8cSClaudio Fontana !is_timer ? 1860c36af8cSClaudio Fontana "" : lvt & APIC_LVT_TIMER_PERIODIC ? 1870c36af8cSClaudio Fontana "periodic" : lvt & APIC_LVT_TIMER_TSCDEADLINE ? 1880c36af8cSClaudio Fontana "tsc-deadline" : "one-shot", 1890c36af8cSClaudio Fontana dm2str(dm)); 1900c36af8cSClaudio Fontana if (dm != APIC_DM_NMI) { 1910c36af8cSClaudio Fontana qemu_printf(" (vec %u)\n", lvt & APIC_VECTOR_MASK); 1920c36af8cSClaudio Fontana } else { 1930c36af8cSClaudio Fontana qemu_printf("\n"); 1940c36af8cSClaudio Fontana } 1950c36af8cSClaudio Fontana } 1960c36af8cSClaudio Fontana 1970c36af8cSClaudio Fontana /* ARRAY_SIZE check is not required because 1980c36af8cSClaudio Fontana * destination shorthand has a size of 2 bit. 1990c36af8cSClaudio Fontana */ 2000c36af8cSClaudio Fontana static inline const char *shorthand2str(uint32_t shorthand) 2010c36af8cSClaudio Fontana { 2020c36af8cSClaudio Fontana const char *str[] = { 2030c36af8cSClaudio Fontana "no-shorthand", "self", "all-self", "all" 2040c36af8cSClaudio Fontana }; 2050c36af8cSClaudio Fontana return str[shorthand]; 2060c36af8cSClaudio Fontana } 2070c36af8cSClaudio Fontana 2080c36af8cSClaudio Fontana static inline uint8_t divider_conf(uint32_t divide_conf) 2090c36af8cSClaudio Fontana { 2100c36af8cSClaudio Fontana uint8_t divide_val = ((divide_conf & 0x8) >> 1) | (divide_conf & 0x3); 2110c36af8cSClaudio Fontana 2120c36af8cSClaudio Fontana return divide_val == 7 ? 1 : 2 << divide_val; 2130c36af8cSClaudio Fontana } 2140c36af8cSClaudio Fontana 2150c36af8cSClaudio Fontana static inline void mask2str(char *str, uint32_t val, uint8_t size) 2160c36af8cSClaudio Fontana { 2170c36af8cSClaudio Fontana while (size--) { 2180c36af8cSClaudio Fontana *str++ = (val >> size) & 1 ? '1' : '0'; 2190c36af8cSClaudio Fontana } 2200c36af8cSClaudio Fontana *str = 0; 2210c36af8cSClaudio Fontana } 2220c36af8cSClaudio Fontana 2230c36af8cSClaudio Fontana #define MAX_LOGICAL_APIC_ID_MASK_SIZE 16 2240c36af8cSClaudio Fontana 2250c36af8cSClaudio Fontana static void dump_apic_icr(APICCommonState *s, CPUX86State *env) 2260c36af8cSClaudio Fontana { 2270c36af8cSClaudio Fontana uint32_t icr = s->icr[0], icr2 = s->icr[1]; 2280c36af8cSClaudio Fontana uint8_t dest_shorthand = \ 2290c36af8cSClaudio Fontana (icr & APIC_ICR_DEST_SHORT) >> APIC_ICR_DEST_SHORT_SHIFT; 2300c36af8cSClaudio Fontana bool logical_mod = icr & APIC_ICR_DEST_MOD; 2310c36af8cSClaudio Fontana char apic_id_str[MAX_LOGICAL_APIC_ID_MASK_SIZE + 1]; 2320c36af8cSClaudio Fontana uint32_t dest_field; 2330c36af8cSClaudio Fontana bool x2apic; 2340c36af8cSClaudio Fontana 2350c36af8cSClaudio Fontana qemu_printf("ICR\t 0x%08x %s %s %s %s\n", 2360c36af8cSClaudio Fontana icr, 2370c36af8cSClaudio Fontana logical_mod ? "logical" : "physical", 2380c36af8cSClaudio Fontana icr & APIC_ICR_TRIGGER_MOD ? "level" : "edge", 2390c36af8cSClaudio Fontana icr & APIC_ICR_LEVEL ? "assert" : "de-assert", 2400c36af8cSClaudio Fontana shorthand2str(dest_shorthand)); 2410c36af8cSClaudio Fontana 2420c36af8cSClaudio Fontana qemu_printf("ICR2\t 0x%08x", icr2); 2430c36af8cSClaudio Fontana if (dest_shorthand != 0) { 2440c36af8cSClaudio Fontana qemu_printf("\n"); 2450c36af8cSClaudio Fontana return; 2460c36af8cSClaudio Fontana } 2470c36af8cSClaudio Fontana x2apic = env->features[FEAT_1_ECX] & CPUID_EXT_X2APIC; 2480c36af8cSClaudio Fontana dest_field = x2apic ? icr2 : icr2 >> APIC_ICR_DEST_SHIFT; 2490c36af8cSClaudio Fontana 2500c36af8cSClaudio Fontana if (!logical_mod) { 2510c36af8cSClaudio Fontana if (x2apic) { 2520c36af8cSClaudio Fontana qemu_printf(" cpu %u (X2APIC ID)\n", dest_field); 2530c36af8cSClaudio Fontana } else { 2540c36af8cSClaudio Fontana qemu_printf(" cpu %u (APIC ID)\n", 2550c36af8cSClaudio Fontana dest_field & APIC_LOGDEST_XAPIC_ID); 2560c36af8cSClaudio Fontana } 2570c36af8cSClaudio Fontana return; 2580c36af8cSClaudio Fontana } 2590c36af8cSClaudio Fontana 2600c36af8cSClaudio Fontana if (s->dest_mode == 0xf) { /* flat mode */ 2610c36af8cSClaudio Fontana mask2str(apic_id_str, icr2 >> APIC_ICR_DEST_SHIFT, 8); 2620c36af8cSClaudio Fontana qemu_printf(" mask %s (APIC ID)\n", apic_id_str); 2630c36af8cSClaudio Fontana } else if (s->dest_mode == 0) { /* cluster mode */ 2640c36af8cSClaudio Fontana if (x2apic) { 2650c36af8cSClaudio Fontana mask2str(apic_id_str, dest_field & APIC_LOGDEST_X2APIC_ID, 16); 2660c36af8cSClaudio Fontana qemu_printf(" cluster %u mask %s (X2APIC ID)\n", 2670c36af8cSClaudio Fontana dest_field >> APIC_LOGDEST_X2APIC_SHIFT, apic_id_str); 2680c36af8cSClaudio Fontana } else { 2690c36af8cSClaudio Fontana mask2str(apic_id_str, dest_field & APIC_LOGDEST_XAPIC_ID, 4); 2700c36af8cSClaudio Fontana qemu_printf(" cluster %u mask %s (APIC ID)\n", 2710c36af8cSClaudio Fontana dest_field >> APIC_LOGDEST_XAPIC_SHIFT, apic_id_str); 2720c36af8cSClaudio Fontana } 2730c36af8cSClaudio Fontana } 2740c36af8cSClaudio Fontana } 2750c36af8cSClaudio Fontana 2760c36af8cSClaudio Fontana static void dump_apic_interrupt(const char *name, uint32_t *ireg_tab, 2770c36af8cSClaudio Fontana uint32_t *tmr_tab) 2780c36af8cSClaudio Fontana { 2790c36af8cSClaudio Fontana int i, empty = true; 2800c36af8cSClaudio Fontana 2810c36af8cSClaudio Fontana qemu_printf("%s\t ", name); 2820c36af8cSClaudio Fontana for (i = 0; i < 256; i++) { 2830c36af8cSClaudio Fontana if (apic_get_bit(ireg_tab, i)) { 2840c36af8cSClaudio Fontana qemu_printf("%u%s ", i, 2850c36af8cSClaudio Fontana apic_get_bit(tmr_tab, i) ? "(level)" : ""); 2860c36af8cSClaudio Fontana empty = false; 2870c36af8cSClaudio Fontana } 2880c36af8cSClaudio Fontana } 2890c36af8cSClaudio Fontana qemu_printf("%s\n", empty ? "(none)" : ""); 2900c36af8cSClaudio Fontana } 2910c36af8cSClaudio Fontana 2920c36af8cSClaudio Fontana void x86_cpu_dump_local_apic_state(CPUState *cs, int flags) 2930c36af8cSClaudio Fontana { 2940c36af8cSClaudio Fontana X86CPU *cpu = X86_CPU(cs); 2950c36af8cSClaudio Fontana APICCommonState *s = APIC_COMMON(cpu->apic_state); 2960c36af8cSClaudio Fontana if (!s) { 2970c36af8cSClaudio Fontana qemu_printf("local apic state not available\n"); 2980c36af8cSClaudio Fontana return; 2990c36af8cSClaudio Fontana } 3000c36af8cSClaudio Fontana uint32_t *lvt = s->lvt; 3010c36af8cSClaudio Fontana 3020c36af8cSClaudio Fontana qemu_printf("dumping local APIC state for CPU %-2u\n\n", 3030c36af8cSClaudio Fontana CPU(cpu)->cpu_index); 3040c36af8cSClaudio Fontana dump_apic_lvt("LVT0", lvt[APIC_LVT_LINT0], false); 3050c36af8cSClaudio Fontana dump_apic_lvt("LVT1", lvt[APIC_LVT_LINT1], false); 3060c36af8cSClaudio Fontana dump_apic_lvt("LVTPC", lvt[APIC_LVT_PERFORM], false); 3070c36af8cSClaudio Fontana dump_apic_lvt("LVTERR", lvt[APIC_LVT_ERROR], false); 3080c36af8cSClaudio Fontana dump_apic_lvt("LVTTHMR", lvt[APIC_LVT_THERMAL], false); 3090c36af8cSClaudio Fontana dump_apic_lvt("LVTT", lvt[APIC_LVT_TIMER], true); 3100c36af8cSClaudio Fontana 3110c36af8cSClaudio Fontana qemu_printf("Timer\t DCR=0x%x (divide by %u) initial_count = %u" 3120c36af8cSClaudio Fontana " current_count = %u\n", 3130c36af8cSClaudio Fontana s->divide_conf & APIC_DCR_MASK, 3140c36af8cSClaudio Fontana divider_conf(s->divide_conf), 3150c36af8cSClaudio Fontana s->initial_count, apic_get_current_count(s)); 3160c36af8cSClaudio Fontana 3170c36af8cSClaudio Fontana qemu_printf("SPIV\t 0x%08x APIC %s, focus=%s, spurious vec %u\n", 3180c36af8cSClaudio Fontana s->spurious_vec, 3190c36af8cSClaudio Fontana s->spurious_vec & APIC_SPURIO_ENABLED ? "enabled" : "disabled", 3200c36af8cSClaudio Fontana s->spurious_vec & APIC_SPURIO_FOCUS ? "on" : "off", 3210c36af8cSClaudio Fontana s->spurious_vec & APIC_VECTOR_MASK); 3220c36af8cSClaudio Fontana 3230c36af8cSClaudio Fontana dump_apic_icr(s, &cpu->env); 3240c36af8cSClaudio Fontana 3250c36af8cSClaudio Fontana qemu_printf("ESR\t 0x%08x\n", s->esr); 3260c36af8cSClaudio Fontana 3270c36af8cSClaudio Fontana dump_apic_interrupt("ISR", s->isr, s->tmr); 3280c36af8cSClaudio Fontana dump_apic_interrupt("IRR", s->irr, s->tmr); 3290c36af8cSClaudio Fontana 3300c36af8cSClaudio Fontana qemu_printf("\nAPR 0x%02x TPR 0x%02x DFR 0x%02x LDR 0x%02x", 3310c36af8cSClaudio Fontana s->arb_id, s->tpr, s->dest_mode, s->log_dest); 3320c36af8cSClaudio Fontana if (s->dest_mode == 0) { 3330c36af8cSClaudio Fontana qemu_printf("(cluster %u: id %u)", 3340c36af8cSClaudio Fontana s->log_dest >> APIC_LOGDEST_XAPIC_SHIFT, 3350c36af8cSClaudio Fontana s->log_dest & APIC_LOGDEST_XAPIC_ID); 3360c36af8cSClaudio Fontana } 3370c36af8cSClaudio Fontana qemu_printf(" PPR 0x%02x\n", apic_get_ppr(s)); 3380c36af8cSClaudio Fontana } 339b5c6a3c1SPhilippe Mathieu-Daudé 3400c36af8cSClaudio Fontana #endif /* !CONFIG_USER_ONLY */ 3410c36af8cSClaudio Fontana 3420c36af8cSClaudio Fontana #define DUMP_CODE_BYTES_TOTAL 50 3430c36af8cSClaudio Fontana #define DUMP_CODE_BYTES_BACKWARD 20 3440c36af8cSClaudio Fontana 3450c36af8cSClaudio Fontana void x86_cpu_dump_state(CPUState *cs, FILE *f, int flags) 3460c36af8cSClaudio Fontana { 3470c36af8cSClaudio Fontana X86CPU *cpu = X86_CPU(cs); 3480c36af8cSClaudio Fontana CPUX86State *env = &cpu->env; 3490c36af8cSClaudio Fontana int eflags, i, nb; 3500c36af8cSClaudio Fontana char cc_op_name[32]; 3510c36af8cSClaudio Fontana static const char *seg_name[6] = { "ES", "CS", "SS", "DS", "FS", "GS" }; 3520c36af8cSClaudio Fontana 3530c36af8cSClaudio Fontana eflags = cpu_compute_eflags(env); 3540c36af8cSClaudio Fontana #ifdef TARGET_X86_64 3550c36af8cSClaudio Fontana if (env->hflags & HF_CS64_MASK) { 3560c36af8cSClaudio Fontana qemu_fprintf(f, "RAX=%016" PRIx64 " RBX=%016" PRIx64 " RCX=%016" PRIx64 " RDX=%016" PRIx64 "\n" 3570c36af8cSClaudio Fontana "RSI=%016" PRIx64 " RDI=%016" PRIx64 " RBP=%016" PRIx64 " RSP=%016" PRIx64 "\n" 3580c36af8cSClaudio Fontana "R8 =%016" PRIx64 " R9 =%016" PRIx64 " R10=%016" PRIx64 " R11=%016" PRIx64 "\n" 3590c36af8cSClaudio Fontana "R12=%016" PRIx64 " R13=%016" PRIx64 " R14=%016" PRIx64 " R15=%016" PRIx64 "\n" 3600c36af8cSClaudio Fontana "RIP=%016" PRIx64 " RFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n", 3610c36af8cSClaudio Fontana env->regs[R_EAX], 3620c36af8cSClaudio Fontana env->regs[R_EBX], 3630c36af8cSClaudio Fontana env->regs[R_ECX], 3640c36af8cSClaudio Fontana env->regs[R_EDX], 3650c36af8cSClaudio Fontana env->regs[R_ESI], 3660c36af8cSClaudio Fontana env->regs[R_EDI], 3670c36af8cSClaudio Fontana env->regs[R_EBP], 3680c36af8cSClaudio Fontana env->regs[R_ESP], 3690c36af8cSClaudio Fontana env->regs[8], 3700c36af8cSClaudio Fontana env->regs[9], 3710c36af8cSClaudio Fontana env->regs[10], 3720c36af8cSClaudio Fontana env->regs[11], 3730c36af8cSClaudio Fontana env->regs[12], 3740c36af8cSClaudio Fontana env->regs[13], 3750c36af8cSClaudio Fontana env->regs[14], 3760c36af8cSClaudio Fontana env->regs[15], 3770c36af8cSClaudio Fontana env->eip, eflags, 3780c36af8cSClaudio Fontana eflags & DF_MASK ? 'D' : '-', 3790c36af8cSClaudio Fontana eflags & CC_O ? 'O' : '-', 3800c36af8cSClaudio Fontana eflags & CC_S ? 'S' : '-', 3810c36af8cSClaudio Fontana eflags & CC_Z ? 'Z' : '-', 3820c36af8cSClaudio Fontana eflags & CC_A ? 'A' : '-', 3830c36af8cSClaudio Fontana eflags & CC_P ? 'P' : '-', 3840c36af8cSClaudio Fontana eflags & CC_C ? 'C' : '-', 3850c36af8cSClaudio Fontana env->hflags & HF_CPL_MASK, 3860c36af8cSClaudio Fontana (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1, 3870c36af8cSClaudio Fontana (env->a20_mask >> 20) & 1, 3880c36af8cSClaudio Fontana (env->hflags >> HF_SMM_SHIFT) & 1, 3890c36af8cSClaudio Fontana cs->halted); 3900c36af8cSClaudio Fontana } else 3910c36af8cSClaudio Fontana #endif 3920c36af8cSClaudio Fontana { 3930c36af8cSClaudio Fontana qemu_fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n" 3940c36af8cSClaudio Fontana "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n" 3950c36af8cSClaudio Fontana "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c] CPL=%d II=%d A20=%d SMM=%d HLT=%d\n", 3960c36af8cSClaudio Fontana (uint32_t)env->regs[R_EAX], 3970c36af8cSClaudio Fontana (uint32_t)env->regs[R_EBX], 3980c36af8cSClaudio Fontana (uint32_t)env->regs[R_ECX], 3990c36af8cSClaudio Fontana (uint32_t)env->regs[R_EDX], 4000c36af8cSClaudio Fontana (uint32_t)env->regs[R_ESI], 4010c36af8cSClaudio Fontana (uint32_t)env->regs[R_EDI], 4020c36af8cSClaudio Fontana (uint32_t)env->regs[R_EBP], 4030c36af8cSClaudio Fontana (uint32_t)env->regs[R_ESP], 4040c36af8cSClaudio Fontana (uint32_t)env->eip, eflags, 4050c36af8cSClaudio Fontana eflags & DF_MASK ? 'D' : '-', 4060c36af8cSClaudio Fontana eflags & CC_O ? 'O' : '-', 4070c36af8cSClaudio Fontana eflags & CC_S ? 'S' : '-', 4080c36af8cSClaudio Fontana eflags & CC_Z ? 'Z' : '-', 4090c36af8cSClaudio Fontana eflags & CC_A ? 'A' : '-', 4100c36af8cSClaudio Fontana eflags & CC_P ? 'P' : '-', 4110c36af8cSClaudio Fontana eflags & CC_C ? 'C' : '-', 4120c36af8cSClaudio Fontana env->hflags & HF_CPL_MASK, 4130c36af8cSClaudio Fontana (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1, 4140c36af8cSClaudio Fontana (env->a20_mask >> 20) & 1, 4150c36af8cSClaudio Fontana (env->hflags >> HF_SMM_SHIFT) & 1, 4160c36af8cSClaudio Fontana cs->halted); 4170c36af8cSClaudio Fontana } 4180c36af8cSClaudio Fontana 4190c36af8cSClaudio Fontana for(i = 0; i < 6; i++) { 4200c36af8cSClaudio Fontana cpu_x86_dump_seg_cache(env, f, seg_name[i], &env->segs[i]); 4210c36af8cSClaudio Fontana } 4220c36af8cSClaudio Fontana cpu_x86_dump_seg_cache(env, f, "LDT", &env->ldt); 4230c36af8cSClaudio Fontana cpu_x86_dump_seg_cache(env, f, "TR", &env->tr); 4240c36af8cSClaudio Fontana 4250c36af8cSClaudio Fontana #ifdef TARGET_X86_64 4260c36af8cSClaudio Fontana if (env->hflags & HF_LMA_MASK) { 4270c36af8cSClaudio Fontana qemu_fprintf(f, "GDT= %016" PRIx64 " %08x\n", 4280c36af8cSClaudio Fontana env->gdt.base, env->gdt.limit); 4290c36af8cSClaudio Fontana qemu_fprintf(f, "IDT= %016" PRIx64 " %08x\n", 4300c36af8cSClaudio Fontana env->idt.base, env->idt.limit); 4310c36af8cSClaudio Fontana qemu_fprintf(f, "CR0=%08x CR2=%016" PRIx64 " CR3=%016" PRIx64 " CR4=%08x\n", 4320c36af8cSClaudio Fontana (uint32_t)env->cr[0], 4330c36af8cSClaudio Fontana env->cr[2], 4340c36af8cSClaudio Fontana env->cr[3], 4350c36af8cSClaudio Fontana (uint32_t)env->cr[4]); 4360c36af8cSClaudio Fontana for(i = 0; i < 4; i++) 4370c36af8cSClaudio Fontana qemu_fprintf(f, "DR%d=%016" PRIx64 " ", i, env->dr[i]); 4380c36af8cSClaudio Fontana qemu_fprintf(f, "\nDR6=%016" PRIx64 " DR7=%016" PRIx64 "\n", 4390c36af8cSClaudio Fontana env->dr[6], env->dr[7]); 4400c36af8cSClaudio Fontana } else 4410c36af8cSClaudio Fontana #endif 4420c36af8cSClaudio Fontana { 4430c36af8cSClaudio Fontana qemu_fprintf(f, "GDT= %08x %08x\n", 4440c36af8cSClaudio Fontana (uint32_t)env->gdt.base, env->gdt.limit); 4450c36af8cSClaudio Fontana qemu_fprintf(f, "IDT= %08x %08x\n", 4460c36af8cSClaudio Fontana (uint32_t)env->idt.base, env->idt.limit); 4470c36af8cSClaudio Fontana qemu_fprintf(f, "CR0=%08x CR2=%08x CR3=%08x CR4=%08x\n", 4480c36af8cSClaudio Fontana (uint32_t)env->cr[0], 4490c36af8cSClaudio Fontana (uint32_t)env->cr[2], 4500c36af8cSClaudio Fontana (uint32_t)env->cr[3], 4510c36af8cSClaudio Fontana (uint32_t)env->cr[4]); 4520c36af8cSClaudio Fontana for(i = 0; i < 4; i++) { 4530c36af8cSClaudio Fontana qemu_fprintf(f, "DR%d=" TARGET_FMT_lx " ", i, env->dr[i]); 4540c36af8cSClaudio Fontana } 4550c36af8cSClaudio Fontana qemu_fprintf(f, "\nDR6=" TARGET_FMT_lx " DR7=" TARGET_FMT_lx "\n", 4560c36af8cSClaudio Fontana env->dr[6], env->dr[7]); 4570c36af8cSClaudio Fontana } 4580c36af8cSClaudio Fontana if (flags & CPU_DUMP_CCOP) { 4590c36af8cSClaudio Fontana if ((unsigned)env->cc_op < CC_OP_NB) 4600c36af8cSClaudio Fontana snprintf(cc_op_name, sizeof(cc_op_name), "%s", cc_op_str[env->cc_op]); 4610c36af8cSClaudio Fontana else 4620c36af8cSClaudio Fontana snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op); 4630c36af8cSClaudio Fontana #ifdef TARGET_X86_64 4640c36af8cSClaudio Fontana if (env->hflags & HF_CS64_MASK) { 46561848717SMarkus Armbruster qemu_fprintf(f, "CCS=%016" PRIx64 " CCD=%016" PRIx64 " CCO=%s\n", 4660c36af8cSClaudio Fontana env->cc_src, env->cc_dst, 4670c36af8cSClaudio Fontana cc_op_name); 4680c36af8cSClaudio Fontana } else 4690c36af8cSClaudio Fontana #endif 4700c36af8cSClaudio Fontana { 47161848717SMarkus Armbruster qemu_fprintf(f, "CCS=%08x CCD=%08x CCO=%s\n", 4720c36af8cSClaudio Fontana (uint32_t)env->cc_src, (uint32_t)env->cc_dst, 4730c36af8cSClaudio Fontana cc_op_name); 4740c36af8cSClaudio Fontana } 4750c36af8cSClaudio Fontana } 4760c36af8cSClaudio Fontana qemu_fprintf(f, "EFER=%016" PRIx64 "\n", env->efer); 4770c36af8cSClaudio Fontana if (flags & CPU_DUMP_FPU) { 4780c36af8cSClaudio Fontana int fptag; 479f9c0322aSRobert Hoo const uint64_t avx512_mask = XSTATE_OPMASK_MASK | \ 480f9c0322aSRobert Hoo XSTATE_ZMM_Hi256_MASK | \ 481f9c0322aSRobert Hoo XSTATE_Hi16_ZMM_MASK | \ 482f9c0322aSRobert Hoo XSTATE_YMM_MASK | XSTATE_SSE_MASK, 483f9c0322aSRobert Hoo avx_mask = XSTATE_YMM_MASK | XSTATE_SSE_MASK; 4840c36af8cSClaudio Fontana fptag = 0; 4850c36af8cSClaudio Fontana for(i = 0; i < 8; i++) { 4860c36af8cSClaudio Fontana fptag |= ((!env->fptags[i]) << i); 4870c36af8cSClaudio Fontana } 4880c36af8cSClaudio Fontana update_mxcsr_from_sse_status(env); 4890c36af8cSClaudio Fontana qemu_fprintf(f, "FCW=%04x FSW=%04x [ST=%d] FTW=%02x MXCSR=%08x\n", 4900c36af8cSClaudio Fontana env->fpuc, 4910c36af8cSClaudio Fontana (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11, 4920c36af8cSClaudio Fontana env->fpstt, 4930c36af8cSClaudio Fontana fptag, 4940c36af8cSClaudio Fontana env->mxcsr); 4950c36af8cSClaudio Fontana for(i=0;i<8;i++) { 4960c36af8cSClaudio Fontana CPU_LDoubleU u; 4970c36af8cSClaudio Fontana u.d = env->fpregs[i].d; 4980c36af8cSClaudio Fontana qemu_fprintf(f, "FPR%d=%016" PRIx64 " %04x", 4990c36af8cSClaudio Fontana i, u.l.lower, u.l.upper); 5000c36af8cSClaudio Fontana if ((i & 1) == 1) 5010c36af8cSClaudio Fontana qemu_fprintf(f, "\n"); 5020c36af8cSClaudio Fontana else 5030c36af8cSClaudio Fontana qemu_fprintf(f, " "); 5040c36af8cSClaudio Fontana } 505f9c0322aSRobert Hoo 506f9c0322aSRobert Hoo if ((env->xcr0 & avx512_mask) == avx512_mask) { 507f9c0322aSRobert Hoo /* XSAVE enabled AVX512 */ 508f9c0322aSRobert Hoo for (i = 0; i < NB_OPMASK_REGS; i++) { 509f9c0322aSRobert Hoo qemu_fprintf(f, "Opmask%02d=%016"PRIx64"%s", i, 510f9c0322aSRobert Hoo env->opmask_regs[i], ((i & 3) == 3) ? "\n" : " "); 511f9c0322aSRobert Hoo } 512f9c0322aSRobert Hoo 513f9c0322aSRobert Hoo nb = (env->hflags & HF_CS64_MASK) ? 32 : 8; 5140c36af8cSClaudio Fontana for (i = 0; i < nb; i++) { 515f9c0322aSRobert Hoo qemu_fprintf(f, "ZMM%02d=%016"PRIx64" %016"PRIx64" %016"PRIx64 516f9c0322aSRobert Hoo " %016"PRIx64" %016"PRIx64" %016"PRIx64 517f9c0322aSRobert Hoo " %016"PRIx64" %016"PRIx64"\n", 5180c36af8cSClaudio Fontana i, 519f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(7), 520f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(6), 521f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(5), 522f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(4), 523f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(3), 524f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(2), 525f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(1), 526f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(0)); 527f9c0322aSRobert Hoo } 528f9c0322aSRobert Hoo } else if ((env->xcr0 & avx_mask) == avx_mask) { 529f9c0322aSRobert Hoo /* XSAVE enabled AVX */ 530f9c0322aSRobert Hoo nb = env->hflags & HF_CS64_MASK ? 16 : 8; 531f9c0322aSRobert Hoo for (i = 0; i < nb; i++) { 532f9c0322aSRobert Hoo qemu_fprintf(f, "YMM%02d=%016"PRIx64" %016"PRIx64" %016"PRIx64 533f9c0322aSRobert Hoo " %016"PRIx64"\n", i, 534f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(3), 535f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(2), 536f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(1), 537f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(0)); 538f9c0322aSRobert Hoo } 539f9c0322aSRobert Hoo } else { /* SSE and below cases */ 540f9c0322aSRobert Hoo nb = env->hflags & HF_CS64_MASK ? 16 : 8; 541f9c0322aSRobert Hoo for (i = 0; i < nb; i++) { 542f9c0322aSRobert Hoo qemu_fprintf(f, "XMM%02d=%016"PRIx64" %016"PRIx64"%s", 543f9c0322aSRobert Hoo i, 544f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(1), 545f9c0322aSRobert Hoo env->xmm_regs[i].ZMM_Q(0), 546f9c0322aSRobert Hoo (i & 1) ? "\n" : " "); 547f9c0322aSRobert Hoo } 5480c36af8cSClaudio Fontana } 5490c36af8cSClaudio Fontana } 5500c36af8cSClaudio Fontana if (flags & CPU_DUMP_CODE) { 5510c36af8cSClaudio Fontana target_ulong base = env->segs[R_CS].base + env->eip; 5520c36af8cSClaudio Fontana target_ulong offs = MIN(env->eip, DUMP_CODE_BYTES_BACKWARD); 5530c36af8cSClaudio Fontana uint8_t code; 5540c36af8cSClaudio Fontana char codestr[3]; 5550c36af8cSClaudio Fontana 5560c36af8cSClaudio Fontana qemu_fprintf(f, "Code="); 5570c36af8cSClaudio Fontana for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) { 5580c36af8cSClaudio Fontana if (cpu_memory_rw_debug(cs, base - offs + i, &code, 1, 0) == 0) { 5590c36af8cSClaudio Fontana snprintf(codestr, sizeof(codestr), "%02x", code); 5600c36af8cSClaudio Fontana } else { 5610c36af8cSClaudio Fontana snprintf(codestr, sizeof(codestr), "??"); 5620c36af8cSClaudio Fontana } 5630c36af8cSClaudio Fontana qemu_fprintf(f, "%s%s%s%s", i > 0 ? " " : "", 5640c36af8cSClaudio Fontana i == offs ? "<" : "", codestr, i == offs ? ">" : ""); 5650c36af8cSClaudio Fontana } 5660c36af8cSClaudio Fontana qemu_fprintf(f, "\n"); 5670c36af8cSClaudio Fontana } 5680c36af8cSClaudio Fontana } 569