Revision 79c4f6b0

b/cpu-all.h
770 770
#define CPU_INTERRUPT_NMI    0x200 /* NMI pending. */
771 771
#define CPU_INTERRUPT_INIT   0x400 /* INIT pending. */
772 772
#define CPU_INTERRUPT_SIPI   0x800 /* SIPI pending. */
773
#define CPU_INTERRUPT_MCE    0x1000 /* (x86 only) MCE pending. */
773 774

  
774 775
void cpu_interrupt(CPUState *s, int mask);
775 776
void cpu_reset_interrupt(CPUState *env, int mask);
......
1071 1072
extern int64_t kqemu_ret_intr_count;
1072 1073
#endif
1073 1074

  
1075
void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
1076
                        uint64_t mcg_status, uint64_t addr, uint64_t misc);
1077

  
1074 1078
#endif /* CPU_ALL_H */
b/cpu-exec.c
400 400
                            env->hflags2 |= HF2_NMI_MASK;
401 401
                            do_interrupt(EXCP02_NMI, 0, 0, 0, 1);
402 402
                            next_tb = 0;
403
			} else if (interrupt_request & CPU_INTERRUPT_MCE) {
404
                            env->interrupt_request &= ~CPU_INTERRUPT_MCE;
405
                            do_interrupt(EXCP12_MCHK, 0, 0, 0, 0);
406
                            next_tb = 0;
403 407
                        } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
404 408
                                   (((env->hflags2 & HF2_VINTR_MASK) && 
405 409
                                     (env->hflags2 & HF2_HIF_MASK)) ||
b/monitor.c
1677 1677
    }
1678 1678
}
1679 1679

  
1680
#if defined(TARGET_I386)
1681
static void do_inject_mce(Monitor *mon,
1682
                          int cpu_index, int bank,
1683
                          unsigned status_hi, unsigned status_lo,
1684
                          unsigned mcg_status_hi, unsigned mcg_status_lo,
1685
                          unsigned addr_hi, unsigned addr_lo,
1686
                          unsigned misc_hi, unsigned misc_lo)
1687
{
1688
    CPUState *cenv;
1689
    uint64_t status = ((uint64_t)status_hi << 32) | status_lo;
1690
    uint64_t mcg_status = ((uint64_t)mcg_status_hi << 32) | mcg_status_lo;
1691
    uint64_t addr = ((uint64_t)addr_hi << 32) | addr_lo;
1692
    uint64_t misc = ((uint64_t)misc_hi << 32) | misc_lo;
1693

  
1694
    for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu)
1695
        if (cenv->cpu_index == cpu_index && cenv->mcg_cap) {
1696
            cpu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc);
1697
            break;
1698
        }
1699
}
1700
#endif
1701

  
1680 1702
static const mon_cmd_t mon_cmds[] = {
1681 1703
#include "qemu-monitor.h"
1682 1704
    { NULL, NULL, },
......
2451 2473
                      void *arg3, void *arg4, void *arg5);
2452 2474
    void (*handler_7)(Monitor *mon, void *arg0, void *arg1, void *arg2,
2453 2475
                      void *arg3, void *arg4, void *arg5, void *arg6);
2476
    void (*handler_8)(Monitor *mon, void *arg0, void *arg1, void *arg2,
2477
                      void *arg3, void *arg4, void *arg5, void *arg6,
2478
                      void *arg7);
2479
    void (*handler_9)(Monitor *mon, void *arg0, void *arg1, void *arg2,
2480
                      void *arg3, void *arg4, void *arg5, void *arg6,
2481
                      void *arg7, void *arg8);
2482
    void (*handler_10)(Monitor *mon, void *arg0, void *arg1, void *arg2,
2483
                       void *arg3, void *arg4, void *arg5, void *arg6,
2484
                       void *arg7, void *arg8, void *arg9);
2454 2485

  
2455 2486
#ifdef DEBUG
2456 2487
    monitor_printf(mon, "command='%s'\n", cmdline);
......
2739 2770
        handler_7(mon, args[0], args[1], args[2], args[3], args[4], args[5],
2740 2771
                  args[6]);
