Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

511 lines
13 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
mca.c
Abstract:
WinDbg Extension Api
Author:
Shiv Kaushik
Environment:
User Mode.
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//
// MCA MSR architecture definitions
//
//
// MSR addresses for Pentium Style Machine Check Exception
//
#define MCE_MSR_MC_ADDR 0x0
#define MCE_MSR_MC_TYPE 0x1
//
// MSR addresses for Pentium Pro Style Machine Check Architecture
//
//
// Global capability, status and control register addresses
//
#define MCA_MSR_MCG_CAP 0x179
#define MCA_MSR_MCG_STATUS 0x17a
#define MCA_MSR_MCG_CTL 0x17b
//
// Control, Status, Address, and Misc register address for
// bank 0. Other bank registers are at a stride of MCA_NUM_REGS
// from corresponding bank 0 register.
//
#define MCA_NUM_REGS 4
#define MCA_MSR_MC0_CTL 0x400
#define MCA_MSR_MC0_STATUS 0x401
#define MCA_MSR_MC0_ADDR 0x402
#define MCA_MSR_MC0_MISC 0x403
//
// Flags used to determine if the MCE or MCA feature is
// available. Used with HalpFeatureBits.
//
#define HAL_MCA_PRESENT 0x4
#define HAL_MCE_PRESENT 0x8
//
// Flags to decode errors in MCI_STATUS register of MCA banks
//
#define MCA_EC_NO_ERROR 0x0000
#define MCA_EC_UNCLASSIFIED 0x0001
#define MCA_EC_ROMPARITY 0x0002
#define MCA_EC_EXTERN 0x0003
#define MCA_EC_FRC 0x0004
#include "pshpack1.h"
//
// Global Machine Check Capability Register
//
typedef struct _MCA_MCG_CAPABILITY {
union {
struct {
ULONG McaCnt:8;
ULONG McaCntlPresent:1;
ULONG Reserved_1: 23;
ULONG Reserved_2;
} hw;
ULONGLONG QuadPart;
} u;
} MCA_MCG_CAPABILITY, *PMCA_MCG_CAPABILITY;
//
// Global Machine Check Status Register
//
typedef struct _MCA_MCG_STATUS {
union {
struct {
ULONG RestartIPValid:1;
ULONG ErrorIPValid:1;
ULONG McCheckInProgress:1;
ULONG Reserved_1:29;
ULONG Reserved_2;
} hw;
ULONGLONG QuadPart;
} u;
} MCA_MCG_STATUS, *PMCA_MCG_STATUS;
//
// MCA COD field in status register for interpreting errors
//
typedef struct _MCA_COD {
union {
struct {
USHORT Level:2;
USHORT Type:2;
USHORT Request:4;
USHORT BusErrInfo:4;
USHORT Other:4;
} hw;
USHORT ShortPart;
} u;
} MCA_COD, *PMCA_COD;
//
// STATUS register for each MCA bank.
//
typedef struct _MCA_MCI_STATUS {
union {
struct {
MCA_COD McaCod;
USHORT MsCod;
ULONG OtherInfo:25;
ULONG Damage:1;
ULONG AddressValid:1;
ULONG MiscValid:1;
ULONG Enabled:1;
ULONG UnCorrected:1;
ULONG OverFlow:1;
ULONG Valid:1;
} hw;
ULONGLONG QuadPart;
} u;
} MCA_MCI_STATUS, *PMCA_MCI_STATUS;
//
// ADDR register for each MCA bank
//
typedef struct _MCA_MCI_ADDR{
union {
struct {
ULONG Address;
ULONG Reserved;
} hw;
ULONGLONG QuadPart;
} u;
} MCA_MCI_ADDR, *PMCA_MCI_ADDR;
#include "poppack.h"
//
// Machine Check Error Description
//
// Any Reserved/Generic entry
CHAR Reserved[] = "Reserved";
CHAR Generic[] = "Generic";
// Transaction Types
CHAR TransInstruction[] = "Instruction";
CHAR TransData[] = "Data";
static CHAR *TransType[] = {TransInstruction,
TransData,
Generic,
Reserved
};
// Level Encodings
CHAR Level0[] = "Level 0";
CHAR Level1[] = "Level 1";
CHAR Level2[] = "Level 2";
static CHAR *Level[] = {
Level0,
Level1,
Level2,
Generic
};
// Request Encodings
CHAR ReqGenericRead[] = "Generic Read";
CHAR ReqGenericWrite[] = "Generic Write";
CHAR ReqDataRead[] = "Data Read";
CHAR ReqDataWrite[] = "Data Write";
CHAR ReqInstrFetch[] = "Instruction Fetch";
CHAR ReqPrefetch[] = "Prefetch";
CHAR ReqEviction[] = "Eviction";
CHAR ReqSnoop[] = "Snoop";
static CHAR *Request[] = {
Generic,
ReqGenericRead,
ReqGenericWrite,
ReqDataRead,
ReqDataWrite,
ReqInstrFetch,
ReqPrefetch,
ReqEviction,
ReqSnoop,
Reserved,
Reserved,
Reserved,
Reserved,
Reserved,
Reserved,
Reserved
};
// Memory Hierarchy Error Encodings
CHAR MemHierMemAccess[] = "Memory Access";
CHAR MemHierIO[] = "I/O";
CHAR MemHierOther[] = "Other Transaction";
static CHAR *MemoryHierarchy[] = {
MemHierMemAccess,
Reserved,
MemHierIO,
MemHierOther
};
// Time Out Status
CHAR TimeOut[] = "Timed Out";
CHAR NoTimeOut[] = "Did Not Time Out";
static CHAR *TimeOutCode[] = {
NoTimeOut,
TimeOut
};
// Participation Status
CHAR PartSource[] = "Source";
CHAR PartResponds[] = "Responds";
CHAR PartObserver[] = "Observer";
static CHAR *ParticipCode[] = {
PartSource,
PartResponds,
PartObserver,
Generic
};
VOID
DecodeError (
IN MCA_MCI_STATUS MciStatus
)
/*++
Routine Description:
Decode the machine check error logged to the status register
Model specific errors are not decoded.
Arguments:
MciStatus: Contents of Machine Check Status register
Return Value:
None
--*/
{
MCA_COD McaCod;
McaCod = MciStatus.u.hw.McaCod;
//
// Decode Errors: First identify simple errors and then
// handle compound errors as default case
//
switch(McaCod.u.ShortPart) {
case MCA_EC_NO_ERROR:
dprintf("\t\tNo Error\n");
break;
case MCA_EC_UNCLASSIFIED:
dprintf("\t\tUnclassified Error\n");
break;
case MCA_EC_ROMPARITY:
dprintf("\t\tMicrocode ROM Parity Error\n");
break;
case MCA_EC_EXTERN:
dprintf("\t\tExternal Error\n");
break;
case MCA_EC_FRC:
dprintf("\t\tFRC Error\n");
break;
default: // check for complex error conditions
if (McaCod.u.hw.BusErrInfo == 0x4) {
dprintf("\t\tInternal Unclassified Error\n");
} else if (McaCod.u.hw.BusErrInfo == 0) {
// TLB Unit Error
dprintf("\t\t%s TLB %s Error\n",
TransType[McaCod.u.hw.Type],
Level[McaCod.u.hw.Level]);
} else if (McaCod.u.hw.BusErrInfo == 1) {
// Memory Unit Error
dprintf("\t\t%s Cache %s %s Error\n",
TransType[McaCod.u.hw.Type],
Level[McaCod.u.hw.Level],
Request[McaCod.u.hw.Request]);
} else if (McaCod.u.hw.BusErrInfo >= 8) {
// Bus/Interconnect Error
dprintf("\t\tBus %s, Local Processor: %s, %s Error\n",
Level[McaCod.u.hw.Level],
ParticipCode[((McaCod.u.hw.BusErrInfo & 0x6)>>1)],
Request[McaCod.u.hw.Request]);
dprintf("%s Request %s\n",
MemoryHierarchy[McaCod.u.hw.Type],
TimeOutCode[McaCod.u.hw.BusErrInfo & 0x1]);
} else {
dprintf("\t\tUnresolved compound error code\n");
}
break;
}
}
DECLARE_API( mca )
/*++
Routine Description:
Dumps processors machine check architecture registers
and interprets any logged errors
Arguments:
args - none
Return Value:
None
--*/
{
MCA_MCG_CAPABILITY Capabilities;
MCA_MCG_STATUS McgStatus;
MCA_MCI_STATUS MciStatus;
MCA_MCI_ADDR MciAddress;
ULONGLONG MciControl;
ULONGLONG MciMisc;
ULONG Index,i;
PUCHAR p;
ULONG FeatureBits;
ULONG Cr4Value;
BOOLEAN Cr4MCEnabled = FALSE;
ULONGLONG MachineCheckAddress, MachineCheckType;
//
// Quick sanity check for Machine Check availability.
// Support included for both Pentium Style MCE and Pentium
// Pro Style MCA.
//
i = 0;
sscanf(args,"%lX",&i);
if (i != 1) {
i = (ULONG) GetExpression("hal!HalpFeatureBits");
if (!i) {
dprintf ("HalpFeatureBits not found\n");
return;
}
FeatureBits = 0;
ReadMemory(i, &FeatureBits, sizeof(i), &i);
if (FeatureBits == -1 ||
(!(FeatureBits & HAL_MCA_PRESENT) &&
!(FeatureBits & HAL_MCE_PRESENT))) {
dprintf ("Machine Check feature not present\n");
return;
}
}
//
// Read cr4 to determine if CR4.MCE is enabled.
// This enables the Machine Check exception reporting
//
Cr4Value = GetExpression("@Cr4");
if (Cr4Value & CR4_MCE) {
Cr4MCEnabled = TRUE;
}
if (FeatureBits & HAL_MCE_PRESENT) {
// Read P5_MC_ADDR Register and P5_MC_TYPE Register
ReadMsr(MCE_MSR_MC_ADDR, &MachineCheckAddress);
ReadMsr(MCE_MSR_MC_TYPE, &MachineCheckType);
dprintf ("MCE: %s, Cycle Address: 0x%.8x%.8x, Type: 0x%.8x%.8x\n\n",
(Cr4MCEnabled ? "Enabled" : "Disabled"),
(ULONG)(MachineCheckAddress >> 32),
(ULONG)(MachineCheckAddress),
(ULONG)(MachineCheckType >> 32),
(ULONG)(MachineCheckType));
}
if (FeatureBits & HAL_MCA_PRESENT) {
//
// Dump MCA registers
//
ReadMsr(MCA_MSR_MCG_CAP, &Capabilities.u.QuadPart);
ReadMsr(MCA_MSR_MCG_STATUS, &McgStatus.u.QuadPart);
dprintf ("MCA: %s, Banks %d, Control Reg: %s, Machine Check: %s.\n",
(Cr4MCEnabled ? "Enabled" : "Disabled"),
Capabilities.u.hw.McaCnt,
Capabilities.u.hw.McaCntlPresent ? "Supported" : "Not Supported",
McgStatus.u.hw.McCheckInProgress ? "In Progress" : "None"
);
if (McgStatus.u.hw.McCheckInProgress && McgStatus.u.hw.ErrorIPValid) {
dprintf ("MCA: Error IP Valid\n");
}
if (McgStatus.u.hw.McCheckInProgress && McgStatus.u.hw.RestartIPValid) {
dprintf ("MCA: Restart IP Valid\n");
}
//
// Scan all the banks to check if any machines checks have been
// logged and decode the errors if any.
//
dprintf ("Bank Error Control Register Status Register\n");
for (Index=0; Index < (ULONG) Capabilities.u.hw.McaCnt; Index++) {
ReadMsr(MCA_MSR_MC0_CTL+MCA_NUM_REGS*Index, &MciControl);
ReadMsr(MCA_MSR_MC0_STATUS+MCA_NUM_REGS*Index, &MciStatus.u.QuadPart);
dprintf (" %2d. %s 0x%.8x%.8x 0x%.8x%.8x\n",
Index,
(MciStatus.u.hw.Valid ? "Valid" : "None "),
(ULONG) (MciControl >> 32),
(ULONG) (MciControl),
(ULONG) (MciStatus.u.QuadPart>>32),
(ULONG) (MciStatus.u.QuadPart)
);
if (MciStatus.u.hw.Valid) {
DecodeError(MciStatus);
}
if (MciStatus.u.hw.AddressValid) {
ReadMsr(MCA_MSR_MC0_ADDR+MCA_NUM_REGS*Index, &MciAddress.u.QuadPart);
dprintf ("\t\tAddress Reg 0x%.8x%.8x ",
(ULONG) (MciAddress.u.QuadPart>>32),
(ULONG) (MciAddress.u.QuadPart)
);
}
if (MciStatus.u.hw.MiscValid) {
ReadMsr(MCA_MSR_MC0_MISC+MCA_NUM_REGS*Index, &MciMisc);
dprintf ("\t\tMisc Reg 0x%.8x%.8x ",
(ULONG) (MciMisc >> 32),
(ULONG) (MciMisc)
);
}
dprintf("\n");
}
}
}