From 498f7d8ddd4f60c8c8226bb6e672be04ab4c18e0 Mon Sep 17 00:00:00 2001 From: jljusten Date: Mon, 13 Aug 2012 15:42:07 +0000 Subject: [PATCH] OvmfPkg: generate full MADT dynamically, synchronize contents with qemu 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 Reviewed-by: Jordan Justen git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13628 6f19259b-4bc3-4df7-8a09-765794883524 --- OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf | 4 + OvmfPkg/AcpiPlatformDxe/Qemu.c | 170 +++++++++++++++----- OvmfPkg/AcpiTables/Madt.aslc | 27 +--- OvmfPkg/AcpiTables/Platform.h | 4 +- OvmfPkg/OvmfPkgIa32.dsc | 3 + OvmfPkg/OvmfPkgIa32X64.dsc | 3 + OvmfPkg/OvmfPkgX64.dsc | 3 + 7 files changed, 149 insertions(+), 65 deletions(-) diff --git a/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf b/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf index 04eb495cac..acc224728e 100644 --- a/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf +++ b/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf @@ -35,6 +35,8 @@ MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec OvmfPkg/OvmfPkg.dec + UefiCpuPkg/UefiCpuPkg.dec + PcAtChipsetPkg/PcAtChipsetPkg.dec [LibraryClasses] UefiLib @@ -58,6 +60,8 @@ [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile + gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress + gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel [Depex] gEfiAcpiTableProtocolGuid diff --git a/OvmfPkg/AcpiPlatformDxe/Qemu.c b/OvmfPkg/AcpiPlatformDxe/Qemu.c index 4c88c32ec8..1ac443f3f2 100644 --- a/OvmfPkg/AcpiPlatformDxe/Qemu.c +++ b/OvmfPkg/AcpiPlatformDxe/Qemu.c @@ -17,7 +17,8 @@ #include #include #include - +#include +#include BOOLEAN QemuDetected ( @@ -32,6 +33,27 @@ QemuDetected ( } +STATIC +UINTN +CountBits16 ( + UINT16 Mask + ) +{ + // + // For all N >= 1, N bits are enough to represent the number of bits set + // among N bits. It's true for N == 1. When adding a new bit (N := N+1), + // the maximum number of possibly set bits increases by one, while the + // representable maximum doubles. + // + Mask = ((Mask & 0xAAAA) >> 1) + (Mask & 0x5555); + Mask = ((Mask & 0xCCCC) >> 2) + (Mask & 0x3333); + Mask = ((Mask & 0xF0F0) >> 4) + (Mask & 0x0F0F); + Mask = ((Mask & 0xFF00) >> 8) + (Mask & 0x00FF); + + return Mask; +} + + STATIC EFI_STATUS EFIAPI @@ -42,58 +64,120 @@ QemuInstallAcpiMadtTable ( OUT UINTN *TableKey ) { - EFI_STATUS Status; - UINTN Count; - UINTN Loop; - EFI_ACPI_DESCRIPTION_HEADER *Hdr; - UINTN NewBufferSize; - EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic; + UINTN CpuCount; + UINTN PciLinkIsoCount; + UINTN NewBufferSize; + EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt; + EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic; + EFI_ACPI_1_0_IO_APIC_STRUCTURE *IoApic; + EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *Iso; + EFI_ACPI_1_0_LOCAL_APIC_NMI_STRUCTURE *LocalApicNmi; + VOID *Ptr; + UINTN Loop; + EFI_STATUS Status; + + ASSERT (AcpiTableBufferSize >= sizeof (EFI_ACPI_DESCRIPTION_HEADER)); QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount); - Count = (UINTN) QemuFwCfgRead16 (); - ASSERT (Count >= 1); + CpuCount = QemuFwCfgRead16 (); + ASSERT (CpuCount >= 1); - if (Count == 1) { - // - // The pre-built MADT table covers the single CPU case - // - return InstallAcpiTable ( - AcpiProtocol, - AcpiTableBuffer, - AcpiTableBufferSize, - TableKey - ); + // + // Set Level-tiggered, Active High for these identity mapped IRQs. The bitset + // corresponds to the union of all possible interrupt assignments for the LNKA, + // LNKB, LNKC, LNKD PCI interrupt lines. See the DSDT. + // + PciLinkIsoCount = CountBits16 (PcdGet16 (Pcd8259LegacyModeEdgeLevel)); + + NewBufferSize = 1 * sizeof (*Madt) + + CpuCount * sizeof (*LocalApic) + + 1 * sizeof (*IoApic) + + (1 + PciLinkIsoCount) * sizeof (*Iso) + + 1 * sizeof (*LocalApicNmi); + + Madt = AllocatePool (NewBufferSize); + if (Madt == NULL) { + return EFI_OUT_OF_RESOURCES; } - // - // We need to add additional Local APIC entries to the MADT - // - NewBufferSize = AcpiTableBufferSize + ((Count - 1) * sizeof (*LocalApic)); - Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AllocatePool (NewBufferSize); - ASSERT (Hdr != NULL); + Madt->Header = *(EFI_ACPI_DESCRIPTION_HEADER *) AcpiTableBuffer; + Madt->Header.Length = NewBufferSize; + Madt->LocalApicAddress = PcdGet32 (PcdCpuLocalApicBaseAddress); + Madt->Flags = EFI_ACPI_1_0_PCAT_COMPAT; + Ptr = Madt + 1; - CopyMem (Hdr, AcpiTableBuffer, AcpiTableBufferSize); - - LocalApic = (EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE*) - (((UINT8*) Hdr) + AcpiTableBufferSize); - - // - // Add Local APIC entries for the APs to the MADT - // - for (Loop = 1; Loop < Count; Loop++) { - LocalApic->Type = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC; - LocalApic->Length = sizeof (*LocalApic); - LocalApic->AcpiProcessorId = (UINT8) Loop; - LocalApic->ApicId = (UINT8) Loop; - LocalApic->Flags = 1; - LocalApic++; + LocalApic = Ptr; + for (Loop = 0; Loop < CpuCount; ++Loop) { + LocalApic->Type = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC; + LocalApic->Length = sizeof (*LocalApic); + LocalApic->AcpiProcessorId = Loop; + LocalApic->ApicId = Loop; + LocalApic->Flags = 1; // enabled + ++LocalApic; } + Ptr = LocalApic; - Hdr->Length = (UINT32) NewBufferSize; + IoApic = Ptr; + IoApic->Type = EFI_ACPI_1_0_IO_APIC; + IoApic->Length = sizeof (*IoApic); + IoApic->IoApicId = CpuCount; + IoApic->Reserved = EFI_ACPI_RESERVED_BYTE; + IoApic->IoApicAddress = 0xFEC00000; + IoApic->SystemVectorBase = 0x00000000; + Ptr = IoApic + 1; - Status = InstallAcpiTable (AcpiProtocol, Hdr, NewBufferSize, TableKey); + // + // IRQ0 (8254 Timer) => IRQ2 (PIC) Interrupt Source Override Structure + // + Iso = Ptr; + Iso->Type = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE; + Iso->Length = sizeof (*Iso); + Iso->Bus = 0x00; // ISA + Iso->Source = 0x00; // IRQ0 + Iso->GlobalSystemInterruptVector = 0x00000002; + Iso->Flags = 0x0000; // Conforms to specs of the bus + ++Iso; - FreePool (Hdr); + // + // Set Level-tiggered, Active High for all possible PCI link targets. + // + for (Loop = 0; Loop < 16; ++Loop) { + if ((PcdGet16 (Pcd8259LegacyModeEdgeLevel) & (1 << Loop)) == 0) { + continue; + } + Iso->Type = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE; + Iso->Length = sizeof (*Iso); + Iso->Bus = 0x00; // ISA + Iso->Source = Loop; + Iso->GlobalSystemInterruptVector = Loop; + Iso->Flags = 0x000D; // Level-tiggered, Active High + ++Iso; + } + ASSERT ( + Iso - (EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *)Ptr == + 1 + PciLinkIsoCount + ); + Ptr = Iso; + + LocalApicNmi = Ptr; + LocalApicNmi->Type = EFI_ACPI_1_0_LOCAL_APIC_NMI; + LocalApicNmi->Length = sizeof (*LocalApicNmi); + LocalApicNmi->AcpiProcessorId = 0xFF; // applies to all processors + // + // polarity and trigger mode of the APIC I/O input signals conform to the + // specifications of the bus + // + LocalApicNmi->Flags = 0x0000; + // + // Local APIC interrupt input LINTn to which NMI is connected. + // + LocalApicNmi->LocalApicInti = 0x01; + Ptr = LocalApicNmi + 1; + + ASSERT ((UINT8 *)Ptr - (UINT8 *)Madt == NewBufferSize); + Status = InstallAcpiTable (AcpiProtocol, Madt, NewBufferSize, TableKey); + + FreePool (Madt); return Status; } diff --git a/OvmfPkg/AcpiTables/Madt.aslc b/OvmfPkg/AcpiTables/Madt.aslc index f5b71a6e0c..62bf2c7fd2 100644 --- a/OvmfPkg/AcpiTables/Madt.aslc +++ b/OvmfPkg/AcpiTables/Madt.aslc @@ -16,11 +16,7 @@ **/ #include - -// -// MADT Definitions -// -#define EFI_ACPI_OEM_MADT_REVISION 0x00000000 // TBD +#include // // Local APIC address @@ -74,21 +70,12 @@ EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE Madt = { EFI_ACPI_1_0_APIC_SIGNATURE, sizeof (EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE), EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION, - - // - // Checksum will be updated at runtime - // - 0x00, - - // - // It is expected that these values will be programmed at runtime - // - ' ', ' ', ' ', ' ', ' ', ' ', - - 0, - EFI_ACPI_OEM_MADT_REVISION, - 0, - 0, + 0x00, // Checksum will be updated at runtime + EFI_ACPI_OEM_ID, + EFI_ACPI_OEM_TABLE_ID, + EFI_ACPI_OEM_REVISION, + EFI_ACPI_CREATOR_ID, + EFI_ACPI_CREATOR_REVISION, // // MADT specific fields diff --git a/OvmfPkg/AcpiTables/Platform.h b/OvmfPkg/AcpiTables/Platform.h index 4b03897614..e8fae3c839 100644 --- a/OvmfPkg/AcpiTables/Platform.h +++ b/OvmfPkg/AcpiTables/Platform.h @@ -23,9 +23,9 @@ // #define EFI_ACPI_OEM_ID 'O','V','M','F',' ',' ' // OEMID 6 bytes long #define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('O','V','M','F','E','D','K','2') // OEM table id 8 bytes long -#define EFI_ACPI_OEM_REVISION 0x02000820 +#define EFI_ACPI_OEM_REVISION 0x20120804 #define EFI_ACPI_CREATOR_ID SIGNATURE_32('O','V','M','F') -#define EFI_ACPI_CREATOR_REVISION 0x00000097 +#define EFI_ACPI_CREATOR_REVISION 0x00000098 #define INT_MODEL 0x01 #define SCI_INT_VECTOR 0x0009 diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index ffedcbf6de..453a5788cb 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -302,6 +302,9 @@ !endif !endif + # IRQs 5, 9, 10, 11 are level-triggered + gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0E20 + !if $(SECURE_BOOT_ENABLE) == TRUE # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x05 diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 123ac31e01..73e8c987b5 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -302,6 +302,9 @@ !endif !endif + # IRQs 5, 9, 10, 11 are level-triggered + gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0E20 + [PcdsFixedAtBuild.X64] !if $(SECURE_BOOT_ENABLE) == TRUE # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 1fce7a7e8c..1c2aec0cdc 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -302,6 +302,9 @@ !endif !endif + # IRQs 5, 9, 10, 11 are level-triggered + gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0E20 + !if $(SECURE_BOOT_ENABLE) == TRUE # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x05