コード例 #1
0
ファイル: mce_amd.c プロジェクト: sheep/xen
static struct mcinfo_extended *
amd_f10_handler(struct mc_info *mi, uint16_t bank, uint64_t status)
{
    struct mcinfo_extended *mc_ext;

    /* Family 0x10 introduced additional MSR that belong to the
     * northbridge bank (4). */
    if ( mi == NULL || bank != 4 )
        return NULL;

    if ( !(status & MCi_STATUS_VAL) )
        return NULL;

    if ( !(status & MCi_STATUS_MISCV) )
        return NULL;

    mc_ext = x86_mcinfo_reserve(mi, sizeof(*mc_ext), MC_TYPE_EXTENDED);
    if ( !mc_ext )
    {
        mi->flags |= MCINFO_FLAGS_UNCOMPLETE;
        return NULL;
    }

    mc_ext->mc_msrs = 3;

    mc_ext->mc_msr[0].reg = MSR_F10_MC4_MISC1;
    mc_ext->mc_msr[1].reg = MSR_F10_MC4_MISC2;
    mc_ext->mc_msr[2].reg = MSR_F10_MC4_MISC3;

    mc_ext->mc_msr[0].value = mca_rdmsr(MSR_F10_MC4_MISC1);
    mc_ext->mc_msr[1].value = mca_rdmsr(MSR_F10_MC4_MISC2);
    mc_ext->mc_msr[2].value = mca_rdmsr(MSR_F10_MC4_MISC3);

    return mc_ext;
}
コード例 #2
0
ファイル: mce.c プロジェクト: SJTU-IPADS/PMigrate-Xen
static struct mcinfo_bank *mca_init_bank(enum mca_source who,
                                         struct mc_info *mi, int bank)
{
    struct mcinfo_bank *mib;
    uint64_t addr=0, misc = 0;

    if (!mi)
        return NULL;

    mib = x86_mcinfo_reserve(mi, sizeof(struct mcinfo_bank));
    if (!mib)
    {
        mi->flags |= MCINFO_FLAGS_UNCOMPLETE;
        return NULL;
    }

    memset(mib, 0, sizeof (struct mcinfo_bank));
    mib->mc_status = mca_rdmsr(MSR_IA32_MCx_STATUS(bank));

    mib->common.type = MC_TYPE_BANK;
    mib->common.size = sizeof (struct mcinfo_bank);
    mib->mc_bank = bank;

    addr = misc = 0;
    if (mib->mc_status & MCi_STATUS_MISCV)
        mib->mc_misc = mca_rdmsr(MSR_IA32_MCx_MISC(bank));

    if (mib->mc_status & MCi_STATUS_ADDRV)
    {
        mib->mc_addr = mca_rdmsr(MSR_IA32_MCx_ADDR(bank));

        if (mfn_valid(paddr_to_pfn(mib->mc_addr))) {
            struct domain *d;

            d = maddr_get_owner(mib->mc_addr);
            if (d != NULL && (who == MCA_POLLER ||
                              who == MCA_CMCI_HANDLER))
                mib->mc_domid = d->domain_id;
        }
    }

    if (who == MCA_CMCI_HANDLER) {
        mib->mc_ctrl2 = mca_rdmsr(MSR_IA32_MC0_CTL2 + bank);
        rdtscll(mib->mc_tsc);
    }

    return mib;
}
コード例 #3
0
ファイル: mce.c プロジェクト: dzan/xenOnArm
static void mca_init_bank(enum mca_source who,
    struct mc_info *mi, int bank)
{
    struct mcinfo_bank *mib;

    if (!mi)
        return;

    mib = x86_mcinfo_reserve(mi, sizeof(*mib));
    if (!mib)
    {
        mi->flags |= MCINFO_FLAGS_UNCOMPLETE;
        return;
    }

    mib->mc_status = mca_rdmsr(MSR_IA32_MCx_STATUS(bank));

    mib->common.type = MC_TYPE_BANK;
    mib->common.size = sizeof (struct mcinfo_bank);
    mib->mc_bank = bank;

    if (mib->mc_status & MCi_STATUS_MISCV)
        mib->mc_misc = mca_rdmsr(MSR_IA32_MCx_MISC(bank));

    if (mib->mc_status & MCi_STATUS_ADDRV)
        mib->mc_addr = mca_rdmsr(MSR_IA32_MCx_ADDR(bank));

    if ((mib->mc_status & MCi_STATUS_MISCV) &&
        (mib->mc_status & MCi_STATUS_ADDRV) &&
        (mc_check_addr(mib->mc_status, mib->mc_misc, MC_ADDR_PHYSICAL)) &&
        (who == MCA_POLLER || who == MCA_CMCI_HANDLER) &&
        (mfn_valid(paddr_to_pfn(mib->mc_addr))))
    {
        struct domain *d;

        d = maddr_get_owner(mib->mc_addr);
        if (d)
            mib->mc_domid = d->domain_id;
    }

