/////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: AcpiTables.cs // // Note: // Pages of 111-121 ACPI 3.0 Spec. namespace Microsoft.Singularity.Hal.Acpi { using System; using System.Collections; using System.Diagnostics; using Microsoft.Singularity.Io; public struct MadtFlags { public const uint PCAT_COMPAT_FLAG = 0x01; } public class Madt { public const string Signature = "APIC"; private IoMemory region; private SystemTableHeader header; uint localApicAddress; uint flags; // Values per MadtFlags private Madt(IoMemory region, SystemTableHeader header) { this.region = region; this.header = header; localApicAddress = region.Read32(0); flags = region.Read32(4); // XXX Just for debugging GetLocalApics(); GetIoApics(); GetInterruptSourceOverrides(); GetNmis(); GetApicNmis(); GetLocalApicAddressOverrides(); GetIoSApics(); GetLocalSApics(); GetPlatformInterruptSources(); } /////////////////////////////////////////////////////////////////////// // Structure and method to get MADT table items generically private delegate object ItemCreateDelegate(IoMemory mem, int offset); private ArrayList GetStructures(byte typeId, ItemCreateDelegate createMethod) { ArrayList l = new ArrayList(); int offset = 8; while (offset < region.Length) { if (region.Read8(offset) == typeId) { object entry = createMethod(region, offset); if (entry != null) { l.Add(entry); } } offset += region.Read8(offset + 1); } return l; } /////////////////////////////////////////////////////////////////////// // Methods to get MADT items of particular types public ArrayList GetLocalApics() { return GetStructures(LocalApic.TypeId, new ItemCreateDelegate(LocalApic.Create)); } public ArrayList GetIoApics() { return GetStructures(IoApic.TypeId, new ItemCreateDelegate(IoApic.Create)); } public ArrayList GetInterruptSourceOverrides() { return GetStructures(InterruptSourceOverride.TypeId, new ItemCreateDelegate(InterruptSourceOverride.Create)); } public ArrayList GetNmis() { return GetStructures(Nmi.TypeId, new ItemCreateDelegate(Nmi.Create)); } public ArrayList GetApicNmis() { return GetStructures(ApicNmi.TypeId, new ItemCreateDelegate(ApicNmi.Create)); } public ArrayList GetLocalApicAddressOverrides() { return GetStructures(LocalApicAddressOverride.TypeId, new ItemCreateDelegate(LocalApicAddressOverride.Create)); } public ArrayList GetIoSApics() { return GetStructures(IoSApic.TypeId, new ItemCreateDelegate(IoSApic.Create)); } public ArrayList GetLocalSApics() { return GetStructures(LocalSApic.TypeId, new ItemCreateDelegate(LocalSApic.Create)); } public ArrayList GetPlatformInterruptSources() { return GetStructures(PlatformInterruptSource.TypeId, new ItemCreateDelegate(PlatformInterruptSource.Create)); } /////////////////////////////////////////////////////////////////////// // internal static Madt Create(SystemTableHeader header) { IoMemory region = IoMemory.MapPhysicalMemory(header.PostHeaderAddress, header.PostHeaderLength, true, false); int sum = (header.Checksum + AcpiChecksum.Compute(region)) & 0xff; if (sum != 0) { return null; } return new Madt(region, header); } } /////////////////////////////////////////////////////////////////////////// // MADT APIC Structure Constants public struct ApicFlags { public const uint Enabled = 0x01; } public struct MpsIntiFlags { public const ushort PolarityBus = 0; public const ushort PolarityActiveHigh = 1; public const ushort PolarityActiveLow = 3; public const ushort PolarityMask = 3; public const ushort TriggerBus = 0; public const ushort TriggerEdge = 4; public const ushort TriggerLevel = 6; public const ushort TriggerMask = 6; } public struct PlatformInterruptType { public const uint PMI = 1; public const uint INIT = 2; public const uint CorrectedPlatformErrorInterrupt = 3; } public struct PlatformInterruptSourceFlags { public const uint CpeiProcessorOverride = 1; } /////////////////////////////////////////////////////////////////////////// // MADT APIC Structures public class LocalApic { internal const byte TypeId = 0x00; internal const byte Length = 8; public byte AcpiProcessorId; public byte ApicId; public uint Flags; // Values per ApicFlags internal LocalApic(IoMemory region, int offset) { Debug.Assert(region.Read8(offset + 0) == TypeId); Debug.Assert(region.Read8(offset + 1) == Length); AcpiProcessorId = region.Read8(offset + 2); ApicId = region.Read8(offset + 3); Flags = region.Read32(offset + 4); // DebugStub.Print("{0:x4}:{1:x4} type {2:x1} AcpiProcId {3:x2} ApicId {4:x2} Flags {5:x8} (LocalApic)\n", __arglist(offset, offset + Length, TypeId, AcpiProcessorId, ApicId, Flags)); } internal static object Create(IoMemory region, int offset) { LocalApic entry = new LocalApic(region, offset); // Only return usable entries return ((entry.Flags & 1) == 1 ? entry : null); } } public class IoApic { internal const byte TypeId = 0x01; internal const byte Length = 12; public byte Id; public uint Address; public uint InterruptBase; internal IoApic(IoMemory region, int offset) { Debug.Assert(region.Read8(offset + 0) == TypeId); Debug.Assert(region.Read8(offset + 1) == Length); Id = region.Read8(offset + 2); // reserved = region.Read8(offset + 3); Address = region.Read32(offset + 4); InterruptBase = region.Read32(offset + 8); // DebugStub.Print("{0:x4}:{1:x4} type {2:x1} Id {3:x2} Address {4:x8} InterruptBase {5:x8} (IoApic)\n", __arglist(offset, offset + Length, TypeId, Id, Address, InterruptBase)); } internal static object Create(IoMemory region, int offset) { return new IoApic(region, offset); } } public class InterruptSourceOverride { internal const byte TypeId = 0x02; internal const byte Length = 10; public byte Bus; public byte Source; public uint GlobalSystemInterrupt; public ushort Flags; // Values per MpsIntiFlags internal InterruptSourceOverride(IoMemory region, int offset) { Debug.Assert(region.Read8(offset + 0) == TypeId); Debug.Assert(region.Read8(offset + 1) == Length); Bus = region.Read8(offset + 2); Source = region.Read8(offset + 3); GlobalSystemInterrupt = region.Read32(offset + 4); Flags = region.Read16(offset + 8); // DebugStub.Print("{0:x4}:{1:x4} type {2:x1} Bus {3:x2} Source {4:x2} GlobalSystemInterrupt {5:x8} Flags {6:x2} (InterruptSourceOverride)\n", __arglist(offset, offset + Length, TypeId, Bus, Source, GlobalSystemInterrupt, Flags)); } internal static object Create(IoMemory region, int offset) { return new InterruptSourceOverride(region, offset); } } public class Nmi { internal const byte TypeId = 0x03; internal const byte Length = 8; public ushort Flags; // Values per MpsIntiFlags public uint GlobalSystemInterrupt; internal Nmi(IoMemory region, int offset) { Debug.Assert(region.Read8(offset + 0) == TypeId); Debug.Assert(region.Read8(offset + 1) == Length); Flags = region.Read16(offset + 2); GlobalSystemInterrupt = region.Read32(offset + 4); // DebugStub.Print("{0:x4}:{1:x4} type {2:x1} Flags {3:x2} GlobalSystemInterrupt {4:x8} (Nmi)\n", __arglist(offset, offset + Length, TypeId, Flags, GlobalSystemInterrupt)); } internal static object Create(IoMemory region, int offset) { return new Nmi(region, offset); } } public class ApicNmi { internal const byte TypeId = 0x04; internal const byte Length = 6; public byte AcpiProcessorId; public ushort Flags; // Values per MpsIntiFlags public byte LocalApicLint; internal ApicNmi(IoMemory region, int offset) { Debug.Assert(region.Read8(offset + 0) == TypeId); Debug.Assert(region.Read8(offset + 1) == Length); AcpiProcessorId = region.Read8(offset + 2); Flags = region.Read16(offset + 3); LocalApicLint = region.Read8(offset + 5); // DebugStub.Print("{0:x4}:{1:x4} type {2:x1} ApicProcessorId {3:x2} Flags {4:x4} LocalApicLint {5:x2} (ApicNmi)\n", __arglist(offset, offset + Length, TypeId, AcpiProcessorId, Flags, LocalApicLint)); } internal static object Create(IoMemory region, int offset) { return new ApicNmi(region, offset); } } public class LocalApicAddressOverride { internal const byte TypeId = 0x05; internal const byte Length = 12; ulong LocalApicAddress; internal LocalApicAddressOverride(IoMemory region, int offset) { Debug.Assert(region.Read8(offset + 0) == TypeId); Debug.Assert(region.Read8(offset + 1) == Length); // reserved = region.Read16(offset + 2); LocalApicAddress = region.Read64(offset + 4); // DebugStub.Print("{0:x04}:{1:x04} type {2:x01} LocalApicAddress {3:x016} (LocalApicAddressOverride)\n", __arglist(offset, offset + Length, TypeId, LocalApicAddress)); } internal static object Create(IoMemory region, int offset) { return new LocalApicAddressOverride(region, offset); } } public class IoSApic { internal const byte TypeId = 0x6; internal const byte Length = 16; internal byte Id; internal uint InterruptBase; internal ulong Address; internal IoSApic(IoMemory region, int offset) { Debug.Assert(region.Read8(offset + 0) == TypeId); Debug.Assert(region.Read8(offset + 1) == Length); Id = region.Read8(offset + 2); // reserved = region.Read8(offset + 3); InterruptBase = region.Read32(offset + 4); Address = region.Read64(offset + 8); // DebugStub.Print("{0:x04}:{1:x04} type {2:x01} Id {3:x02} InterruptBase {4:x04} Address {5:x016} (IoSApic)\n", __arglist(offset, offset + Length, TypeId, Id, InterruptBase, Address)); } internal static object Create(IoMemory region, int offset) { return new IoSApic(region, offset); } } public class LocalSApic { internal const byte TypeId = 0x07; internal const byte MinLength = 17; public byte AcpiProcessorId; public byte LocalSApicId; public byte LocalSApicEid; public uint Flags; // Values per ApicFlags public uint AcpiProcessorUidValue; public string AcpiProcessorUidString; internal LocalSApic(IoMemory region, int offset) { Debug.Assert(region.Read8(offset + 0) == TypeId); byte length = region.Read8(offset + 1); Debug.Assert(length >= MinLength); AcpiProcessorId = region.Read8(offset + 2); LocalSApicId = region.Read8(offset + 3); LocalSApicEid = region.Read8(offset + 4); // reserved = region.Read24(offset + 5); Flags = region.Read32(offset + 8); AcpiProcessorUidValue = region.Read32(offset + 12) ; AcpiProcessorUidString = region.ReadString(offset + 16, (int)length - 17); // DebugStub.Print("{0:x04}:{1:x04} type {2:x01} AcpiProcId {3:x02} LocalSApicId {4:x02} LocalSApicEid {5:x02} Flags {6:x08} AcpiProcUid {7:x04} AcpiProcUid \"{8}\" (LocalSApic)\n", __arglist(offset, offset + length, TypeId, AcpiProcessorId, LocalSApicId, LocalSApicEid, Flags, AcpiProcessorUidValue, AcpiProcessorUidString)); } internal static object Create(IoMemory region, int offset) { return new LocalSApic(region, offset); } } public class PlatformInterruptSource { internal const byte TypeId = 0x8; internal const byte Length = 16; public ushort Flags; // Values per MpsIntiFlags public byte InterruptType; // PlatformInterruptType public byte ProcessorId; public byte ProcessorEid; public byte IoSApicVector; public uint GlobalSystemInterrupt; public uint SourceFlags; // PlatformInterruptSourceFlags internal PlatformInterruptSource(IoMemory region, int offset) { Debug.Assert(region.Read8(offset + 0) == TypeId); Debug.Assert(region.Read8(offset + 1) == Length); Flags = region.Read16(offset + 2); InterruptType = region.Read8(offset + 4); ProcessorId = region.Read8(offset + 5); ProcessorEid = region.Read8(offset + 6); IoSApicVector = region.Read8(offset + 7); GlobalSystemInterrupt = region.Read32(offset + 8); SourceFlags = region.Read32(offset + 12); // DebugStub.Print("{0:x04}:{1:x04} type {2:x01} Flags {3:x04} InterruptType {4:x02} ProcessorId {5:x02} ProcessorEid {6:x02} IoSApicVector {7:x02} GlobalSystemInterrupt {8:x04} SourceFlags {9:x04} (PlatformInterruptSource)\n", __arglist(offset, offset + Length, TypeId, Flags, InterruptType, ProcessorId, ProcessorEid, IoSApicVector, GlobalSystemInterrupt, SourceFlags)); } internal static object Create(IoMemory region, int offset) { return new PlatformInterruptSource(region, offset); } } }