]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: generate full MADT dynamically, synchronize contents with qemu
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 13 Aug 2012 15:42:07 +0000 (15:42 +0000)
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 13 Aug 2012 15:42:07 +0000 (15:42 +0000)
Represent the set of possible PCI link target IRQs with
Pcd8259LegacyModeEdgeLevel. This ensures that the 8259 Interrupt
Controller code in PcAtChipsetPkg will treat them as level-triggered too.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13628 6f19259b-4bc3-4df7-8a09-765794883524

OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
OvmfPkg/AcpiPlatformDxe/Qemu.c
OvmfPkg/AcpiTables/Madt.aslc
OvmfPkg/AcpiTables/Platform.h
OvmfPkg/OvmfPkgIa32.dsc
OvmfPkg/OvmfPkgIa32X64.dsc
OvmfPkg/OvmfPkgX64.dsc

index 04eb495cac8e71020da98b5ad2c75331afc1d7d5..acc224728e9b059618cf3a9b3b35512d055d4679 100644 (file)
@@ -35,6 +35,8 @@
   MdePkg/MdePkg.dec\r
   MdeModulePkg/MdeModulePkg.dec\r
   OvmfPkg/OvmfPkg.dec\r
+  UefiCpuPkg/UefiCpuPkg.dec\r
+  PcAtChipsetPkg/PcAtChipsetPkg.dec\r
 \r
 [LibraryClasses]\r
   UefiLib\r
@@ -58,6 +60,8 @@
 \r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile\r
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress\r
+  gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel\r
 \r
 [Depex]\r
   gEfiAcpiTableProtocolGuid\r
index 4c88c32ec8ae26b21dcea3a651f258aa2fd2dd74..1ac443f3f26990d51a13d53dc0296ca06c0dfe81 100644 (file)
@@ -17,7 +17,8 @@
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/QemuFwCfgLib.h>\r
 #include <Library/DxeServicesTableLib.h>\r
-\r
+#include <Library/PcdLib.h>\r
+#include <IndustryStandard/Acpi.h>\r
 \r
 BOOLEAN\r
 QemuDetected (\r
@@ -32,6 +33,27 @@ QemuDetected (
 }\r
 \r
 \r
+STATIC\r
+UINTN\r
+CountBits16 (\r
+  UINT16 Mask\r
+  )\r
+{\r
+  //\r
+  // For all N >= 1, N bits are enough to represent the number of bits set\r
+  // among N bits. It's true for N == 1. When adding a new bit (N := N+1),\r
+  // the maximum number of possibly set bits increases by one, while the\r
+  // representable maximum doubles.\r
+  //\r
+  Mask = ((Mask & 0xAAAA) >> 1) + (Mask & 0x5555);\r
+  Mask = ((Mask & 0xCCCC) >> 2) + (Mask & 0x3333);\r
+  Mask = ((Mask & 0xF0F0) >> 4) + (Mask & 0x0F0F);\r
+  Mask = ((Mask & 0xFF00) >> 8) + (Mask & 0x00FF);\r
+\r
+  return Mask;\r
+}\r
+\r
+\r
 STATIC\r
 EFI_STATUS\r
 EFIAPI\r
@@ -42,58 +64,120 @@ QemuInstallAcpiMadtTable (
   OUT  UINTN                         *TableKey\r
   )\r
 {\r
-  EFI_STATUS                                   Status;\r
-  UINTN                                        Count;\r
-  UINTN                                        Loop;\r
-  EFI_ACPI_DESCRIPTION_HEADER                  *Hdr;\r
-  UINTN                                        NewBufferSize;\r
-  EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE  *LocalApic;\r
+  UINTN                                               CpuCount;\r
+  UINTN                                               PciLinkIsoCount;\r
+  UINTN                                               NewBufferSize;\r
+  EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt;\r
+  EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE         *LocalApic;\r
+  EFI_ACPI_1_0_IO_APIC_STRUCTURE                      *IoApic;\r
+  EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE    *Iso;\r
+  EFI_ACPI_1_0_LOCAL_APIC_NMI_STRUCTURE               *LocalApicNmi;\r
+  VOID                                                *Ptr;\r
+  UINTN                                               Loop;\r
+  EFI_STATUS                                          Status;\r
+\r
+  ASSERT (AcpiTableBufferSize >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));\r
 \r
   QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount);\r
-  Count = (UINTN) QemuFwCfgRead16 ();\r
-  ASSERT (Count >= 1);\r
-\r
-  if (Count == 1) {\r
-    //\r
-    // The pre-built MADT table covers the single CPU case\r
-    //\r
-    return InstallAcpiTable (\r
-             AcpiProtocol,\r
-             AcpiTableBuffer,\r
-             AcpiTableBufferSize,\r
-             TableKey\r
-             );\r
-  }\r
+  CpuCount = QemuFwCfgRead16 ();\r
+  ASSERT (CpuCount >= 1);\r
 \r
   //\r
