461 lines
16 KiB
C#
461 lines
16 KiB
C#
///////////////////////////////////////////////////////////////////////////////
|
||
//
|
||
// 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);
|
||
}
|
||
}
|
||
|
||
}
|