From nobody Thu Oct 14 07:10:56 2021 X-Original-To: freebsd-virtualization@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 99B7E1807744 for ; Thu, 14 Oct 2021 07:11:19 +0000 (UTC) (envelope-from C.Koehne@beckhoff.com) Received: from Internet2.beckhoff.com (internet2.beckhoff.com [194.25.186.210]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (Client CN "*.beckhoff.com", Issuer "Thawte TLS RSA CA G1" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4HVLD63QBHz4Yvc for ; Thu, 14 Oct 2021 07:11:18 +0000 (UTC) (envelope-from C.Koehne@beckhoff.com) Received: from 172.17.5.170 by Internet2.beckhoff.com (Tls12, Aes256, Sha384, DiffieHellmanEllipticKey256); Thu, 14 Oct 2021 07:11:17 GMT Received: from CorvinK-NB03.beckhoff.com (172.17.62.127) by ex04.beckhoff.com (172.17.5.170) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2375.12; Thu, 14 Oct 2021 09:11:15 +0200 From: =?UTF-8?q?Corvin=20K=C3=B6hne?= To: CC: FreeBSD Virtualization Subject: [PATCH] OvmfPkg/Bhyve: install bhyve's ACPI tables Date: Thu, 14 Oct 2021 09:10:56 +0200 Message-ID: <20211014071056.452-1-c.koehne@beckhoff.com> X-Mailer: git-send-email 2.33.0.windows.2 List-Id: Discussion List-Archive: https://lists.freebsd.org/archives/freebsd-virtualization List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-freebsd-virtualization@freebsd.org X-BeenThere: freebsd-virtualization@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Originating-IP: [172.17.62.127] X-ClientProxiedBy: ex06.beckhoff.com (172.17.5.171) To ex04.beckhoff.com (172.17.5.170) X-OLX-Disclaimer: EX04.BECKHOFF.COM X-Rspamd-Queue-Id: 4HVLD63QBHz4Yvc X-Spamd-Bar: ++ Authentication-Results: mx1.freebsd.org; dkim=none; dmarc=none; spf=pass (mx1.freebsd.org: domain of C.Koehne@beckhoff.com designates 194.25.186.210 as permitted sender) smtp.mailfrom=C.Koehne@beckhoff.com X-Spamd-Result: default: False [2.26 / 15.00]; ARC_NA(0.00)[]; NEURAL_HAM_MEDIUM(-1.00)[-1.000]; HAS_XOIP(0.00)[]; FROM_HAS_DN(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; R_SPF_ALLOW(-0.20)[+mx]; MIME_GOOD(-0.10)[text/plain]; DMARC_NA(0.00)[beckhoff.com]; RCPT_COUNT_ONE(0.00)[1]; RCVD_COUNT_THREE(0.00)[3]; TO_DN_ALL(0.00)[]; NEURAL_SPAM_LONG(1.00)[1.000]; MID_CONTAINS_FROM(1.00)[]; RCVD_IN_DNSWL_NONE(0.00)[194.25.186.210:from]; NEURAL_SPAM_SHORT(1.00)[1.000]; FROM_EQ_ENVFROM(0.00)[]; R_DKIM_NA(0.00)[]; MIME_TRACE(0.00)[0:+]; ASN(0.00)[asn:3320, ipnet:194.25.0.0/16, country:DE]; RCVD_TLS_LAST(0.00)[]; R_MIXED_CHARSET(0.56)[subject]; RWL_MAILSPIKE_POSSIBLE(0.00)[194.25.186.210:from] X-ThisMailContainsUnwantedMimeParts: N =EF=BB=BFIt's much easier to create configuration dependend ACPI tables for bhyve than for OVMF. For this reason, don't use the statically created ACPI tables provided by OVMF. Instead use the dynamically created ACPI tables of bhyve. If bhyve provides no ACPI tables or we are unable to detect those, fall back to OVMF tables. Implementation is similar to . Signed-off-by: Corvin K=C3=B6hne CC: FreeBSD Virtualization --- MdePkg/Include/Uefi/UefiBaseType.h | 2 + OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c | 10 + OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h | 6 + OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c | 241 +++++++++++++++++++ 4 files changed, 259 insertions(+) diff --git a/MdePkg/Include/Uefi/UefiBaseType.h b/MdePkg/Include/Uefi/UefiB= aseType.h index 45e2aa63bb..084c52cd0f 100644 --- a/MdePkg/Include/Uefi/UefiBaseType.h +++ b/MdePkg/Include/Uefi/UefiBaseType.h @@ -53,6 +53,8 @@ typedef UINT64 EFI_PHYSICAL_ADDRESS; /// typedef UINT64 EFI_VIRTUAL_ADDRESS; =20 +#define NUMERIC_VALUE_AS_POINTER(Type, Value) ((Type *) ((UINTN)(Value))= ) + /// /// EFI Time Abstraction: /// Year: 1900 - 9999 diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c b/OvmfPkg/Bhyve/A= cpiPlatformDxe/AcpiPlatform.c index 9ccdb4d91c..e7de6937da 100644 --- a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c +++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c @@ -245,6 +245,16 @@ InstallAcpiTables ( { EFI_STATUS Status; =20 + Status =3D InstallBhyveTables (AcpiTable); + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + if (Status !=3D EFI_NOT_FOUND) { + DEBUG ((DEBUG_INFO, "%a: unable to install bhyve's ACPI tables (%r)\n"= , + __FUNCTION__, Status)); + return Status; + } + Status =3D InstallOvmfFvTables (AcpiTable); =20 return Status; diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h b/OvmfPkg/Bhyve/A= cpiPlatformDxe/AcpiPlatform.h index 994ee2c7cd..1a99838e8e 100644 --- a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h +++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h @@ -46,6 +46,12 @@ BhyveInstallAcpiTable( OUT UINTN *TableKey ); =20 +EFI_STATUS +EFIAPI +InstallBhyveTables ( + IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol + ); + EFI_STATUS EFIAPI InstallXenTables ( diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c b/OvmfPkg/Bhyve/AcpiPlat= formDxe/Bhyve.c index 01ee894746..2f5dd87995 100644 --- a/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c +++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c @@ -12,6 +12,19 @@ #include #include =20 +#define BHYVE_ACPI_PHYSICAL_ADDRESS ((UINTN)0x000F2400) +#define BHYVE_BIOS_PHYSICAL_END ((UINTN)0x00100000) + +#pragma pack (1) + +typedef struct +{ + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 Tables[0]; +} EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE; + +#pragma pack () + STATIC EFI_STATUS EFIAPI @@ -130,3 +143,231 @@ BhyveInstallAcpiTable ( TableKey ); } + +/** + Get the address of bhyve's ACPI Root System Description Pointer (RSDP). + + @param RsdpPtr Return pointer to RSDP. + + @return EFI_SUCCESS Bhyve's RSDP successfully found. + @return EFI_NOT_FOUND Couldn't find bhyve's RSDP. + @return EFI_UNSUPPORTED Revision is lower than 2. + @return EFI_PROTOCOL_ERROR Invalid RSDP found. + +**/ +EFI_STATUS +EFIAPI +BhyveGetAcpiRsdp ( + OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr + ) +{ + UINTN RsdpAddress; + EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; + + if (RsdpPtr =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Detect the RSDP + // + for (RsdpAddress =3D BHYVE_ACPI_PHYSICAL_ADDRESS; + RsdpAddress < BHYVE_BIOS_PHYSICAL_END; + RsdpAddress +=3D 0x10) { + Rsdp =3D NUMERIC_VALUE_AS_POINTER ( + EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER, + RsdpAddress + ); + if (Rsdp->Signature !=3D EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_= SIGNATURE) { + continue; + } + if (Rsdp->Revision < 2) { + DEBUG ((DEBUG_INFO, "%a: unsupported RSDP found\n", __FUNCTION__)); + return EFI_UNSUPPORTED; + } + + // + // For ACPI 1.0/2.0/3.0 the checksum of first 20 bytes should be 0. + // For ACPI 2.0/3.0 the checksum of the entire table should be 0. + // + UINT8 Sum =3D CalculateCheckSum8 ( + (CONST UINT8 *)Rsdp, + sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER) + ); + if (Sum !=3D 0) { + DEBUG ((DEBUG_INFO, "%a: RSDP header checksum not valid: 0x%02x\n", + __FUNCTION__, Sum)); + return EFI_PROTOCOL_ERROR; + } + Sum =3D CalculateCheckSum8 ( + (CONST UINT8 *)Rsdp, + sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER) + ); + if (Sum !=3D 0) { + DEBUG ((DEBUG_INFO, "%a: RSDP table checksum not valid: 0x%02x\n", + __FUNCTION__, Sum)); + return EFI_PROTOCOL_ERROR; + } + + // + // RSDP was found and is valid + // + *RsdpPtr =3D Rsdp; + + return EFI_SUCCESS; + } + + DEBUG ((DEBUG_INFO, "%a: RSDP not found\n", __FUNCTION__)); + return EFI_NOT_FOUND; +} + +/** + Get bhyve's ACPI tables from the RSDP. And install bhyve's ACPI tables + into the RSDT/XSDT using InstallAcpiTable. + + @param AcpiProtocol Protocol instance pointer. + + @return EFI_SUCCESS All tables were successfully inserted. + @return EFI_UNSUPPORTED Bhyve's ACPI tables doesn't include a XSDT. + @return EFI_PROTOCOL_ERROR Invalid XSDT found. + + @return Error codes propagated from underlying funct= ions. +**/ +EFI_STATUS +EFIAPI +InstallBhyveTables ( + IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol + ) +{ + EFI_STATUS Status; + UINTN TableHandle; + EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; + EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; + EFI_ACPI_DESCRIPTION_HEADER *Dsdt; + + Rsdp =3D NULL; + Facs =3D NULL; + Dsdt =3D NULL; + + // + // Try to find bhyve ACPI tables + // + Status =3D BhyveGetAcpiRsdp (&Rsdp); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: can't get RSDP (%r)\n", __FUNCTION__, Status)= ); + return Status; + } + + // + // Bhyve should always provide a XSDT + // + EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE * CONST Xsdt =3D + NUMERIC_VALUE_AS_POINTER ( + EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE, + Rsdp->XsdtAddress + ); + if (Xsdt =3D=3D NULL) { + DEBUG ((DEBUG_INFO, "%a: XSDT not found\n", __FUNCTION__)); + return EFI_UNSUPPORTED; + } + if (Xsdt->Header.Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER)) { + DEBUG ((DEBUG_INFO, "%a: invalid XSDT length\n", __FUNCTION__)); + return EFI_PROTOCOL_ERROR; + } + + // + // Install ACPI tables + // + CONST UINTN NumberOfTableEntries =3D + (Xsdt->Header.Length - sizeof (Xsdt->Header)) / sizeof (UINT64); + for (UINTN Index =3D 0; Index < NumberOfTableEntries; Index++) { + EFI_ACPI_DESCRIPTION_HEADER * CONST CurrentTable =3D + NUMERIC_VALUE_AS_POINTER ( + EFI_ACPI_DESCRIPTION_HEADER, + Xsdt->Tables[Index] + ); + Status =3D AcpiProtocol->InstallAcpiTable ( + AcpiProtocol, + CurrentTable, + CurrentTable->Length, + &TableHandle + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: failed to install ACPI table %c%c%c%c (%r)\= n", + __FUNCTION__, + NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[0], + NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[1], + NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[2], + NUMERIC_VALUE_AS_POINTER (UINT8, CurrentTable->Signature)[3], + Status)); + return Status; + } + + if (CurrentTable->Signature =3D=3D EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION= _TABLE_SIGNATURE) { + EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE * CONST Fadt =3D + (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE * CONST)CurrentTable; + if (Fadt->XFirmwareCtrl) { + Facs =3D NUMERIC_VALUE_AS_POINTER ( + EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE, + Fadt->XFirmwareCtrl + ); + } else { + Facs =3D NUMERIC_VALUE_AS_POINTER ( + EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE, + Fadt->FirmwareCtrl + ); + } + if (Fadt->XDsdt) { + Dsdt =3D NUMERIC_VALUE_AS_POINTER ( + EFI_ACPI_DESCRIPTION_HEADER, + Fadt->XDsdt + ); + } else { + Dsdt =3D NUMERIC_VALUE_AS_POINTER ( + EFI_ACPI_DESCRIPTION_HEADER, + Fadt->Dsdt + ); + } + } + } + + // + // Install FACS + // + if (Facs !=3D NULL) { + Status =3D AcpiProtocol->InstallAcpiTable ( + AcpiProtocol, + Facs, + Facs->Length, + &TableHandle + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: failed to install FACS (%r)\n", __FUNCTION_= _, + Status)); + return Status; + } + } + + // + // Install DSDT + // If it's not found, something bad happened. Don't continue execution. + // + if (Dsdt =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a: failed to find DSDT\n", __FUNCTION__)); + CpuDeadLoop (); + } + + Status =3D AcpiProtocol->InstallAcpiTable ( + AcpiProtocol, + Dsdt, + Dsdt->Length, + &TableHandle + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: failed to install DSDT (%r)\n", __FUNCTION__, + Status)); + return Status; + } + + return EFI_SUCCESS; +} --=20 2.33.0.windows.2 Beckhoff Automation GmbH & Co. KG | Managing Director: Dipl. Phys. Hans Bec= khoff Registered office: Verl, Germany | Register court: Guetersloh HRA 7075