2741 2772
        break;
2773
    case 8:
2774
        handler_8 = cmd->handler;
2775
        handler_8(mon, args[0], args[1], args[2], args[3], args[4], args[5],
2776
                  args[6], args[7]);
2777
        break;
2778
    case 9:
2779
        handler_9 = cmd->handler;
2780
        handler_9(mon, args[0], args[1], args[2], args[3], args[4], args[5],
2781
                  args[6], args[7], args[8]);
2782
        break;
2783
    case 10:
2784
        handler_10 = cmd->handler;
2785
        handler_10(mon, args[0], args[1], args[2], args[3], args[4], args[5],
2786
                   args[6], args[7], args[8], args[9]);
2787
        break;
2742 2788
    default:
2743 2789
        monitor_printf(mon, "unsupported number of arguments: %d\n", nb_args);
2744 2790
        goto fail;
b/qemu-monitor.hx
615 615
policy back to @code{deny}.
616 616
ETEXI
617 617

  
618
#if defined(TARGET_I386)
619
    { "mce", "iillll", do_inject_mce, "cpu bank status mcgstatus addr misc", "inject a MCE on the given CPU"},
620
#endif
621
STEXI
622
@item mce @var{cpu} @var{bank} @var{status} @var{mcgstatus} @var{addr} @var{misc}
623
Inject an MCE on the given CPU (x86 only).
624
ETEXI
625

  
618 626
STEXI
619 627
@end table
620 628
ETEXI
b/target-i386/cpu.h
204 204
#define CR4_DE_MASK   (1 << 3)
205 205
#define CR4_PSE_MASK  (1 << 4)
206 206
#define CR4_PAE_MASK  (1 << 5)
207
#define CR4_MCE_MASK  (1 << 6)
207 208
#define CR4_PGE_MASK  (1 << 7)
208 209
#define CR4_PCE_MASK  (1 << 8)
209 210
#define CR4_OSFXSR_SHIFT 9
......
250 251
#define PG_ERROR_RSVD_MASK 0x08
251 252
#define PG_ERROR_I_D_MASK  0x10
252 253

  
254
#define MCG_CTL_P	(1UL<<8)   /* MCG_CAP register available */
255

  
256
#define MCE_CAP_DEF	MCG_CTL_P
257
#define MCE_BANKS_DEF	10
258

  
259
#define MCG_STATUS_MCIP	(1UL<<2)   /* machine check in progress */
260

  
261
#define MCI_STATUS_VAL	(1UL<<63)  /* valid error */
262
#define MCI_STATUS_OVER	(1UL<<62)  /* previous errors lost */
263
#define MCI_STATUS_UC	(1UL<<61)  /* uncorrected error */
264

  
253 265
#define MSR_IA32_TSC                    0x10
254 266
#define MSR_IA32_APICBASE               0x1b
255 267
#define MSR_IA32_APICBASE_BSP           (1<<8)
......
290 302

  
291 303
#define MSR_MTRRdefType			0x2ff
292 304

  
305
#define MSR_MC0_CTL			0x400
306
#define MSR_MC0_STATUS			0x401
307
#define MSR_MC0_ADDR			0x402
308
#define MSR_MC0_MISC			0x403
309

  
293 310
#define MSR_EFER                        0xc0000080
294 311

  
295 312
#define MSR_EFER_SCE   (1 << 0)
......
678 695
    /* in order to simplify APIC support, we leave this pointer to the
679 696
       user */
680 697
    struct APICState *apic_state;
698

  
699
    uint64 mcg_cap;
700
    uint64 mcg_status;
701
    uint64 mcg_ctl;
702
    uint64 *mce_banks;
681 703
} CPUX86State;
682 704

  
683 705
CPUX86State *cpu_x86_init(const char *cpu_model);
......
842 864
#define cpu_signal_handler cpu_x86_signal_handler
843 865
#define cpu_list x86_cpu_list
844 866

  
845
#define CPU_SAVE_VERSION 9
867
#define CPU_SAVE_VERSION 10
846 868

  
847 869
/* MMU modes definitions */
848 870
#define MMU_MODE0_SUFFIX _kernel
b/target-i386/helper.c
1496 1496
    if (prev_debug_excp_handler)