-  // We need to add additional Local APIC entries to the MADT\r
+  // Set Level-tiggered, Active High for these identity mapped IRQs. The bitset\r
+  // corresponds to the union of all possible interrupt assignments for the LNKA,\r
+  // LNKB, LNKC, LNKD PCI interrupt lines. See the DSDT.\r
   //\r
-  NewBufferSize = AcpiTableBufferSize + ((Count - 1) * sizeof (*LocalApic));\r
-  Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AllocatePool (NewBufferSize);\r
-  ASSERT (Hdr != NULL);\r
+  PciLinkIsoCount = CountBits16 (PcdGet16 (Pcd8259LegacyModeEdgeLevel));\r
+\r
+  NewBufferSize = 1                     * sizeof (*Madt) +\r
+                  CpuCount              * sizeof (*LocalApic) +\r
+                  1                     * sizeof (*IoApic) +\r
+                  (1 + PciLinkIsoCount) * sizeof (*Iso) +\r
+                  1                     * sizeof (*LocalApicNmi);\r
 \r
-  CopyMem (Hdr, AcpiTableBuffer, AcpiTableBufferSize);\r
+  Madt = AllocatePool (NewBufferSize);\r
+  if (Madt == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Madt->Header           = *(EFI_ACPI_DESCRIPTION_HEADER *) AcpiTableBuffer;\r
+  Madt->Header.Length    = NewBufferSize;\r
+  Madt->LocalApicAddress = PcdGet32 (PcdCpuLocalApicBaseAddress);\r
+  Madt->Flags            = EFI_ACPI_1_0_PCAT_COMPAT;\r
+  Ptr = Madt + 1;\r
+\r
+  LocalApic = Ptr;\r
+  for (Loop = 0; Loop < CpuCount; ++Loop) {\r
+    LocalApic->Type            = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC;\r
+    LocalApic->Length          = sizeof (*LocalApic);\r
+    LocalApic->AcpiProcessorId = Loop;\r
+    LocalApic->ApicId          = Loop;\r
+    LocalApic->Flags           = 1; // enabled\r
+    ++LocalApic;\r
+  }\r
+  Ptr = LocalApic;\r
 \r
-  LocalApic = (EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE*)\r
-                (((UINT8*) Hdr) + AcpiTableBufferSize);\r
+  IoApic = Ptr;\r
+  IoApic->Type             = EFI_ACPI_1_0_IO_APIC;\r
+  IoApic->Length           = sizeof (*IoApic);\r
+  IoApic->IoApicId         = CpuCount;\r
+  IoApic->Reserved         = EFI_ACPI_RESERVED_BYTE;\r
+  IoApic->IoApicAddress    = 0xFEC00000;\r
+  IoApic->SystemVectorBase = 0x00000000;\r
+  Ptr = IoApic + 1;\r
 \r
   //\r
-  // Add Local APIC entries for the APs to the MADT\r
+  // IRQ0 (8254 Timer) => IRQ2 (PIC) Interrupt Source Override Structure\r
   //\r
-  for (Loop = 1; Loop < Count; Loop++) {\r
-    LocalApic->Type = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC;\r
-    LocalApic->Length = sizeof (*LocalApic);\r
-    LocalApic->AcpiProcessorId = (UINT8) Loop;\r
-    LocalApic->ApicId = (UINT8) Loop;\r
-    LocalApic->Flags = 1;\r
-    LocalApic++;\r
-  }\r
+  Iso = Ptr;\r
+  Iso->Type                        = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE;\r
+  Iso->Length                      = sizeof (*Iso);\r
+  Iso->Bus                         = 0x00; // ISA\r
+  Iso->Source                      = 0x00; // IRQ0\r
+  Iso->GlobalSystemInterruptVector = 0x00000002;\r
+  Iso->Flags                       = 0x0000; // Conforms to specs of the bus\r
+  ++Iso;\r
 \r
-  Hdr->Length = (UINT32) NewBufferSize;\r
+  //\r
+  // Set Level-tiggered, Active High for all possible PCI link targets.\r
+  //\r
+  for (Loop = 0; Loop < 16; ++Loop) {\r
+    if ((PcdGet16 (Pcd8259LegacyModeEdgeLevel) & (1 << Loop)) == 0) {\r
+      continue;\r
+    }\r
+    Iso->Type                        = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE;\r
+    Iso->Length                      = sizeof (*Iso);\r
+    Iso->Bus                         = 0x00; // ISA\r
+    Iso->Source                      = Loop;\r
+    Iso->GlobalSystemInterruptVector = Loop;\r
+    Iso->Flags                       = 0x000D; // Level-tiggered, Active High\r
+    ++Iso;\r
+  }\r
+  ASSERT (\r
+    Iso - (EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *)Ptr ==\r
+      1 + PciLinkIsoCount\r
+    );\r
+  Ptr = Iso;\r
+\r
+  LocalApicNmi = Ptr;\r
+  LocalApicNmi->Type            = EFI_ACPI_1_0_LOCAL_APIC_NMI;\r
+  LocalApicNmi->Length          = sizeof (*LocalApicNmi);\r
+  LocalApicNmi->AcpiProcessorId = 0xFF; // applies to all processors\r
+  //\r
+  // polarity and trigger mode of the APIC I/O input signals conform to the\r
+  // specifications of the bus\r
+  //\r
+  LocalApicNmi->Flags           = 0x0000;\r
+  //\r
+  // Local APIC interrupt input LINTn to which NMI is connected.\r
+  //\r
+  LocalApicNmi->LocalApicInti   = 0x01;\r
+  Ptr = LocalApicNmi + 1;\r
 \r
-  Status = InstallAcpiTable (AcpiProtocol, Hdr, NewBufferSize, TableKey);\r
+  ASSERT ((UINT8 *)Ptr - (UINT8 *)Madt == NewBufferSize);\r
+  Status = InstallAcpiTable (AcpiProtocol, Madt, NewBufferSize, TableKey);\r
 \r
-  FreePool (Hdr);\r
+  FreePool (Madt);\r
 \r
   return Status;\r
 }\r
