xref: /qemu/target/i386/cpu-dump.c (revision e36b976da4f6f4c0d434e6bb811f60b7b445e8ea)
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