    if (who == MCA_CMCI_HANDLER) {
        mib->mc_ctrl2 = mca_rdmsr(MSR_IA32_MC0_CTL2 + bank);
        rdtscll(mib->mc_tsc);
    }
}
コード例 #4
0
static struct mcinfo_recovery *
mci_action_add_pageoffline(int bank, struct mc_info *mi,
                       uint64_t mfn, uint32_t status)
{
    struct mcinfo_recovery *rec;

    if (!mi)
        return NULL;

    rec = x86_mcinfo_reserve(mi, sizeof(*rec));
    if (!rec) {
        mi->flags |= MCINFO_FLAGS_UNCOMPLETE;
        return NULL;
    }

    rec->common.type = MC_TYPE_RECOVERY;
    rec->common.size = sizeof(*rec);
    rec->mc_bank = bank;
    rec->action_types = MC_ACTION_PAGE_OFFLINE;
    rec->action_info.page_retire.mfn = mfn;
    rec->action_info.page_retire.status = status;
    return rec;
}
コード例 #5
0
ファイル: mce.c プロジェクト: dzan/xenOnArm
/* Add out_param clear_bank for Machine Check Handler Caller.
 * For Intel latest CPU, whether to clear the error bank status needs to
 * be judged by the callback function defined above.
 */
mctelem_cookie_t
mcheck_mca_logout(enum mca_source who, struct mca_banks *bankmask,
                  struct mca_summary *sp, struct mca_banks *clear_bank)
{
    uint64_t gstatus, status;
    struct mcinfo_global *mig = NULL; /* on stack */
    mctelem_cookie_t mctc = NULL;
    bool_t uc = 0, pcc = 0, recover = 1, need_clear = 1;
    uint32_t mc_flags = 0;
    struct mc_info *mci = NULL;
    mctelem_class_t which = MC_URGENT; /* XXXgcc */
    int errcnt = 0;
    int i;

    gstatus = mca_rdmsr(MSR_IA32_MCG_STATUS);
    switch (who) {
    case MCA_MCE_SCAN:
        mc_flags = MC_FLAG_MCE;
        which = MC_URGENT;
        break;

    case MCA_POLLER:
    case MCA_RESET:
        mc_flags = MC_FLAG_POLLED;
        which = MC_NONURGENT;
        break;

    case MCA_CMCI_HANDLER:
        mc_flags = MC_FLAG_CMCI;
        which = MC_NONURGENT;
        break;

    default:
        BUG();
    }

    /* If no mc_recovery_scan callback handler registered,
     * this error is not recoverable
     */
    recover = (mc_recoverable_scan) ? 1 : 0;

    for (i = 0; i < nr_mce_banks; i++) {
        /* Skip bank if corresponding bit in bankmask is clear */
        if (!mcabanks_test(i, bankmask))
            continue;

        status = mca_rdmsr(MSR_IA32_MCx_STATUS(i));
        if (!(status & MCi_STATUS_VAL))
            continue; /* this bank has no valid telemetry */

        /* For Intel Latest CPU CMCI/MCE Handler caller, we need to
         * decide whether to clear bank by MCi_STATUS bit value such as
         * OVER/UC/EN/PCC/S/AR
         */
        if ( mc_need_clearbank_scan )
            need_clear = mc_need_clearbank_scan(who, status);

        /* If this is the first bank with valid MCA DATA, then
         * try to reserve an entry from the urgent/nonurgent queue
         * depending on whether we are called from an exception or
         * a poller;  this can fail (for example dom0 may not
         * yet have consumed past telemetry). */
        if (errcnt++ == 0) {
            if ( (mctc = mctelem_reserve(which)) != NULL ) {
                mci = mctelem_dataptr(mctc);
                mcinfo_clear(mci);
                mig = x86_mcinfo_reserve(mci, sizeof(*mig));
                /* mc_info should at least hold up the global information */
                ASSERT(mig);
                mca_init_global(mc_flags, mig);
                /* A hook here to get global extended msrs */
                {
                    if (boot_cpu_data.x86_vendor ==
                        X86_VENDOR_INTEL)
                        intel_get_extended_msrs(mig, mci);
                }
            }
        }

        /* flag for uncorrected errors */
        if (!uc && ((status & MCi_STATUS_UC) != 0))
            uc = 1;

        /* flag processor context corrupt */
        if (!pcc && ((status & MCi_STATUS_PCC) != 0))
            pcc = 1;

        if (recover && uc)
            /* uc = 1, recover = 1, we need not panic.
             */
            recover = mc_recoverable_scan(status);

        mca_init_bank(who, mci, i);

        if (mc_callback_bank_extended)
            mc_callback_bank_extended(mci, i, status);

        /* By default, need_clear = 1 */
        if (who != MCA_MCE_SCAN && need_clear)
            /* Clear bank */
            mcabank_clear(i);
        else if ( who == MCA_MCE_SCAN && need_clear)
            mcabanks_set(i, clear_bank);

        wmb();
    }

    if (mig && errcnt > 0) {
        if (pcc)
            mig->mc_flags |= MC_FLAG_UNCORRECTABLE;
        else if (uc)
            mig->mc_flags |= MC_FLAG_RECOVERABLE;
        else
            mig->mc_flags |= MC_FLAG_CORRECTABLE;
    }


    if (sp) {
        sp->errcnt = errcnt;
        sp->ripv = (gstatus & MCG_STATUS_RIPV) != 0;
        sp->eipv = (gstatus & MCG_STATUS_EIPV) != 0;
        sp->uc = uc;
        sp->pcc = pcc;
        sp->recoverable = recover;
    }

    return mci != NULL ? mctc : NULL; /* may be NULL */
}