index f5b71a6e0ca943a590e057d09c87aef96553fbfb..62bf2c7fd223c5f5daf0039e86161dac778113bb 100644 (file)
 **/\r
 \r
 #include <IndustryStandard/Acpi.h>\r
-\r
-//\r
-// MADT Definitions\r
-//\r
-#define EFI_ACPI_OEM_MADT_REVISION 0x00000000 // TBD\r
+#include <Platform.h>\r
 \r
 //\r
 // Local APIC address\r
@@ -74,21 +70,12 @@ EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE Madt = {
   EFI_ACPI_1_0_APIC_SIGNATURE,\r
   sizeof (EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE),\r
   EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,\r
-\r
-  //\r
-  // Checksum will be updated at runtime\r
-  //\r
-  0x00,\r
-\r
-  //\r
-  // It is expected that these values will be programmed at runtime\r
-  //\r
-  ' ', ' ', ' ', ' ', ' ', ' ',\r
-\r
-  0,\r
-  EFI_ACPI_OEM_MADT_REVISION,\r
-  0,\r
-  0,\r
+  0x00,                                                     // Checksum will be updated at runtime\r
+  EFI_ACPI_OEM_ID,\r
+  EFI_ACPI_OEM_TABLE_ID,\r
+  EFI_ACPI_OEM_REVISION,\r
+  EFI_ACPI_CREATOR_ID,\r
+  EFI_ACPI_CREATOR_REVISION,\r
 \r
   //\r
   // MADT specific fields\r
index 4b03897614a8d209a13ed4122e29f855c586d69a..e8fae3c83937ba445471e09ed9dcc55891b1f06f 100644 (file)
@@ -23,9 +23,9 @@
 //\r
 #define EFI_ACPI_OEM_ID           'O','V','M','F',' ',' '   // OEMID 6 bytes long\r
 #define EFI_ACPI_OEM_TABLE_ID     SIGNATURE_64('O','V','M','F','E','D','K','2') // OEM table id 8 bytes long\r
-#define EFI_ACPI_OEM_REVISION     0x02000820\r
+#define EFI_ACPI_OEM_REVISION     0x20120804\r
 #define EFI_ACPI_CREATOR_ID       SIGNATURE_32('O','V','M','F')\r
-#define EFI_ACPI_CREATOR_REVISION 0x00000097\r
+#define EFI_ACPI_CREATOR_REVISION 0x00000098\r
 \r
 #define INT_MODEL       0x01\r
 #define SCI_INT_VECTOR  0x0009\r
index ffedcbf6de46e584a2b6bdaaa16cee6167f6e751..453a5788cb43062fa2adc45b354ae6467199d580 100644 (file)
 !endif\r
 !endif\r
 \r
+  # IRQs 5, 9, 10, 11 are level-triggered\r
+  gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0E20\r
+\r
 !if $(SECURE_BOOT_ENABLE) == TRUE\r
   # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot\r
   gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x05\r
index 123ac31e01ea14b844e01962f459320b16faff18..73e8c987b5e3ec594260cc3f07a3fb2f4178cb93 100644 (file)
 !endif\r
 !endif\r
 \r
+  # IRQs 5, 9, 10, 11 are level-triggered\r
+  gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0E20\r
+\r
 [PcdsFixedAtBuild.X64]\r
 !if $(SECURE_BOOT_ENABLE) == TRUE\r
   # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot\r
index 1fce7a7e8ce72b5b4b60f5553cc9cc54901a7e03..1c2aec0cdc8d32fea2e13795b34f383b720b93bd 100644 (file)
 !endif\r
 !endif\r
 \r
+  # IRQs 5, 9, 10, 11 are level-triggered\r
+  gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0E20\r
+\r
 !if $(SECURE_BOOT_ENABLE) == TRUE\r
   # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot\r
   gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x05\r