1497 1497
        prev_debug_excp_handler(env);
1498 1498
}
1499

  
1500
/* This should come from sysemu.h - if we could include it here... */
1501
void qemu_system_reset_request(void);
1502

  
1503
void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
1504
                        uint64_t mcg_status, uint64_t addr, uint64_t misc)
1505
{
1506
    uint64_t mcg_cap = cenv->mcg_cap;
1507
    unsigned bank_num = mcg_cap & 0xff;
1508
    uint64_t *banks = cenv->mce_banks;
1509

  
1510
    if (bank >= bank_num || !(status & MCI_STATUS_VAL))
1511
        return;
1512

  
1513
    /*
1514
     * if MSR_MCG_CTL is not all 1s, the uncorrected error
1515
     * reporting is disabled
1516
     */
1517
    if ((status & MCI_STATUS_UC) && (mcg_cap & MCG_CTL_P) &&
1518
        cenv->mcg_ctl != ~(uint64_t)0)
1519
        return;
1520
    banks += 4 * bank;
1521
    /*
1522
     * if MSR_MCi_CTL is not all 1s, the uncorrected error
1523
     * reporting is disabled for the bank
1524
     */
1525
    if ((status & MCI_STATUS_UC) && banks[0] != ~(uint64_t)0)
1526
        return;
1527
    if (status & MCI_STATUS_UC) {
1528
        if ((cenv->mcg_status & MCG_STATUS_MCIP) ||
1529
            !(cenv->cr[4] & CR4_MCE_MASK)) {
1530
            fprintf(stderr, "injects mce exception while previous "
1531
                    "one is in progress!\n");
1532
            qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
1533
            qemu_system_reset_request();
1534
            return;
1535
        }
1536
        if (banks[1] & MCI_STATUS_VAL)
1537
            status |= MCI_STATUS_OVER;
1538
        banks[2] = addr;
1539
        banks[3] = misc;
1540
        cenv->mcg_status = mcg_status;
1541
        banks[1] = status;
1542
        cpu_interrupt(cenv, CPU_INTERRUPT_MCE);
1543
    } else if (!(banks[1] & MCI_STATUS_VAL)
1544
               || !(banks[1] & MCI_STATUS_UC)) {
1545
        if (banks[1] & MCI_STATUS_VAL)
1546
            status |= MCI_STATUS_OVER;
1547
        banks[2] = addr;
1548
        banks[3] = misc;
1549
        banks[1] = status;
1550
    } else
1551
        banks[1] |= MCI_STATUS_OVER;
1552
}
1499 1553
#endif /* !CONFIG_USER_ONLY */
1500 1554

  
1555
static void mce_init(CPUX86State *cenv)
1556
{
1557
    unsigned int bank, bank_num;
1558

  
1559
    if (((cenv->cpuid_version >> 8)&0xf) >= 6
1560
        && (cenv->cpuid_features&(CPUID_MCE|CPUID_MCA)) == (CPUID_MCE|CPUID_MCA)) {
1561
        cenv->mcg_cap = MCE_CAP_DEF | MCE_BANKS_DEF;
1562
        cenv->mcg_ctl = ~(uint64_t)0;
1563
        bank_num = cenv->mcg_cap & 0xff;
1564
        cenv->mce_banks = qemu_mallocz(bank_num * sizeof(uint64_t) * 4);
1565
        for (bank = 0; bank < bank_num; bank++)
1566
            cenv->mce_banks[bank*4] = ~(uint64_t)0;
1567
    }
1568
}
1569

  
1501 1570
static void host_cpuid(uint32_t function, uint32_t count,
1502 1571
                       uint32_t *eax, uint32_t *ebx,
1503 1572
                       uint32_t *ecx, uint32_t *edx)
......
1735 1804
        cpu_x86_close(env);
1736 1805
        return NULL;
1737 1806
    }
1807
    mce_init(env);
1738 1808
    cpu_reset(env);
