From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out01.mta.xmission.com (out01.mta.xmission.com [166.70.13.231]) by mx.groups.io with SMTP id smtpd.web10.2767.1587752974493843743 for ; Fri, 24 Apr 2020 11:29:34 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: bsdio.com, ip: 166.70.13.231, mailfrom: rebecca@bsdio.com) Received: from in02.mta.xmission.com ([166.70.13.52]) by out01.mta.xmission.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1jS34v-00023j-Qd; Fri, 24 Apr 2020 12:29:33 -0600 Received: from mta5.zcs.xmission.com ([166.70.13.69]) by in02.mta.xmission.com with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.87) (envelope-from ) id 1jS34u-0005Ca-Ho; Fri, 24 Apr 2020 12:29:33 -0600 Received: from localhost (localhost [127.0.0.1]) by mta5.zcs.xmission.com (Postfix) with ESMTP id 66667128068B; Fri, 24 Apr 2020 12:29:32 -0600 (MDT) X-Amavis-Modified: Mail body modified (using disclaimer) - mta5.zcs.xmission.com Received: from mta5.zcs.xmission.com ([127.0.0.1]) by localhost (mta5.zcs.xmission.com [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id 2-Lj7hFdZjjh; Fri, 24 Apr 2020 12:29:32 -0600 (MDT) Received: from photon.int.bluestop.org (c-174-52-16-57.hsd1.ut.comcast.net [174.52.16.57]) by mta5.zcs.xmission.com (Postfix) with ESMTPSA id 14CD3128068C; Fri, 24 Apr 2020 12:29:32 -0600 (MDT) From: "Rebecca Cran" To: devel@edk2.groups.io, Jordan Justen , Laszlo Ersek , Ard Biesheuvel , Andrew Fish , Leif Lindholm , Michael D Kinney Cc: Rebecca Cran Date: Fri, 24 Apr 2020 12:29:14 -0600 Message-Id: <20200424182914.138915-7-rebecca@bsdio.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20200424182914.138915-1-rebecca@bsdio.com> References: <20200424182914.138915-1-rebecca@bsdio.com> MIME-Version: 1.0 X-XM-SPF: eid=1jS34u-0005Ca-Ho;;;mid=<20200424182914.138915-7-rebecca@bsdio.com>;;;hst=in02.mta.xmission.com;;;ip=166.70.13.69;;;frm=rebecca@bsdio.com;;;spf=pass X-SA-Exim-Connect-IP: 166.70.13.69 X-SA-Exim-Mail-From: rebecca@bsdio.com X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on sa08.xmission.com X-Spam-Level: ** X-Spam-Status: No, score=2.1 required=8.0 tests=ALL_TRUSTED,BAYES_50, DCC_CHECK_NEGATIVE,T_TM2_M_HEADER_IN_MSG,TooManyTo_001,TooManyTo_002, TooManyTo_003,TooManyTo_004,TooManyTo_005 autolearn=disabled version=3.4.2 X-Spam-Report: * -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP * 0.8 BAYES_50 BODY: Bayes spam probability is 40 to 60% * [score: 0.5000] * 0.5 TooManyTo_004 Multiple "To" Header Recipients 5x (uncommon) * 0.4 TooManyTo_005 Multiple "To" Header Recipients 6x (uncommon) * 0.3 TooManyTo_001 Multiple "To" Header Recipients 2x (uncommon) * 0.6 TooManyTo_003 Multiple "To" Header Recipients 4x (uncommon) * 0.5 TooManyTo_002 Multiple "To" Header Recipients 3x (uncommon) * 0.0 T_TM2_M_HEADER_IN_MSG BODY: No description available. * -0.0 DCC_CHECK_NEGATIVE Not listed in DCC * [sa08 1397; IP=ok Body=1 Fuz1=1] [Fuz2=1] X-Spam-DCC: XMission; sa08 1397; IP=ok Body=1 Fuz1=1 Fuz2=1 X-Spam-Combo: **;devel@edk2.groups.io, Jordan Justen , Laszlo Ersek , Ard Biesheuvel , Andrew Fish , Leif Lindholm , Michael D Kinney X-Spam-Relay-Country: X-Spam-Timing: total 1031 ms - load_scoreonly_sql: 0.05 (0.0%), signal_user_changed: 12 (1.2%), b_tie_ro: 10 (1.0%), parse: 3.2 (0.3%), extract_message_metadata: 22 (2.1%), get_uri_detail_list: 8 (0.8%), tests_pri_-1000: 3.6 (0.4%), tests_pri_-950: 1.38 (0.1%), tests_pri_-900: 1.19 (0.1%), tests_pri_-90: 127 (12.3%), check_bayes: 110 (10.7%), b_tokenize: 33 (3.2%), b_tok_get_all: 20 (1.9%), b_comp_prob: 7 (0.6%), b_tok_touch_all: 44 (4.3%), b_finish: 1.42 (0.1%), tests_pri_0: 843 (81.8%), check_dkim_signature: 1.00 (0.1%), check_dkim_adsp: 73 (7.0%), poll_dns_idle: 66 (6.4%), tests_pri_10: 3.3 (0.3%), tests_pri_500: 8 (0.8%), rewrite_mail: 0.00 (0.0%) Subject: [PATCH v4 6/6] BhyvePkg: Add AcpiPlatformDxe X-Spam-Flag: No X-SA-Exim-Version: 4.2.1 (built Thu, 05 May 2016 13:38:54 -0600) X-SA-Exim-Scanned: Yes (on in02.mta.xmission.com) Content-Transfer-Encoding: quoted-printable Make a copy of OvmfPkg/AcpiPlatformDxe under BhyvePkg, with the changes needed to support the bhyve hypervisor. Signed-off-by: Rebecca Cran --- BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c | 251 +++++++++++++++++++ BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h | 77 ++++++ BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf | 65 +++++ BhyvePkg/AcpiPlatformDxe/Bhyve.c | 132 ++++++++++ BhyvePkg/AcpiPlatformDxe/EntryPoint.c | 90 +++++++ BhyvePkg/AcpiPlatformDxe/PciDecoding.c | 192 ++++++++++++++ 6 files changed, 807 insertions(+) create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf create mode 100644 BhyvePkg/AcpiPlatformDxe/Bhyve.c create mode 100644 BhyvePkg/AcpiPlatformDxe/EntryPoint.c create mode 100644 BhyvePkg/AcpiPlatformDxe/PciDecoding.c diff --git a/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c b/BhyvePkg/AcpiPlatfor= mDxe/AcpiPlatform.c new file mode 100644 index 0000000000..31bbf6c474 --- /dev/null +++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c @@ -0,0 +1,251 @@ +/** @file=0D + OVMF ACPI Platform Driver=0D +=0D + Copyright (c) 2020, Rebecca Cran =0D + Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#include "AcpiPlatform.h"=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +InstallAcpiTable (=0D + IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,=0D + IN VOID *AcpiTableBuffer,=0D + IN UINTN AcpiTableBufferSize,=0D + OUT UINTN *TableKey=0D + )=0D +{=0D + return AcpiProtocol->InstallAcpiTable (=0D + AcpiProtocol,=0D + AcpiTableBuffer,=0D + AcpiTableBufferSize,=0D + TableKey=0D + );=0D +}=0D +=0D +=0D +/**=0D + Locate the first instance of a protocol. If the protocol requested is a= n=0D + FV protocol, then it will return the first FV that contains the ACPI tab= le=0D + storage file.=0D +=0D + @param Instance Return pointer to the first instance of the protoc= ol=0D +=0D + @return EFI_SUCCESS The function completed successfully.=0D + @return EFI_NOT_FOUND The protocol could not be located.=0D + @return EFI_OUT_OF_RESOURCES There are not enough resources to find the= protocol.=0D +=0D +**/=0D +EFI_STATUS=0D +LocateFvInstanceWithTables (=0D + OUT EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance=0D + )=0D +{=0D + EFI_STATUS Status;=0D + EFI_HANDLE *HandleBuffer;=0D + UINTN NumberOfHandles;=0D + EFI_FV_FILETYPE FileType;=0D + UINT32 FvStatus;=0D + EFI_FV_FILE_ATTRIBUTES Attributes;=0D + UINTN Size;=0D + UINTN Index;=0D + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;=0D +=0D + FvStatus =3D 0;=0D +=0D + //=0D + // Locate protocol.=0D + //=0D + Status =3D gBS->LocateHandleBuffer (=0D + ByProtocol,=0D + &gEfiFirmwareVolume2ProtocolGuid,=0D + NULL,=0D + &NumberOfHandles,=0D + &HandleBuffer=0D + );=0D + if (EFI_ERROR (Status)) {=0D + //=0D + // Defined errors at this time are not found and out of resources.=0D + //=0D + return Status;=0D + }=0D +=0D + //=0D + // Looking for FV with ACPI storage file=0D + //=0D + for (Index =3D 0; Index < NumberOfHandles; Index++) {=0D + //=0D + // Get the protocol on this handle=0D + // This should not fail because of LocateHandleBuffer=0D + //=0D + Status =3D gBS->HandleProtocol (=0D + HandleBuffer[Index],=0D + &gEfiFirmwareVolume2ProtocolGuid,=0D + (VOID**) &FvInstance=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D +=0D + //=0D + // See if it has the ACPI storage file=0D + //=0D + Status =3D FvInstance->ReadFile (=0D + FvInstance,=0D + (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),= =0D + NULL,=0D + &Size,=0D + &FileType,=0D + &Attributes,=0D + &FvStatus=0D + );=0D +=0D + //=0D + // If we found it, then we are done=0D + //=0D + if (Status =3D=3D EFI_SUCCESS) {=0D + *Instance =3D FvInstance;=0D + break;=0D + }=0D + }=0D +=0D + //=0D + // Our exit status is determined by the success of the previous operatio= ns=0D + // If the protocol was found, Instance already points to it.=0D + //=0D +=0D + //=0D + // Free any allocated buffers=0D + //=0D + gBS->FreePool (HandleBuffer);=0D +=0D + return Status;=0D +}=0D +=0D +=0D +/**=0D + Find ACPI tables in an FV and install them.=0D +=0D + This is now a fall-back path. Normally, we will search for tables provid= ed=0D + by the VMM first.=0D +=0D + If that fails, we use this function to load the ACPI tables from an FV. = The=0D + sources for the FV based tables is located under OvmfPkg/AcpiTables.=0D +=0D + @param AcpiTable Protocol instance pointer=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +InstallOvmfFvTables (=0D + IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable=0D + )=0D +{=0D + EFI_STATUS Status;=0D + EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;=0D + INTN Instance;=0D + EFI_ACPI_COMMON_HEADER *CurrentTable;=0D + UINTN TableHandle;=0D + UINT32 FvStatus;=0D + UINTN TableSize;=0D + UINTN Size;=0D + EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction;=0D +=0D + Instance =3D 0;=0D + CurrentTable =3D NULL;=0D + TableHandle =3D 0;=0D +=0D + TableInstallFunction =3D BhyveInstallAcpiTable;=0D +=0D + //=0D + // set FwVol (and use an ASSERT() below) to suppress incorrect=0D + // compiler/analyzer warnings=0D + //=0D + FwVol =3D NULL;=0D + //=0D + // Locate the firmware volume protocol=0D + //=0D + Status =3D LocateFvInstanceWithTables (&FwVol);=0D + if (EFI_ERROR (Status)) {=0D + return EFI_ABORTED;=0D + }=0D + ASSERT (FwVol !=3D NULL);=0D +=0D + //=0D + // Read tables from the storage file.=0D + //=0D + while (Status =3D=3D EFI_SUCCESS) {=0D +=0D + Status =3D FwVol->ReadSection (=0D + FwVol,=0D + (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),=0D + EFI_SECTION_RAW,=0D + Instance,=0D + (VOID**) &CurrentTable,=0D + &Size,=0D + &FvStatus=0D + );=0D + if (!EFI_ERROR (Status)) {=0D + //=0D + // Add the table=0D + //=0D + TableHandle =3D 0;=0D +=0D + TableSize =3D ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length= ;=0D + ASSERT (Size >=3D TableSize);=0D +=0D + //=0D + // Install ACPI table=0D + //=0D + Status =3D TableInstallFunction (=0D + AcpiTable,=0D + CurrentTable,=0D + TableSize,=0D + &TableHandle=0D + );=0D +=0D + //=0D + // Free memory allocated by ReadSection=0D + //=0D + gBS->FreePool (CurrentTable);=0D +=0D + if (EFI_ERROR (Status)) {=0D + return EFI_ABORTED;=0D + }=0D +=0D + //=0D + // Increment the instance=0D + //=0D + Instance++;=0D + CurrentTable =3D NULL;=0D + }=0D + }=0D +=0D + return EFI_SUCCESS;=0D +}=0D +=0D +/**=0D + Effective entrypoint of Acpi Platform driver.=0D +=0D + @param ImageHandle=0D + @param SystemTable=0D +=0D + @return EFI_SUCCESS=0D + @return EFI_LOAD_ERROR=0D + @return EFI_OUT_OF_RESOURCES=0D +=0D +**/=0D +EFI_STATUS=0D +EFIAPI=0D +InstallAcpiTables (=0D + IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + Status =3D InstallOvmfFvTables (AcpiTable);=0D +=0D + return Status;=0D +}=0D +=0D diff --git a/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h b/BhyvePkg/AcpiPlatfor= mDxe/AcpiPlatform.h new file mode 100644 index 0000000000..d30cd11a1d --- /dev/null +++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h @@ -0,0 +1,77 @@ +/** @file=0D + Sample ACPI Platform Driver=0D +=0D + Copyright (c) 2020, Rebecca Cran =0D + Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +=0D +**/=0D +=0D +#ifndef _ACPI_PLATFORM_H_INCLUDED_=0D +#define _ACPI_PLATFORM_H_INCLUDED_=0D +=0D +#include =0D +=0D +#include =0D +#include =0D +#include =0D +=0D +#include =0D +#include =0D +#include =0D +#include =0D +#include =0D +=0D +#include =0D +=0D +typedef struct {=0D + EFI_PCI_IO_PROTOCOL *PciIo;=0D + UINT64 PciAttributes;=0D +} ORIGINAL_ATTRIBUTES;=0D +=0D +typedef struct S3_CONTEXT S3_CONTEXT;=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +InstallAcpiTable (=0D + IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,=0D + IN VOID *AcpiTableBuffer,=0D + IN UINTN AcpiTableBufferSize,=0D + OUT UINTN *TableKey=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +BhyveInstallAcpiTable(=0D + IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,=0D + IN VOID *AcpiTableBuffer,=0D + IN UINTN AcpiTableBufferSize,=0D + OUT UINTN *TableKey=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +InstallXenTables (=0D + IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol=0D + );=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +InstallAcpiTables (=0D + IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable=0D + );=0D +=0D +VOID=0D +EnablePciDecoding (=0D + OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,=0D + OUT UINTN *Count=0D + );=0D +=0D +VOID=0D +RestorePciDecoding (=0D + IN ORIGINAL_ATTRIBUTES *OriginalAttributes,=0D + IN UINTN Count=0D + );=0D +=0D +#endif=0D +=0D diff --git a/BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf b/BhyvePkg/AcpiPl= atformDxe/AcpiPlatformDxe.inf new file mode 100644 index 0000000000..bc52fa5e2f --- /dev/null +++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf @@ -0,0 +1,65 @@ +## @file=0D +# OVMF ACPI Platform Driver=0D +#=0D +# Copyright (c) 2020, Rebecca Cran =0D +# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
= =0D +#=0D +# SPDX-License-Identifier: BSD-2-Clause-Patent=0D +##=0D +=0D +[Defines]=0D + INF_VERSION =3D 0x00010005=0D + BASE_NAME =3D AcpiPlatform=0D + FILE_GUID =3D D5F92408-BAB5-44CA-8A60-C212F01D7E9D= =0D + MODULE_TYPE =3D DXE_DRIVER=0D + VERSION_STRING =3D 1.0=0D + ENTRY_POINT =3D AcpiPlatformEntryPoint=0D +=0D +#=0D +# The following information is for reference only and not required by the = build tools.=0D +#=0D +# VALID_ARCHITECTURES =3D IA32 X64 EBC=0D +#=0D +=0D +[Sources]=0D + AcpiPlatform.c=0D + AcpiPlatform.h=0D + EntryPoint.c=0D + PciDecoding.c=0D + Bhyve.c=0D +=0D +[Packages]=0D + MdePkg/MdePkg.dec=0D + MdeModulePkg/MdeModulePkg.dec=0D + BhyvePkg/BhyvePkg.dec=0D + UefiCpuPkg/UefiCpuPkg.dec=0D +=0D +[LibraryClasses]=0D + UefiLib=0D + PcdLib=0D + BaseMemoryLib=0D + DebugLib=0D + UefiBootServicesTableLib=0D + UefiDriverEntryPoint=0D + BhyveFwCtlLib=0D + MemoryAllocationLib=0D + BaseLib=0D + DxeServicesTableLib=0D + OrderedCollectionLib=0D +=0D +[Protocols]=0D + gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED= =0D + gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSU= MED=0D + gEfiPciIoProtocolGuid # PROTOCOL SOMETIMES_CONSU= MED=0D +=0D +[Guids]=0D + gRootBridgesConnectedEventGroupGuid=0D +=0D +[Pcd]=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile=0D + gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration=0D + gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress=0D + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress=0D +=0D +[Depex]=0D + gEfiAcpiTableProtocolGuid=0D diff --git a/BhyvePkg/AcpiPlatformDxe/Bhyve.c b/BhyvePkg/AcpiPlatformDxe/Bh= yve.c new file mode 100644 index 0000000000..6d42264b65 --- /dev/null +++ b/BhyvePkg/AcpiPlatformDxe/Bhyve.c @@ -0,0 +1,132 @@ +/*=0D + * Copyright (c) 2020, Rebecca Cran =0D + * Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
= =0D + * Copyright (C) 2012, Red Hat, Inc.=0D + * Copyright (c) 2014, Pluribus Networks, Inc.=0D + *=0D + * SPDX-License-Identifier: BSD-2-Clause-Patent=0D + */=0D +#include "AcpiPlatform.h"=0D +=0D +#include =0D +#include =0D +#include =0D +=0D +STATIC=0D +EFI_STATUS=0D +EFIAPI=0D +BhyveInstallAcpiMadtTable (=0D + IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,=0D + IN VOID *AcpiTableBuffer,=0D + IN UINTN AcpiTableBufferSize,=0D + OUT UINTN *TableKey=0D + )=0D +{=0D + UINT32 CpuCount;=0D + UINTN cSize;=0D + UINTN NewBufferSize;=0D + EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt;=0D + EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic;=0D + EFI_ACPI_1_0_IO_APIC_STRUCTURE *IoApic;=0D + EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *Iso;=0D + VOID *Ptr;=0D + UINTN Loop;=0D + EFI_STATUS Status;=0D +=0D + ASSERT (AcpiTableBufferSize >=3D sizeof (EFI_ACPI_DESCRIPTION_HEADER));= =0D +=0D + // Query the host for the number of vCPUs=0D + CpuCount =3D 0;=0D + cSize =3D sizeof(CpuCount);=0D + if (BhyveFwCtlGet ("hw.ncpu", &CpuCount, &cSize) =3D=3D RETURN_SUCCESS) = {=0D + DEBUG ((DEBUG_INFO, "Retrieved CpuCount %d\n", CpuCount));=0D + ASSERT (CpuCount >=3D 1);=0D + } else {=0D + DEBUG ((DEBUG_INFO, "CpuCount retrieval error\n"));=0D + CpuCount =3D 1;=0D + }=0D +=0D + NewBufferSize =3D 1 * sizeof (*Madt) +=0D + CpuCount * sizeof (*LocalApic) +=0D + 1 * sizeof (*IoApic) +=0D + 1 * sizeof (*Iso);=0D +=0D + Madt =3D AllocatePool (NewBufferSize);=0D + if (Madt =3D=3D NULL) {=0D + return EFI_OUT_OF_RESOURCES;=0D + }=0D +=0D + CopyMem (&(Madt->Header), AcpiTableBuffer, sizeof (EFI_ACPI_DESCRIPTION_= HEADER));=0D + Madt->Header.Length =3D (UINT32) NewBufferSize;=0D + Madt->LocalApicAddress =3D 0xFEE00000;=0D + Madt->Flags =3D EFI_ACPI_1_0_PCAT_COMPAT;=0D + Ptr =3D Madt + 1;=0D +=0D + LocalApic =3D Ptr;=0D + for (Loop =3D 0; Loop < CpuCount; ++Loop) {=0D + LocalApic->Type =3D EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC;=0D + LocalApic->Length =3D sizeof (*LocalApic);=0D + LocalApic->AcpiProcessorId =3D (UINT8) Loop;=0D + LocalApic->ApicId =3D (UINT8) Loop;=0D + LocalApic->Flags =3D 1; // enabled=0D + ++LocalApic;=0D + }=0D + Ptr =3D LocalApic;=0D +=0D + IoApic =3D Ptr;=0D + IoApic->Type =3D EFI_ACPI_1_0_IO_APIC;=0D + IoApic->Length =3D sizeof (*IoApic);=0D + IoApic->IoApicId =3D (UINT8) CpuCount;=0D + IoApic->Reserved =3D EFI_ACPI_RESERVED_BYTE;=0D + IoApic->IoApicAddress =3D 0xFEC00000;=0D + IoApic->SystemVectorBase =3D 0x00000000;=0D + Ptr =3D IoApic + 1;=0D +=0D + //=0D + // IRQ0 (8254 Timer) =3D> IRQ2 (PIC) Interrupt Source Override Structure= =0D + //=0D + Iso =3D Ptr;=0D + Iso->Type =3D EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERR= IDE;=0D + Iso->Length =3D sizeof (*Iso);=0D + Iso->Bus =3D 0x00; // ISA=0D + Iso->Source =3D 0x00; // IRQ0=0D + Iso->GlobalSystemInterruptVector =3D 0x00000002;=0D + Iso->Flags =3D 0x0000; // Conforms to specs of the= bus=0D + Ptr =3D Iso + 1;=0D +=0D + ASSERT ((UINTN) ((UINT8 *)Ptr - (UINT8 *)Madt) =3D=3D NewBufferSize);=0D + Status =3D InstallAcpiTable (AcpiProtocol, Madt, NewBufferSize, TableKey= );=0D +=0D + FreePool (Madt);=0D +=0D + return Status;=0D +}=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +BhyveInstallAcpiTable (=0D + IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,=0D + IN VOID *AcpiTableBuffer,=0D + IN UINTN AcpiTableBufferSize,=0D + OUT UINTN *TableKey=0D + )=0D +{=0D + EFI_ACPI_DESCRIPTION_HEADER *Hdr;=0D + EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction;=0D +=0D + Hdr =3D (EFI_ACPI_DESCRIPTION_HEADER*) AcpiTableBuffer;=0D + switch (Hdr->Signature) {=0D + case EFI_ACPI_1_0_APIC_SIGNATURE:=0D + TableInstallFunction =3D BhyveInstallAcpiMadtTable;=0D + break;=0D + default:=0D + TableInstallFunction =3D InstallAcpiTable;=0D + }=0D +=0D + return TableInstallFunction (=0D + AcpiProtocol,=0D + AcpiTableBuffer,=0D + AcpiTableBufferSize,=0D + TableKey=0D + );=0D +}=0D diff --git a/BhyvePkg/AcpiPlatformDxe/EntryPoint.c b/BhyvePkg/AcpiPlatformD= xe/EntryPoint.c new file mode 100644 index 0000000000..f66f892911 --- /dev/null +++ b/BhyvePkg/AcpiPlatformDxe/EntryPoint.c @@ -0,0 +1,90 @@ +/** @file=0D + Entry point of OVMF ACPI Platform Driver=0D +=0D + Copyright (C) 2015, Red Hat, Inc.=0D + Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.
=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +**/=0D +=0D +#include =0D +#include "AcpiPlatform.h"=0D +=0D +STATIC=0D +EFI_ACPI_TABLE_PROTOCOL *=0D +FindAcpiTableProtocol (=0D + VOID=0D + )=0D +{=0D + EFI_STATUS Status;=0D + EFI_ACPI_TABLE_PROTOCOL *AcpiTable;=0D +=0D + Status =3D gBS->LocateProtocol (=0D + &gEfiAcpiTableProtocolGuid,=0D + NULL,=0D + (VOID**)&AcpiTable=0D + );=0D + ASSERT_EFI_ERROR (Status);=0D + return AcpiTable;=0D +}=0D +=0D +=0D +STATIC=0D +VOID=0D +EFIAPI=0D +OnRootBridgesConnected (=0D + IN EFI_EVENT Event,=0D + IN VOID *Context=0D + )=0D +{=0D + EFI_STATUS Status;=0D +=0D + DEBUG ((DEBUG_INFO,=0D + "%a: root bridges have been connected, installing ACPI tables\n",=0D + __FUNCTION__));=0D + Status =3D InstallAcpiTables (FindAcpiTableProtocol ());=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_ERROR, "%a: InstallAcpiTables: %r\n", __FUNCTION__, Stat= us));=0D + }=0D + gBS->CloseEvent (Event);=0D +}=0D +=0D +=0D +EFI_STATUS=0D +EFIAPI=0D +AcpiPlatformEntryPoint (=0D + IN EFI_HANDLE ImageHandle,=0D + IN EFI_SYSTEM_TABLE *SystemTable=0D + )=0D +{=0D + EFI_STATUS Status;=0D + EFI_EVENT RootBridgesConnected;=0D +=0D + //=0D + // If the platform doesn't support PCI, or PCI enumeration has been disa= bled,=0D + // install the tables at once, and let the entry point's return code ref= lect=0D + // the full functionality.=0D + //=0D + if (PcdGetBool (PcdPciDisableBusEnumeration)) {=0D + DEBUG ((DEBUG_INFO, "%a: PCI or its enumeration disabled, installing "= =0D + "ACPI tables\n", __FUNCTION__));=0D + return InstallAcpiTables (FindAcpiTableProtocol ());=0D + }=0D +=0D + //=0D + // Otherwise, delay installing the ACPI tables until root bridges are=0D + // connected. The entry point's return status will only reflect the call= back=0D + // setup. (Note that we're a DXE_DRIVER; our entry point function is inv= oked=0D + // strictly before BDS is entered and can connect the root bridges.)=0D + //=0D + Status =3D gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK,=0D + OnRootBridgesConnected, NULL /* Context */,=0D + &gRootBridgesConnectedEventGroupGuid, &RootBridgesConnec= ted);=0D + if (!EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_INFO,=0D + "%a: waiting for root bridges to be connected, registered callback\n= ",=0D + __FUNCTION__));=0D + }=0D +=0D + return Status;=0D +}=0D diff --git a/BhyvePkg/AcpiPlatformDxe/PciDecoding.c b/BhyvePkg/AcpiPlatform= Dxe/PciDecoding.c new file mode 100644 index 0000000000..73894106c9 --- /dev/null +++ b/BhyvePkg/AcpiPlatformDxe/PciDecoding.c @@ -0,0 +1,192 @@ +/** @file=0D + Temporarily enable IO and MMIO decoding for all PCI devices while QEMU=0D + regenerates the ACPI tables.=0D +=0D + Copyright (C) 2016, Red Hat, Inc.=0D +=0D + SPDX-License-Identifier: BSD-2-Clause-Patent=0D +**/=0D +=0D +#include =0D +=0D +#include "AcpiPlatform.h"=0D +=0D +=0D +/**=0D + Collect all PciIo protocol instances in the system. Save their original= =0D + attributes, and enable IO and MMIO decoding for each.=0D +=0D + This is a best effort function; it doesn't return status codes. Its=0D + caller is supposed to proceed even if this function fails.=0D +=0D + @param[out] OriginalAttributes On output, a dynamically allocated array= of=0D + ORIGINAL_ATTRIBUTES elements. The array = lists=0D + the PciIo protocol instances found in th= e=0D + system at the time of the call, plus the= =0D + original PCI attributes for each.=0D +=0D + Before returning, the function enables I= O and=0D + MMIO decoding for each PciIo instance it= =0D + finds.=0D +=0D + On error, or when no such instances are= =0D + found, OriginalAttributes is set to NULL= .=0D +=0D + @param[out] Count On output, the number of elements in=0D + OriginalAttributes. On error it is set t= o=0D + zero.=0D +**/=0D +VOID=0D +EnablePciDecoding (=0D + OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,=0D + OUT UINTN *Count=0D + )=0D +{=0D + EFI_STATUS Status;=0D + UINTN NoHandles;=0D + EFI_HANDLE *Handles;=0D + ORIGINAL_ATTRIBUTES *OrigAttrs;=0D + UINTN Idx;=0D +=0D + *OriginalAttributes =3D NULL;=0D + *Count =3D 0;=0D +=0D + if (PcdGetBool (PcdPciDisableBusEnumeration)) {=0D + //=0D + // The platform downloads ACPI tables from QEMU in general, but there = are=0D + // no root bridges in this execution. We're done.=0D + //=0D + return;=0D + }=0D +=0D + Status =3D gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid,= =0D + NULL /* SearchKey */, &NoHandles, &Handles);=0D + if (Status =3D=3D EFI_NOT_FOUND) {=0D + //=0D + // No PCI devices were found on either of the root bridges. We're done= .=0D + //=0D + return;=0D + }=0D +=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_WARN, "%a: LocateHandleBuffer(): %r\n", __FUNCTION__,=0D + Status));=0D + return;=0D + }=0D +=0D + OrigAttrs =3D AllocatePool (NoHandles * sizeof *OrigAttrs);=0D + if (OrigAttrs =3D=3D NULL) {=0D + DEBUG ((DEBUG_WARN, "%a: AllocatePool(): out of resources\n",=0D + __FUNCTION__));=0D + goto FreeHandles;=0D + }=0D +=0D + for (Idx =3D 0; Idx < NoHandles; ++Idx) {=0D + EFI_PCI_IO_PROTOCOL *PciIo;=0D + UINT64 Attributes;=0D +=0D + //=0D + // Look up PciIo on the handle and stash it=0D + //=0D + Status =3D gBS->HandleProtocol (Handles[Idx], &gEfiPciIoProtocolGuid,= =0D + (VOID**)&PciIo);=0D + ASSERT_EFI_ERROR (Status);=0D + OrigAttrs[Idx].PciIo =3D PciIo;=0D +=0D + //=0D + // Stash the current attributes=0D + //=0D + Status =3D PciIo->Attributes (PciIo, EfiPciIoAttributeOperationGet, 0,= =0D + &OrigAttrs[Idx].PciAttributes);=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationGet: %r\n",=0D + __FUNCTION__, Status));=0D + goto RestoreAttributes;=0D + }=0D +=0D + //=0D + // Retrieve supported attributes=0D + //=0D + Status =3D PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSupport= ed, 0,=0D + &Attributes);=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationSupported: %r\n",= =0D + __FUNCTION__, Status));=0D + goto RestoreAttributes;=0D + }=0D +=0D + //=0D + // Enable IO and MMIO decoding=0D + //=0D + Attributes &=3D EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY;= =0D + Status =3D PciIo->Attributes (PciIo, EfiPciIoAttributeOperationEnable,= =0D + Attributes, NULL);=0D + if (EFI_ERROR (Status)) {=0D + DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationEnable: %r\n",=0D + __FUNCTION__, Status));=0D + goto RestoreAttributes;=0D + }=0D + }=0D +=0D + //=0D + // Success=0D + //=0D + FreePool (Handles);=0D + *OriginalAttributes =3D OrigAttrs;=0D + *Count =3D NoHandles;=0D + return;=0D +=0D +RestoreAttributes:=0D + while (Idx > 0) {=0D + --Idx;=0D + OrigAttrs[Idx].PciIo->Attributes (OrigAttrs[Idx].PciIo,=0D + EfiPciIoAttributeOperationSet,=0D + OrigAttrs[Idx].PciAttributes,=0D + NULL=0D + );=0D + }=0D + FreePool (OrigAttrs);=0D +=0D +FreeHandles:=0D + FreePool (Handles);=0D +}=0D +=0D +=0D +/**=0D + Restore the original PCI attributes saved with EnablePciDecoding().=0D +=0D + @param[in] OriginalAttributes The array allocated and populated by=0D + EnablePciDecoding(). This parameter may b= e=0D + NULL. If OriginalAttributes is NULL, then= the=0D + function is a no-op; otherwise the PciIo= =0D + attributes will be restored, and the=0D + OriginalAttributes array will be freed.=0D +=0D + @param[in] Count The Count value stored by EnablePciDecodi= ng(),=0D + the number of elements in OriginalAttribu= tes.=0D + Count may be zero if and only if=0D + OriginalAttributes is NULL.=0D +**/=0D +VOID=0D +RestorePciDecoding (=0D + IN ORIGINAL_ATTRIBUTES *OriginalAttributes,=0D + IN UINTN Count=0D + )=0D +{=0D + UINTN Idx;=0D +=0D + ASSERT ((OriginalAttributes =3D=3D NULL) =3D=3D (Count =3D=3D 0));=0D + if (OriginalAttributes =3D=3D NULL) {=0D + return;=0D + }=0D +=0D + for (Idx =3D 0; Idx < Count; ++Idx) {=0D + OriginalAttributes[Idx].PciIo->Attributes (=0D + OriginalAttributes[Idx].PciIo,=0D + EfiPciIoAttributeOperationSet,=0D + OriginalAttributes[Idx].PciAttributes= ,=0D + NULL=0D + );=0D + }=0D + FreePool (OriginalAttributes);=0D +}=0D --=20 2.25.1