OvmfPkg/AcpiPlatformDxe: Dynamically add Local APIC entries in MADT

Update MADT processing for QEMU to add additional Local APIC
entries to the MADT.

The MADT is still built with a single Local APIC entry.
If the AcpiPlatformDxe driver determines that more processors
are available, then additional Local APIC entries are added
to the MADT at runtime.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13387 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
jljusten 2012-05-30 23:15:59 +00:00
parent 54235984ee
commit 255b418415
2 changed files with 83 additions and 1 deletions

View File

@ -46,6 +46,7 @@
UefiDriverEntryPoint UefiDriverEntryPoint
HobLib HobLib
QemuFwCfgLib QemuFwCfgLib
MemoryAllocationLib
[Protocols] [Protocols]
gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED

View File

@ -13,6 +13,8 @@
**/ **/
#include "AcpiPlatform.h" #include "AcpiPlatform.h"
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/QemuFwCfgLib.h> #include <Library/QemuFwCfgLib.h>
@ -29,6 +31,73 @@ QemuDetected (
} }
STATIC
EFI_STATUS
EFIAPI
QemuInstallAcpiMadtTable (
IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
IN VOID *AcpiTableBuffer,
IN UINTN AcpiTableBufferSize,
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;
QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount);
Count = (UINTN) QemuFwCfgRead16 ();
ASSERT (Count >= 1);
if (Count == 1) {
//
// The pre-built MADT table covers the single CPU case
//
return InstallAcpiTable (
AcpiProtocol,
AcpiTableBuffer,
AcpiTableBufferSize,
TableKey
);
}
//
// 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);
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 = Loop;
LocalApic->ApicId = Loop;
LocalApic->Flags = 1;
LocalApic++;
}
Hdr->Length = NewBufferSize;
Status = InstallAcpiTable (AcpiProtocol, Hdr, NewBufferSize, TableKey);
FreePool (Hdr);
return Status;
}
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
QemuInstallAcpiTable ( QemuInstallAcpiTable (
@ -38,7 +107,19 @@ QemuInstallAcpiTable (
OUT UINTN *TableKey OUT UINTN *TableKey
) )
{ {
return InstallAcpiTable( EFI_ACPI_DESCRIPTION_HEADER *Hdr;
EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction;
Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AcpiTableBuffer;
switch (Hdr->Signature) {
case EFI_ACPI_1_0_APIC_SIGNATURE:
TableInstallFunction = QemuInstallAcpiMadtTable;
break;
default:
TableInstallFunction = InstallAcpiTable;
}
return TableInstallFunction (
AcpiProtocol, AcpiProtocol,
AcpiTableBuffer, AcpiTableBuffer,
AcpiTableBufferSize, AcpiTableBufferSize,