1739 1809
#ifdef CONFIG_KQEMU
1740 1810
    kqemu_init(env);
b/target-i386/machine.c
158 158
    qemu_put_sbe32s(f, &pending_irq);
159 159
    qemu_put_be32s(f, &env->mp_state);
160 160
    qemu_put_be64s(f, &env->tsc);
161
}
161

  
162
    /* MCE */
163
    qemu_put_be64s(f, &env->mcg_cap);
164
    if (env->mcg_cap) {
165
        qemu_put_be64s(f, &env->mcg_status);
166
        qemu_put_be64s(f, &env->mcg_ctl);
167
        for (i = 0; i < (env->mcg_cap & 0xff); i++) {
168
            qemu_put_be64s(f, &env->mce_banks[4*i]);
169
            qemu_put_be64s(f, &env->mce_banks[4*i + 1]);
170
            qemu_put_be64s(f, &env->mce_banks[4*i + 2]);
171
            qemu_put_be64s(f, &env->mce_banks[4*i + 3]);
172
        }
173
    }
174
 }
162 175

  
163 176
#ifdef USE_X86LDOUBLE
164 177
/* XXX: add that in a FPU generic layer */
......
349 362
        qemu_get_be64s(f, &env->tsc);
350 363
    }
351 364

  
365
    if (version_id >= 10) {
366
        qemu_get_be64s(f, &env->mcg_cap);
367
        if (env->mcg_cap) {
368
            qemu_get_be64s(f, &env->mcg_status);
369
            qemu_get_be64s(f, &env->mcg_ctl);
370
            for (i = 0; i < (env->mcg_cap & 0xff); i++) {
371
                qemu_get_be64s(f, &env->mce_banks[4*i]);
372
                qemu_get_be64s(f, &env->mce_banks[4*i + 1]);
373
                qemu_get_be64s(f, &env->mce_banks[4*i + 2]);
374
                qemu_get_be64s(f, &env->mce_banks[4*i + 3]);
375
            }
376
        }
377
    }
378

  
352 379
    /* XXX: ensure compatiblity for halted bit ? */
353 380
    /* XXX: compute redundant hflags bits */
354 381
    env->hflags = hflags;
b/target-i386/op_helper.c
3133 3133
    case MSR_MTRRdefType:
3134 3134
        env->mtrr_deftype = val;
3135 3135
        break;
3136
    case MSR_MCG_STATUS:
3137
        env->mcg_status = val;
3138
        break;
3139
    case MSR_MCG_CTL:
3140
        if ((env->mcg_cap & MCG_CTL_P)
3141
            && (val == 0 || val == ~(uint64_t)0))
3142
            env->mcg_ctl = val;
3143
        break;
3136 3144
    default:
3145
        if ((uint32_t)ECX >= MSR_MC0_CTL
3146
            && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
3147
            uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;
3148
            if ((offset & 0x3) != 0
3149
                || (val == 0 || val == ~(uint64_t)0))
3150
                env->mce_banks[offset] = val;
3151
            break;
3152
        }
3137 3153
        /* XXX: exception ? */
3138 3154
        break;
3139 3155
    }
......
3252 3268
            /* XXX: exception ? */
3253 3269
            val = 0;
3254 3270
        break;
3271
    case MSR_MCG_CAP:
3272
        val = env->mcg_cap;
3273
        break;
3274
    case MSR_MCG_CTL:
3275
        if (env->mcg_cap & MCG_CTL_P)
3276
            val = env->mcg_ctl;
3277
        else
3278
            val = 0;
3279
        break;
3280
    case MSR_MCG_STATUS:
3281
        val = env->mcg_status;
3282
        break;
3255 3283
    default:
3284
        if ((uint32_t)ECX >= MSR_MC0_CTL
3285
            && (uint32_t)ECX < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) {
3286
            uint32_t offset = (uint32_t)ECX - MSR_MC0_CTL;
3287
            val = env->mce_banks[offset];
3288
            break;
3289
        }
3256 3290
        /* XXX: exception ? */
3257 3291
        val = 0;
3258 3292
        break;

Also available in: Unified diff