///////////////////////////////////////////////////////////////////////////// // // apic.cpp - Extension to inspect APIC // // Copyright Microsoft Corporation. All rights reserved. // #include "singx86.h" inline static ULONG ApicRead32(const BYTE* apic, int offsetInBytes) { return ((ULONG*) apic)[offsetInBytes / sizeof(ULONG)]; } inline static BYTE ApicRead8(const BYTE* apic, int offsetInBytes) { return apic[offsetInBytes]; } inline static const char* TimerMode(ULONG flag) { return (flag == 0) ? "One-shot" : "Periodic"; } inline static const char* Mask(ULONG flag) { return (flag == 0) ? "Unmasked" : "Masked "; } inline static const char* TriggerMode(ULONG pmask, ULONG flag) { if ((pmask & (1 << 15)) == 0) return "-----"; return (flag == 0) ? "Edge " : "Level"; } inline static const char* RemoteIRR(ULONG pmask, ULONG flag) { if ((pmask & (1 << 14)) == 0) return "------"; return (flag == 0) ? "No IRR" : "IRR "; } inline static const char* PinPolarity(ULONG pmask, ULONG flag) { if ((pmask & (1 << 13)) == 0) return "---------"; return (flag == 0) ? "Active-Hi" : "Active-Lo"; } inline static const char* DeliveryStatus(ULONG flag) { return (flag == 0) ? "Idle" : "Pend"; } inline static const char* DeliveryMode(ULONG pmask, ULONG value) { if ((pmask & 0x700) == 0) return "---"; const char * dm[8] = { "Fix", "Res", "SMI", "Res", "NMI", "INI", "Res", "Ext" }; value = (value & 0x700u) >> 8; return dm[value]; } static void DumpTimer(ULONG t) { ExtOut("Timer: %08x => Vector %02x ", t & 0x310ff, t & 0xff); ExtOut("%s %s %s\n", Mask(t & 0x10000), TimerMode(t & 0x20000), DeliveryStatus(t & 0x1000)); } static void DumpLvt(const char* name, ULONG pmask, ULONG value) { ExtOut("%s: %08x => Vector %02x ", name, value & pmask, value & 0xff); ExtOut("%s %s %s %s %s %s\n", Mask(value), TriggerMode(pmask, value), RemoteIRR(pmask, value), PinPolarity(pmask, value), DeliveryStatus(value), DeliveryMode(pmask, value)); } static void DumpBits(const char* name, const BYTE* apic, int startOffset) { ExtOut("%s: ", name); for (int w = 0; w < 8; w++) { ULONG bits = ApicRead32(apic, startOffset + w * 16); for (int i = 0; i < 32; i++) { if ((bits & (1 << i)) != 0) { ExtOut("0x%02x ", w * 32 + i); } } } ExtOut("\n"); } EXT_DECL(apic) // Defines: PDEBUG_CLIENT Client, PCSTR args { EXT_ENTER(); // Defines: HRESULT status = S_OK; UNREFERENCED_PARAMETER(args); static const ULONG64 ApicBase = 0x00000000fee00000; BYTE apic[0x400]; EXT_CHECK(g_ExtData->ReadPhysical(ApicBase, &apic, sizeof(apic), NULL)); int maxLvt = ApicRead8(apic, 0x32); ExtOut("Apic Id %u Version %02x Max LVT %u\n", ApicRead8(apic, 0x23), ApicRead8(apic, 0x30), maxLvt); ExtOut("TPR %08x APR %08x PPR %08x\n", ApicRead32(apic, 0x80), ApicRead32(apic, 0x90), ApicRead32(apic, 0xa0)); ExtOut("Logical Destination %08x Destination Format %08x\n", ApicRead32(apic, 0xd0), ApicRead32(apic, 0xe0)); ExtOut("Spurious Interrupt Vector %08x\n", ApicRead32(apic, 0xf0)); ExtOut("Fault Status %02x\n", ApicRead8(apic, 0x280)); DumpTimer(ApicRead32(apic, 0x320)); DumpLvt("LINT0", 0x1f7ff, ApicRead32(apic, 0x350)); DumpLvt("LINT1", 0x1f7ff, ApicRead32(apic, 0x360)); DumpLvt("Fault", 0x110ff, ApicRead32(apic, 0x370)); if (maxLvt >= 4) DumpLvt("Perf ", 0x117ff, ApicRead32(apic, 0x340)); if (maxLvt >= 5) DumpLvt("Therm", 0x117ff, ApicRead32(apic, 0x343)); DumpBits("ISR", apic, 0x100); DumpBits("IRR", apic, 0x200); DumpBits("TMR", apic, 0x180); EXT_LEAVE(); }