Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102627510
D36983.id111782.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
56 KB
Referenced Files
None
Subscribers
None
D36983.id111782.diff
View Options
diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile
--- a/usr.sbin/bhyve/Makefile
+++ b/usr.sbin/bhyve/Makefile
@@ -18,6 +18,7 @@
atkbdc.c \
acpi.c \
audio.c \
+ basl.c \
bhyvegc.c \
bhyverun.c \
block_if.c \
diff --git a/usr.sbin/bhyve/acpi.c b/usr.sbin/bhyve/acpi.c
--- a/usr.sbin/bhyve/acpi.c
+++ b/usr.sbin/bhyve/acpi.c
@@ -38,20 +38,6 @@
*
* The tables are placed in the guest's ROM area just below 1MB physical,
* above the MPTable.
- *
- * Layout (No longer correct at FADT and beyond due to properly
- * calculating the size of the MADT to allow for changes to
- * VM_MAXCPU above 21 which overflows this layout.)
- * ------
- * RSDP -> 0xf2400 (36 bytes fixed)
- * RSDT -> 0xf2440 (36 bytes + 4*7 table addrs, 4 used)
- * XSDT -> 0xf2480 (36 bytes + 8*7 table addrs, 4 used)
- * MADT -> 0xf2500 (depends on #CPUs)
- * FADT -> 0xf2600 (268 bytes)
- * HPET -> 0xf2740 (56 bytes)
- * MCFG -> 0xf2780 (60 bytes)
- * FACS -> 0xf27C0 (64 bytes)
- * DSDT -> 0xf2800 (variable - can go up to 0x100000)
*/
#include <sys/cdefs.h>
@@ -61,6 +47,7 @@
#include <sys/errno.h>
#include <sys/stat.h>
+#include <err.h>
#include <paths.h>
#include <stdarg.h>
#include <stdio.h>
@@ -73,44 +60,21 @@
#include "bhyverun.h"
#include "acpi.h"
+#include "basl.h"
#include "pci_emul.h"
#include "vmgenc.h"
-/*
- * Define the base address of the ACPI tables, the sizes of some tables,
- * and the offsets to the individual tables,
- */
-#define BHYVE_ACPI_BASE 0xf2400
-#define RSDT_OFFSET 0x040
-#define XSDT_OFFSET 0x080
-#define MADT_OFFSET 0x100
-/*
- * The MADT consists of:
- * 44 Fixed Header
- * 8 * maxcpu Processor Local APIC entries
- * 12 I/O APIC entry
- * 2 * 10 Interrupt Source Override entries
- * 6 Local APIC NMI entry
- */
-#define MADT_SIZE roundup2((44 + basl_ncpu*8 + 12 + 2*10 + 6), 0x100)
-#define FADT_OFFSET (MADT_OFFSET + MADT_SIZE)
-#define FADT_SIZE 0x140
-#define HPET_OFFSET (FADT_OFFSET + FADT_SIZE)
-#define HPET_SIZE 0x40
-#define MCFG_OFFSET (HPET_OFFSET + HPET_SIZE)
-#define MCFG_SIZE 0x40
-#define FACS_OFFSET (MCFG_OFFSET + MCFG_SIZE)
-#define FACS_SIZE 0x40
-#define DSDT_OFFSET (FACS_OFFSET + FACS_SIZE)
-
#define BHYVE_ASL_TEMPLATE "bhyve.XXXXXXX"
#define BHYVE_ASL_SUFFIX ".aml"
#define BHYVE_ASL_COMPILER "/usr/sbin/iasl"
+#define BHYVE_ADDRESS_IOAPIC 0xFEC00000
+#define BHYVE_ADDRESS_HPET 0xFED00000
+#define BHYVE_ADDRESS_LAPIC 0xFEE00000
+
static int basl_keep_temps;
static int basl_verbose_iasl;
static int basl_ncpu;
-static uint32_t basl_acpi_base = BHYVE_ACPI_BASE;
static uint32_t hpet_capabilities;
/*
@@ -127,6 +91,9 @@
static int dsdt_indent_level;
static int dsdt_error;
+struct basl_table *rsdt;
+struct basl_table *xsdt;
+
struct basl_fio {
int fd;
FILE *fp;
@@ -139,514 +106,6 @@
#define EFFLUSH(x) \
if (fflush(x) != 0) goto err_exit;
-static int
-basl_fwrite_rsdp(FILE *fp)
-{
- EFPRINTF(fp, "/*\n");
- EFPRINTF(fp, " * bhyve RSDP template\n");
- EFPRINTF(fp, " */\n");
- EFPRINTF(fp, "[0008]\t\tSignature : \"RSD PTR \"\n");
- EFPRINTF(fp, "[0001]\t\tChecksum : 43\n");
- EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n");
- EFPRINTF(fp, "[0001]\t\tRevision : 02\n");
- EFPRINTF(fp, "[0004]\t\tRSDT Address : %08X\n",
- basl_acpi_base + RSDT_OFFSET);
- EFPRINTF(fp, "[0004]\t\tLength : 00000024\n");
- EFPRINTF(fp, "[0008]\t\tXSDT Address : 00000000%08X\n",
- basl_acpi_base + XSDT_OFFSET);
- EFPRINTF(fp, "[0001]\t\tExtended Checksum : 00\n");
- EFPRINTF(fp, "[0003]\t\tReserved : 000000\n");
-
- EFFLUSH(fp);
-
- return (0);
-
-err_exit:
- return (errno);
-}
-
-static int
-basl_fwrite_rsdt(FILE *fp)
-{
- EFPRINTF(fp, "/*\n");
- EFPRINTF(fp, " * bhyve RSDT template\n");
- EFPRINTF(fp, " */\n");
- EFPRINTF(fp, "[0004]\t\tSignature : \"RSDT\"\n");
- EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n");
- EFPRINTF(fp, "[0001]\t\tRevision : 01\n");
- EFPRINTF(fp, "[0001]\t\tChecksum : 00\n");
- EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n");
- EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVRSDT \"\n");
- EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n");
- /* iasl will fill in the compiler ID/revision fields */
- EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n");
- EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n");
- EFPRINTF(fp, "\n");
-
- /* Add in pointers to the MADT, FADT and HPET */
- EFPRINTF(fp, "[0004]\t\tACPI Table Address 0 : %08X\n",
- basl_acpi_base + MADT_OFFSET);
- EFPRINTF(fp, "[0004]\t\tACPI Table Address 1 : %08X\n",
- basl_acpi_base + FADT_OFFSET);
- EFPRINTF(fp, "[0004]\t\tACPI Table Address 2 : %08X\n",
- basl_acpi_base + HPET_OFFSET);
- EFPRINTF(fp, "[0004]\t\tACPI Table Address 3 : %08X\n",
- basl_acpi_base + MCFG_OFFSET);
-
- EFFLUSH(fp);
-
- return (0);
-
-err_exit:
- return (errno);
-}
-
-static int
-basl_fwrite_xsdt(FILE *fp)
-{
- EFPRINTF(fp, "/*\n");
- EFPRINTF(fp, " * bhyve XSDT template\n");
- EFPRINTF(fp, " */\n");
- EFPRINTF(fp, "[0004]\t\tSignature : \"XSDT\"\n");
- EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n");
- EFPRINTF(fp, "[0001]\t\tRevision : 01\n");
- EFPRINTF(fp, "[0001]\t\tChecksum : 00\n");
- EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n");
- EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVXSDT \"\n");
- EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n");
- /* iasl will fill in the compiler ID/revision fields */
- EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n");
- EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n");
- EFPRINTF(fp, "\n");
-
- /* Add in pointers to the MADT, FADT and HPET */
- EFPRINTF(fp, "[0004]\t\tACPI Table Address 0 : 00000000%08X\n",
- basl_acpi_base + MADT_OFFSET);
- EFPRINTF(fp, "[0004]\t\tACPI Table Address 1 : 00000000%08X\n",
- basl_acpi_base + FADT_OFFSET);
- EFPRINTF(fp, "[0004]\t\tACPI Table Address 2 : 00000000%08X\n",
- basl_acpi_base + HPET_OFFSET);
- EFPRINTF(fp, "[0004]\t\tACPI Table Address 3 : 00000000%08X\n",
- basl_acpi_base + MCFG_OFFSET);
-
- EFFLUSH(fp);
-
- return (0);
-
-err_exit:
- return (errno);
-}
-
-static int
-basl_fwrite_madt(FILE *fp)
-{
- int i;
-
- EFPRINTF(fp, "/*\n");
- EFPRINTF(fp, " * bhyve MADT template\n");
- EFPRINTF(fp, " */\n");
- EFPRINTF(fp, "[0004]\t\tSignature : \"APIC\"\n");
- EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n");
- EFPRINTF(fp, "[0001]\t\tRevision : 01\n");
- EFPRINTF(fp, "[0001]\t\tChecksum : 00\n");
- EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n");
- EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVMADT \"\n");
- EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n");
-
- /* iasl will fill in the compiler ID/revision fields */
- EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n");
- EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n");
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp, "[0004]\t\tLocal Apic Address : FEE00000\n");
- EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000001\n");
- EFPRINTF(fp, "\t\t\tPC-AT Compatibility : 1\n");
- EFPRINTF(fp, "\n");
-
- /* Add a Processor Local APIC entry for each CPU */
- for (i = 0; i < basl_ncpu; i++) {
- EFPRINTF(fp, "[0001]\t\tSubtable Type : 00\n");
- EFPRINTF(fp, "[0001]\t\tLength : 08\n");
- /* iasl expects hex values for the proc and apic id's */
- EFPRINTF(fp, "[0001]\t\tProcessor ID : %02x\n", i);
- EFPRINTF(fp, "[0001]\t\tLocal Apic ID : %02x\n", i);
- EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000001\n");
- EFPRINTF(fp, "\t\t\tProcessor Enabled : 1\n");
- EFPRINTF(fp, "\t\t\tRuntime Online Capable : 0\n");
- EFPRINTF(fp, "\n");
- }
-
- /* Always a single IOAPIC entry, with ID 0 */
- EFPRINTF(fp, "[0001]\t\tSubtable Type : 01\n");
- EFPRINTF(fp, "[0001]\t\tLength : 0C\n");
- /* iasl expects a hex value for the i/o apic id */
- EFPRINTF(fp, "[0001]\t\tI/O Apic ID : %02x\n", 0);
- EFPRINTF(fp, "[0001]\t\tReserved : 00\n");
- EFPRINTF(fp, "[0004]\t\tAddress : fec00000\n");
- EFPRINTF(fp, "[0004]\t\tInterrupt : 00000000\n");
- EFPRINTF(fp, "\n");
-
- /* Legacy IRQ0 is connected to pin 2 of the IOAPIC */
- EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n");
- EFPRINTF(fp, "[0001]\t\tLength : 0A\n");
- EFPRINTF(fp, "[0001]\t\tBus : 00\n");
- EFPRINTF(fp, "[0001]\t\tSource : 00\n");
- EFPRINTF(fp, "[0004]\t\tInterrupt : 00000002\n");
- EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0005\n");
- EFPRINTF(fp, "\t\t\tPolarity : 1\n");
- EFPRINTF(fp, "\t\t\tTrigger Mode : 1\n");
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n");
- EFPRINTF(fp, "[0001]\t\tLength : 0A\n");
- EFPRINTF(fp, "[0001]\t\tBus : 00\n");
- EFPRINTF(fp, "[0001]\t\tSource : %02X\n", SCI_INT);
- EFPRINTF(fp, "[0004]\t\tInterrupt : %08X\n", SCI_INT);
- EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0000\n");
- EFPRINTF(fp, "\t\t\tPolarity : 3\n");
- EFPRINTF(fp, "\t\t\tTrigger Mode : 3\n");
- EFPRINTF(fp, "\n");
-
- /* Local APIC NMI is connected to LINT 1 on all CPUs */
- EFPRINTF(fp, "[0001]\t\tSubtable Type : 04\n");
- EFPRINTF(fp, "[0001]\t\tLength : 06\n");
- EFPRINTF(fp, "[0001]\t\tProcessor ID : FF\n");
- EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0005\n");
- EFPRINTF(fp, "\t\t\tPolarity : 1\n");
- EFPRINTF(fp, "\t\t\tTrigger Mode : 1\n");
- EFPRINTF(fp, "[0001]\t\tInterrupt Input LINT : 01\n");
- EFPRINTF(fp, "\n");
-
- EFFLUSH(fp);
-
- return (0);
-
-err_exit:
- return (errno);
-}
-
-static int
-basl_fwrite_fadt(FILE *fp)
-{
- EFPRINTF(fp, "/*\n");
- EFPRINTF(fp, " * bhyve FADT template\n");
- EFPRINTF(fp, " */\n");
- EFPRINTF(fp, "[0004]\t\tSignature : \"FACP\"\n");
- EFPRINTF(fp, "[0004]\t\tTable Length : 0000010C\n");
- EFPRINTF(fp, "[0001]\t\tRevision : 05\n");
- EFPRINTF(fp, "[0001]\t\tChecksum : 00\n");
- EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n");
- EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVFACP \"\n");
- EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n");
- /* iasl will fill in the compiler ID/revision fields */
- EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n");
- EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n");
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp, "[0004]\t\tFACS Address : %08X\n",
- basl_acpi_base + FACS_OFFSET);
- EFPRINTF(fp, "[0004]\t\tDSDT Address : %08X\n",
- basl_acpi_base + DSDT_OFFSET);
- EFPRINTF(fp, "[0001]\t\tModel : 01\n");
- EFPRINTF(fp, "[0001]\t\tPM Profile : 00 [Unspecified]\n");
- EFPRINTF(fp, "[0002]\t\tSCI Interrupt : %04X\n",
- SCI_INT);
- EFPRINTF(fp, "[0004]\t\tSMI Command Port : %08X\n",
- SMI_CMD);
- EFPRINTF(fp, "[0001]\t\tACPI Enable Value : %02X\n",
- BHYVE_ACPI_ENABLE);
- EFPRINTF(fp, "[0001]\t\tACPI Disable Value : %02X\n",
- BHYVE_ACPI_DISABLE);
- EFPRINTF(fp, "[0001]\t\tS4BIOS Command : 00\n");
- EFPRINTF(fp, "[0001]\t\tP-State Control : 00\n");
- EFPRINTF(fp, "[0004]\t\tPM1A Event Block Address : %08X\n",
- PM1A_EVT_ADDR);
- EFPRINTF(fp, "[0004]\t\tPM1B Event Block Address : 00000000\n");
- EFPRINTF(fp, "[0004]\t\tPM1A Control Block Address : %08X\n",
- PM1A_CNT_ADDR);
- EFPRINTF(fp, "[0004]\t\tPM1B Control Block Address : 00000000\n");
- EFPRINTF(fp, "[0004]\t\tPM2 Control Block Address : 00000000\n");
- EFPRINTF(fp, "[0004]\t\tPM Timer Block Address : %08X\n",
- IO_PMTMR);
- EFPRINTF(fp, "[0004]\t\tGPE0 Block Address : %08X\n", IO_GPE0_BLK);
- EFPRINTF(fp, "[0004]\t\tGPE1 Block Address : 00000000\n");
- EFPRINTF(fp, "[0001]\t\tPM1 Event Block Length : 04\n");
- EFPRINTF(fp, "[0001]\t\tPM1 Control Block Length : 02\n");
- EFPRINTF(fp, "[0001]\t\tPM2 Control Block Length : 00\n");
- EFPRINTF(fp, "[0001]\t\tPM Timer Block Length : 04\n");
- EFPRINTF(fp, "[0001]\t\tGPE0 Block Length : %02x\n", IO_GPE0_LEN);
- EFPRINTF(fp, "[0001]\t\tGPE1 Block Length : 00\n");
- EFPRINTF(fp, "[0001]\t\tGPE1 Base Offset : 00\n");
- EFPRINTF(fp, "[0001]\t\t_CST Support : 00\n");
- EFPRINTF(fp, "[0002]\t\tC2 Latency : 0000\n");
- EFPRINTF(fp, "[0002]\t\tC3 Latency : 0000\n");
- EFPRINTF(fp, "[0002]\t\tCPU Cache Size : 0000\n");
- EFPRINTF(fp, "[0002]\t\tCache Flush Stride : 0000\n");
- EFPRINTF(fp, "[0001]\t\tDuty Cycle Offset : 00\n");
- EFPRINTF(fp, "[0001]\t\tDuty Cycle Width : 00\n");
- EFPRINTF(fp, "[0001]\t\tRTC Day Alarm Index : 00\n");
- EFPRINTF(fp, "[0001]\t\tRTC Month Alarm Index : 00\n");
- EFPRINTF(fp, "[0001]\t\tRTC Century Index : 32\n");
- EFPRINTF(fp, "[0002]\t\tBoot Flags (decoded below) : 0000\n");
- EFPRINTF(fp, "\t\t\tLegacy Devices Supported (V2) : 0\n");
- EFPRINTF(fp, "\t\t\t8042 Present on ports 60/64 (V2) : 0\n");
- EFPRINTF(fp, "\t\t\tVGA Not Present (V4) : 1\n");
- EFPRINTF(fp, "\t\t\tMSI Not Supported (V4) : 0\n");
- EFPRINTF(fp, "\t\t\tPCIe ASPM Not Supported (V4) : 1\n");
- EFPRINTF(fp, "\t\t\tCMOS RTC Not Present (V5) : 0\n");
- EFPRINTF(fp, "[0001]\t\tReserved : 00\n");
- EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000000\n");
- EFPRINTF(fp, "\t\t\tWBINVD instruction is operational (V1) : 1\n");
- EFPRINTF(fp, "\t\t\tWBINVD flushes all caches (V1) : 0\n");
- EFPRINTF(fp, "\t\t\tAll CPUs support C1 (V1) : 1\n");
- EFPRINTF(fp, "\t\t\tC2 works on MP system (V1) : 0\n");
- EFPRINTF(fp, "\t\t\tControl Method Power Button (V1) : 0\n");
- EFPRINTF(fp, "\t\t\tControl Method Sleep Button (V1) : 1\n");
- EFPRINTF(fp, "\t\t\tRTC wake not in fixed reg space (V1) : 0\n");
- EFPRINTF(fp, "\t\t\tRTC can wake system from S4 (V1) : 0\n");
- EFPRINTF(fp, "\t\t\t32-bit PM Timer (V1) : 1\n");
- EFPRINTF(fp, "\t\t\tDocking Supported (V1) : 0\n");
- EFPRINTF(fp, "\t\t\tReset Register Supported (V2) : 1\n");
- EFPRINTF(fp, "\t\t\tSealed Case (V3) : 0\n");
- EFPRINTF(fp, "\t\t\tHeadless - No Video (V3) : 1\n");
- EFPRINTF(fp, "\t\t\tUse native instr after SLP_TYPx (V3) : 0\n");
- EFPRINTF(fp, "\t\t\tPCIEXP_WAK Bits Supported (V4) : 0\n");
- EFPRINTF(fp, "\t\t\tUse Platform Timer (V4) : 0\n");
- EFPRINTF(fp, "\t\t\tRTC_STS valid on S4 wake (V4) : 0\n");
- EFPRINTF(fp, "\t\t\tRemote Power-on capable (V4) : 0\n");
- EFPRINTF(fp, "\t\t\tUse APIC Cluster Model (V4) : 0\n");
- EFPRINTF(fp, "\t\t\tUse APIC Physical Destination Mode (V4) : 1\n");
- EFPRINTF(fp, "\t\t\tHardware Reduced (V5) : 0\n");
- EFPRINTF(fp, "\t\t\tLow Power S0 Idle (V5) : 0\n");
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp,
- "[0012]\t\tReset Register : [Generic Address Structure]\n");
- EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : 08\n");
- EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
- EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000CF9\n");
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp, "[0001]\t\tValue to cause reset : 06\n");
- EFPRINTF(fp, "[0002]\t\tARM Flags (decoded below): 0000\n");
- EFPRINTF(fp, "\t\t\tPSCI Compliant : 0\n");
- EFPRINTF(fp, "\t\t\tMust use HVC for PSCI : 0\n");
- EFPRINTF(fp, "[0001]\t\tFADT Minor Revision : 01\n");
- EFPRINTF(fp, "[0008]\t\tFACS Address : 00000000%08X\n",
- basl_acpi_base + FACS_OFFSET);
- EFPRINTF(fp, "[0008]\t\tDSDT Address : 00000000%08X\n",
- basl_acpi_base + DSDT_OFFSET);
- EFPRINTF(fp,
- "[0012]\t\tPM1A Event Block : [Generic Address Structure]\n");
- EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : 20\n");
- EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
- EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 02 [Word Access:16]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n",
- PM1A_EVT_ADDR);
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp,
- "[0012]\t\tPM1B Event Block : [Generic Address Structure]\n");
- EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : 00\n");
- EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
- EFPRINTF(fp,
- "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp,
- "[0012]\t\tPM1A Control Block : [Generic Address Structure]\n");
- EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : 10\n");
- EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
- EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 02 [Word Access:16]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n",
- PM1A_CNT_ADDR);
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp,
- "[0012]\t\tPM1B Control Block : [Generic Address Structure]\n");
- EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : 00\n");
- EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
- EFPRINTF(fp,
- "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp,
- "[0012]\t\tPM2 Control Block : [Generic Address Structure]\n");
- EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : 08\n");
- EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
- EFPRINTF(fp,
- "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
- EFPRINTF(fp, "\n");
-
- /* Valid for bhyve */
- EFPRINTF(fp,
- "[0012]\t\tPM Timer Block : [Generic Address Structure]\n");
- EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : 20\n");
- EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
- EFPRINTF(fp,
- "[0001]\t\tEncoded Access Width : 03 [DWord Access:32]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n",
- IO_PMTMR);
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp, "[0012]\t\tGPE0 Block : [Generic Address Structure]\n");
- EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : %02x\n", IO_GPE0_LEN * 8);
- EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
- EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : %016X\n", IO_GPE0_BLK);
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp, "[0012]\t\tGPE1 Block : [Generic Address Structure]\n");
- EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : 00\n");
- EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
- EFPRINTF(fp,
- "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp,
- "[0012]\t\tSleep Control Register : [Generic Address Structure]\n");
- EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : 08\n");
- EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
- EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp,
- "[0012]\t\tSleep Status Register : [Generic Address Structure]\n");
- EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : 08\n");
- EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
- EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n");
-
- EFFLUSH(fp);
-
- return (0);
-
-err_exit:
- return (errno);
-}
-
-static int
-basl_fwrite_hpet(FILE *fp)
-{
- EFPRINTF(fp, "/*\n");
- EFPRINTF(fp, " * bhyve HPET template\n");
- EFPRINTF(fp, " */\n");
- EFPRINTF(fp, "[0004]\t\tSignature : \"HPET\"\n");
- EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n");
- EFPRINTF(fp, "[0001]\t\tRevision : 01\n");
- EFPRINTF(fp, "[0001]\t\tChecksum : 00\n");
- EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n");
- EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVHPET \"\n");
- EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n");
-
- /* iasl will fill in the compiler ID/revision fields */
- EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n");
- EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n");
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp, "[0004]\t\tHardware Block ID : %08X\n", hpet_capabilities);
- EFPRINTF(fp,
- "[0012]\t\tTimer Block Register : [Generic Address Structure]\n");
- EFPRINTF(fp, "[0001]\t\tSpace ID : 00 [SystemMemory]\n");
- EFPRINTF(fp, "[0001]\t\tBit Width : 00\n");
- EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
- EFPRINTF(fp,
- "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 00000000FED00000\n");
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp, "[0001]\t\tSequence Number : 00\n");
- EFPRINTF(fp, "[0002]\t\tMinimum Clock Ticks : 0000\n");
- EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000001\n");
- EFPRINTF(fp, "\t\t\t4K Page Protect : 1\n");
- EFPRINTF(fp, "\t\t\t64K Page Protect : 0\n");
- EFPRINTF(fp, "\n");
-
- EFFLUSH(fp);
-
- return (0);
-
-err_exit:
- return (errno);
-}
-
-static int
-basl_fwrite_mcfg(FILE *fp)
-{
- EFPRINTF(fp, "/*\n");
- EFPRINTF(fp, " * bhyve MCFG template\n");
- EFPRINTF(fp, " */\n");
- EFPRINTF(fp, "[0004]\t\tSignature : \"MCFG\"\n");
- EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n");
- EFPRINTF(fp, "[0001]\t\tRevision : 01\n");
- EFPRINTF(fp, "[0001]\t\tChecksum : 00\n");
- EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n");
- EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVMCFG \"\n");
- EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n");
-
- /* iasl will fill in the compiler ID/revision fields */
- EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n");
- EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n");
- EFPRINTF(fp, "[0008]\t\tReserved : 0\n");
- EFPRINTF(fp, "\n");
-
- EFPRINTF(fp, "[0008]\t\tBase Address : %016lX\n", pci_ecfg_base());
- EFPRINTF(fp, "[0002]\t\tSegment Group Number : 0000\n");
- EFPRINTF(fp, "[0001]\t\tStart Bus Number : 00\n");
- EFPRINTF(fp, "[0001]\t\tEnd Bus Number : FF\n");
- EFPRINTF(fp, "[0004]\t\tReserved : 0\n");
- EFFLUSH(fp);
- return (0);
-err_exit:
- return (errno);
-}
-
-static int
-basl_fwrite_facs(FILE *fp)
-{
- EFPRINTF(fp, "/*\n");
- EFPRINTF(fp, " * bhyve FACS template\n");
- EFPRINTF(fp, " */\n");
- EFPRINTF(fp, "[0004]\t\tSignature : \"FACS\"\n");
- EFPRINTF(fp, "[0004]\t\tLength : 00000040\n");
- EFPRINTF(fp, "[0004]\t\tHardware Signature : 00000000\n");
- EFPRINTF(fp, "[0004]\t\t32 Firmware Waking Vector : 00000000\n");
- EFPRINTF(fp, "[0004]\t\tGlobal Lock : 00000000\n");
- EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000000\n");
- EFPRINTF(fp, "\t\t\tS4BIOS Support Present : 0\n");
- EFPRINTF(fp, "\t\t\t64-bit Wake Supported (V2) : 0\n");
- EFPRINTF(fp,
- "[0008]\t\t64 Firmware Waking Vector : 0000000000000000\n");
- EFPRINTF(fp, "[0001]\t\tVersion : 02\n");
- EFPRINTF(fp, "[0003]\t\tReserved : 000000\n");
- EFPRINTF(fp, "[0004]\t\tOspmFlags (decoded below) : 00000000\n");
- EFPRINTF(fp, "\t\t\t64-bit Wake Env Required (V2) : 0\n");
-
- EFFLUSH(fp);
-
- return (0);
-
-err_exit:
- return (errno);
-}
-
/*
* Helper routines for writing to the DSDT from other modules.
*/
@@ -731,8 +190,10 @@
dsdt_line("/*");
dsdt_line(" * bhyve DSDT template");
dsdt_line(" */");
- dsdt_line("DefinitionBlock (\"bhyve_dsdt.aml\", \"DSDT\", 2,"
- "\"BHYVE \", \"BVDSDT \", 0x00000001)");
+ dsdt_line("DefinitionBlock (\"bhyve_dsdt.aml\", \"%s\", 0x%02x,"
+ "\"%s\", \"%s\", 0x%08x)",
+ ACPI_SIG_DSDT, BASL_REVISION_DSDT, BASL_OEM_ID,
+ BASL_OEM_TABLE_ID_DSDT, BASL_OEM_REVISION_DSDT);
dsdt_line("{");
dsdt_line(" Name (_S5, Package ()");
dsdt_line(" {");
@@ -835,26 +296,33 @@
}
static int
-basl_load(struct vmctx *ctx, int fd, uint64_t off)
+basl_load(struct vmctx *ctx, int fd)
{
struct stat sb;
- void *gaddr;
+ void *addr;
if (fstat(fd, &sb) < 0)
return (errno);
- gaddr = paddr_guest2host(ctx, basl_acpi_base + off, sb.st_size);
- if (gaddr == NULL)
+ addr = calloc(1, sb.st_size);
+ if (addr == NULL)
return (EFAULT);
- if (read(fd, gaddr, sb.st_size) < 0)
+ if (read(fd, addr, sb.st_size) < 0)
return (errno);
+ struct basl_table *table;
+
+ uint8_t name[ACPI_NAMESEG_SIZE + 1] = { 0 };
+ memcpy(name, addr, sizeof(name) - 1 /* last char is '\0' */);
+ BASL_EXEC(basl_table_create(&table, ctx, name, BASL_TABLE_ALIGNMENT));
+ BASL_EXEC(basl_table_append_bytes(table, addr, sb.st_size));
+
return (0);
}
static int
-basl_compile(struct vmctx *ctx, int (*fwrite_section)(FILE *), uint64_t offset)
+basl_compile(struct vmctx *ctx, int (*fwrite_section)(FILE *))
{
struct basl_fio io[2];
static char iaslbuf[3*MAXPATHLEN + 10];
@@ -888,7 +356,7 @@
* Copy the aml output file into guest
* memory at the specified location
*/
- err = basl_load(ctx, io[1].fd, offset);
+ err = basl_load(ctx, io[1].fd);
}
}
basl_end(&io[0], &io[1]);
@@ -943,6 +411,429 @@
return (err);
}
+static int
+build_dsdt(struct vmctx *const ctx)
+{
+ BASL_EXEC(basl_compile(ctx, basl_fwrite_dsdt));
+
+ return (0);
+}
+
+static int
+build_facs(struct vmctx *const ctx)
+{
+ struct basl_table *facs;
+
+ BASL_EXEC(basl_table_create(&facs, ctx, ACPI_SIG_FACS,
+ BASL_TABLE_ALIGNMENT_FACS));
+
+ /* Signature */
+ BASL_EXEC(
+ basl_table_append_bytes(facs, ACPI_SIG_FACS, ACPI_NAMESEG_SIZE));
+ /* Length */
+ BASL_EXEC(basl_table_append_length(facs, 4));
+ /* Hardware Signature */
+ BASL_EXEC(basl_table_append_int(facs, 0, 4));
+ /* Firmware Waking Vector */
+ BASL_EXEC(basl_table_append_int(facs, 0, 4));
+ /* Global Lock */
+ BASL_EXEC(basl_table_append_int(facs, 0, 4));
+ /* Flags */
+ BASL_EXEC(basl_table_append_int(facs, 0, 4));
+ /* Extended Firmware Waking Vector */
+ BASL_EXEC(basl_table_append_int(facs, 0, 8));
+ /* Version */
+ BASL_EXEC(basl_table_append_int(facs, 2, 1));
+ /* Reserved */
+ BASL_EXEC(basl_table_append_int(facs, 0, 3));
+ /* OSPM Flags */
+ BASL_EXEC(basl_table_append_int(facs, 0, 4));
+ /* Reserved */
+ const uint8_t reserved[24] = { 0 };
+ BASL_EXEC(basl_table_append_bytes(facs, reserved, 24));
+
+ return (0);
+}
+
+static int
+build_fadt(struct vmctx *const ctx)
+{
+ struct basl_table *fadt;
+
+ BASL_EXEC(
+ basl_table_create(&fadt, ctx, ACPI_SIG_FADT, BASL_TABLE_ALIGNMENT));
+
+ /* Header */
+ BASL_EXEC(
+ basl_table_append_header(fadt, ACPI_SIG_FADT, BASL_REVISION_FADT,
+ BASL_OEM_ID, BASL_OEM_TABLE_ID_FADT, BASL_OEM_REVISION_FADT));
+ /* FACS Address */
+ BASL_EXEC(basl_table_append_pointer(fadt, ACPI_SIG_FACS,
+ ACPI_RSDT_ENTRY_SIZE));
+ /* DSDT Address */
+ BASL_EXEC(basl_table_append_pointer(fadt, ACPI_SIG_DSDT,
+ ACPI_RSDT_ENTRY_SIZE));
+ /* Eeserved */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 1));
+ /* Preferred_PM_Profile [Unspecified] */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 1));
+ /* SCI Interrupt */
+ BASL_EXEC(basl_table_append_int(fadt, SCI_INT, 2));
+ /* SMI Command Port */
+ BASL_EXEC(basl_table_append_int(fadt, SMI_CMD, 4));
+ /* ACPI Enable Value */
+ BASL_EXEC(basl_table_append_int(fadt, BHYVE_ACPI_ENABLE, 1));
+ /* ACPI Disable Value */
+ BASL_EXEC(basl_table_append_int(fadt, BHYVE_ACPI_DISABLE, 1));
+ /* S4BIOS Command */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 1));
+ /* P-State Control */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 1));
+ /* PM1A Event Block Address */
+ BASL_EXEC(basl_table_append_int(fadt, PM1A_EVT_ADDR, 4));
+ /* PM1B Event Block Address */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 4));
+ /* PM1A Control Block Address */
+ BASL_EXEC(basl_table_append_int(fadt, PM1A_CNT_ADDR, 4));
+ /* PM1B Control Block Address */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 4));
+ /* PM2 Control Block Address */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 4));
+ /* PM Timer Block Address */
+ BASL_EXEC(basl_table_append_int(fadt, IO_PMTMR, 4));
+ /* GPE0 Block Address */
+ BASL_EXEC(basl_table_append_int(fadt, IO_GPE0_BLK, 4));
+ /* GPE1 Block Address */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 4));
+ /* PM1 Event Block Length */
+ BASL_EXEC(basl_table_append_int(fadt, 4, 1));
+ /* PM1 Control Block Length */
+ BASL_EXEC(basl_table_append_int(fadt, 2, 1));
+ /* PM2 Control Block Length */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 1));
+ /* PM Timer Block Length */
+ BASL_EXEC(basl_table_append_int(fadt, 4, 1));
+ /* GPE0 Block Length */
+ BASL_EXEC(basl_table_append_int(fadt, IO_GPE0_LEN, 1));
+ /* GPE1 Block Length */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 1));
+ /* GPE1 Base Offset */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 1));
+ /* _CST Support */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 1));
+ /* C2 Latency */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 2));
+ /* C3 Latency */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 2));
+ /* CPU Cache Size */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 2));
+ /* Cache Flush Stride */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 2));
+ /* Duty Cycle Offset */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 1));
+ /* Duty Cycle Width */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 1));
+ /* RTC Day Alarm Index */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 1));
+ /* RTC Month Alarm Index */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 1));
+ /* RTC Centyr Index */
+ BASL_EXEC(basl_table_append_int(fadt, 32, 1));
+ /* Boot Flags */
+ BASL_EXEC(basl_table_append_int(fadt,
+ ACPI_FADT_NO_VGA | ACPI_FADT_NO_ASPM, 2));
+ /* Reserved */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 1));
+ /* Flags */
+ BASL_EXEC(basl_table_append_int(fadt,
+ ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED | ACPI_FADT_SLEEP_BUTTON |
+ ACPI_FADT_32BIT_TIMER | ACPI_FADT_RESET_REGISTER |
+ ACPI_FADT_HEADLESS | ACPI_FADT_APIC_PHYSICAL,
+ 4));
+ /* Reset Register */
+ BASL_EXEC(basl_table_append_gas(fadt, ACPI_ADR_SPACE_SYSTEM_IO, 8, 0,
+ ACPI_GAS_ACCESS_WIDTH_BYTE, 0xCF9));
+ /* Reset Value */
+ BASL_EXEC(basl_table_append_int(fadt, 6, 1));
+ /* ARM Boot Architecture Flags */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 2));
+ /* FADT Minor Version */
+ BASL_EXEC(basl_table_append_int(fadt, 1, 1));
+ /* Extended FACS Address */
+ BASL_EXEC(basl_table_append_pointer(fadt, ACPI_SIG_FACS,
+ ACPI_XSDT_ENTRY_SIZE));
+ /* Extended DSDT Address */
+ BASL_EXEC(basl_table_append_pointer(fadt, ACPI_SIG_DSDT,
+ ACPI_XSDT_ENTRY_SIZE));
+ /* Extended PM1A Event Block Address */
+ BASL_EXEC(basl_table_append_gas(fadt, ACPI_ADR_SPACE_SYSTEM_IO, 0x20, 0,
+ ACPI_GAS_ACCESS_WIDTH_WORD, PM1A_EVT_ADDR));
+ /* Extended PM1B Event Block Address */
+ BASL_EXEC(basl_table_append_gas(fadt, ACPI_ADR_SPACE_SYSTEM_IO, 0, 0,
+ ACPI_GAS_ACCESS_WIDTH_UNDEFINED, 0));
+ /* Extended PM1A Control Block Address */
+ BASL_EXEC(basl_table_append_gas(fadt, ACPI_ADR_SPACE_SYSTEM_IO, 0x10, 0,
+ ACPI_GAS_ACCESS_WIDTH_WORD, PM1A_CNT_ADDR));
+ /* Extended PM1B Control Block Address */
+ BASL_EXEC(basl_table_append_gas(fadt, ACPI_ADR_SPACE_SYSTEM_IO, 0, 0,
+ ACPI_GAS_ACCESS_WIDTH_UNDEFINED, 0));
+ /* Extended PM2 Control Block Address */
+ BASL_EXEC(basl_table_append_gas(fadt, ACPI_ADR_SPACE_SYSTEM_IO, 8, 0,
+ ACPI_GAS_ACCESS_WIDTH_UNDEFINED, 0));
+ /* Extended PM Timer Block Address */
+ BASL_EXEC(basl_table_append_gas(fadt, ACPI_ADR_SPACE_SYSTEM_IO, 0x20, 0,
+ ACPI_GAS_ACCESS_WIDTH_DWORD, IO_PMTMR));
+ /* Extended GPE0 Block Address */
+ BASL_EXEC(basl_table_append_gas(fadt, ACPI_ADR_SPACE_SYSTEM_IO,
+ IO_GPE0_LEN * 8, 0, ACPI_GAS_ACCESS_WIDTH_BYTE, IO_GPE0_BLK));
+ /* Extended GPE1 Block Address */
+ BASL_EXEC(basl_table_append_gas(fadt, ACPI_ADR_SPACE_SYSTEM_IO, 0, 0,
+ ACPI_GAS_ACCESS_WIDTH_UNDEFINED, 0));
+ /* Sleep Control Register Address */
+ BASL_EXEC(basl_table_append_gas(fadt, ACPI_ADR_SPACE_SYSTEM_IO, 8, 0,
+ ACPI_GAS_ACCESS_WIDTH_BYTE, 0));
+ /* Sleep Status Register Address */
+ BASL_EXEC(basl_table_append_gas(fadt, ACPI_ADR_SPACE_SYSTEM_IO, 8, 0,
+ ACPI_GAS_ACCESS_WIDTH_BYTE, 0));
+ /* Hypervisor Vendor Identity */
+ BASL_EXEC(basl_table_append_int(fadt, 0, 8));
+
+ BASL_EXEC(basl_table_append_pointer(rsdt, ACPI_SIG_FADT,
+ ACPI_RSDT_ENTRY_SIZE));
+ BASL_EXEC(basl_table_append_pointer(xsdt, ACPI_SIG_FADT,
+ ACPI_XSDT_ENTRY_SIZE));
+
+ return (0);
+}
+
+static int
+build_hpet(struct vmctx *const ctx)
+{
+ struct basl_table *hpet;
+
+ BASL_EXEC(
+ basl_table_create(&hpet, ctx, ACPI_SIG_HPET, BASL_TABLE_ALIGNMENT));
+
+ /* Header */
+ BASL_EXEC(
+ basl_table_append_header(hpet, ACPI_SIG_HPET, BASL_REVISION_HPET,
+ BASL_OEM_ID, BASL_OEM_TABLE_ID_HPET, BASL_OEM_REVISION_HPET));
+ /* Hardware Block ID */
+ BASL_EXEC(basl_table_append_int(hpet, hpet_capabilities, 4));
+ /* Timer Block Register */
+ BASL_EXEC(basl_table_append_gas(hpet, ACPI_ADR_SPACE_SYSTEM_MEMORY, 0,
+ 0, 0, BHYVE_ADDRESS_HPET));
+ /* Sequence Number */
+ BASL_EXEC(basl_table_append_int(hpet, 0, 1));
+ /* Minimum Clock Ticks */
+ BASL_EXEC(basl_table_append_int(hpet, 0, 2));
+ /* Flags */
+ BASL_EXEC(basl_table_append_int(hpet, ACPI_HPET_PAGE_PROTECT4, 4));
+
+ BASL_EXEC(basl_table_append_pointer(rsdt, ACPI_SIG_HPET,
+ ACPI_RSDT_ENTRY_SIZE));
+ BASL_EXEC(basl_table_append_pointer(xsdt, ACPI_SIG_HPET,
+ ACPI_XSDT_ENTRY_SIZE));
+
+ return (0);
+}
+
+static int
+build_madt(struct vmctx *const ctx)
+{
+ struct basl_table *madt;
+
+ BASL_EXEC(
+ basl_table_create(&madt, ctx, ACPI_SIG_MADT, BASL_TABLE_ALIGNMENT));
+
+ /* Header */
+ BASL_EXEC(
+ basl_table_append_header(madt, ACPI_SIG_MADT, BASL_REVISION_MADT,
+ BASL_OEM_ID, BASL_OEM_TABLE_ID_MADT, BASL_OEM_REVISION_MADT));
+ /* Local Apic Address */
+ BASL_EXEC(basl_table_append_int(madt, BHYVE_ADDRESS_LAPIC, 4));
+ /* Flags */
+ BASL_EXEC(basl_table_append_int(madt, ACPI_MADT_PCAT_COMPAT, 4));
+
+ /* Local APIC for each CPU */
+ for (int i = 0; i < basl_ncpu; ++i) {
+ /* Type */
+ BASL_EXEC(
+ basl_table_append_int(madt, ACPI_MADT_TYPE_LOCAL_APIC, 1));
+ /* Length */
+ BASL_EXEC(basl_table_append_int(madt, 8, 1));
+ /* ACPI Processor UID */
+ BASL_EXEC(basl_table_append_int(madt, i, 1));
+ /* APIC ID */
+ BASL_EXEC(basl_table_append_int(madt, i, 1));
+ /* Flags */
+ BASL_EXEC(basl_table_append_int(madt, ACPI_MADT_ENABLED, 4));
+ }
+
+ /* I/O APIC */
+ /* Type */
+ BASL_EXEC(basl_table_append_int(madt, ACPI_MADT_TYPE_IO_APIC, 1));
+ /* Length */
+ BASL_EXEC(basl_table_append_int(madt, 12, 1));
+ /* I/O APIC ID */
+ BASL_EXEC(basl_table_append_int(madt, 0, 1));
+ /* Reserved */
+ BASL_EXEC(basl_table_append_int(madt, 0, 1));
+ /* I/O APIC Address */
+ BASL_EXEC(basl_table_append_int(madt, BHYVE_ADDRESS_IOAPIC, 4));
+ /* Interrupt Base */
+ BASL_EXEC(basl_table_append_int(madt, 0, 4));
+
+ /* Legacy IRQ0 is connected to pin 2 of the I/O APIC */
+ /* Type */
+ BASL_EXEC(
+ basl_table_append_int(madt, ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, 1));
+ /* Length */
+ BASL_EXEC(basl_table_append_int(madt, 10, 1));
+ /* Bus */
+ BASL_EXEC(basl_table_append_int(madt, 0, 1));
+ /* Source */
+ BASL_EXEC(basl_table_append_int(madt, 0, 1));
+ /* Interrupt */
+ BASL_EXEC(basl_table_append_int(madt, 2, 4));
+ /* Flags */
+ BASL_EXEC(basl_table_append_int(madt,
+ ACPI_MADT_POLARITY_ACTIVE_LOW | ACPI_MADT_TRIGGER_LEVEL, 2));
+
+ /* Type */
+ BASL_EXEC(
+ basl_table_append_int(madt, ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, 1));
+ /* Length */
+ BASL_EXEC(basl_table_append_int(madt, 10, 1));
+ /* Bus */
+ BASL_EXEC(basl_table_append_int(madt, 0, 1));
+ /* Source */
+ BASL_EXEC(basl_table_append_int(madt, SCI_INT, 1));
+ /* Interrupt */
+ BASL_EXEC(basl_table_append_int(madt, SCI_INT, 4));
+ /* Flags */
+ BASL_EXEC(basl_table_append_int(madt,
+ ACPI_MADT_POLARITY_ACTIVE_LOW | ACPI_MADT_TRIGGER_LEVEL, 2));
+
+ /* Local APIC NMI is conntected to LINT 1 on all CPUs */
+ /* Type */
+ BASL_EXEC(
+ basl_table_append_int(madt, ACPI_MADT_TYPE_LOCAL_APIC_NMI, 1));
+ /* Length */
+ BASL_EXEC(basl_table_append_int(madt, 6, 1));
+ /* Processor UID */
+ BASL_EXEC(basl_table_append_int(madt, 0xFF, 1));
+ /* Flags */
+ BASL_EXEC(basl_table_append_int(madt,
+ ACPI_MADT_POLARITY_ACTIVE_HIGH | ACPI_MADT_TRIGGER_EDGE, 2));
+ /* Local APIC LINT */
+ BASL_EXEC(basl_table_append_int(madt, 1, 1));
+
+ BASL_EXEC(basl_table_append_pointer(rsdt, ACPI_SIG_MADT,
+ ACPI_RSDT_ENTRY_SIZE));
+ BASL_EXEC(basl_table_append_pointer(xsdt, ACPI_SIG_MADT,
+ ACPI_XSDT_ENTRY_SIZE));
+
+ return (0);
+}
+
+static int
+build_mcfg(struct vmctx *const ctx)
+{
+ struct basl_table *mcfg;
+
+ BASL_EXEC(
+ basl_table_create(&mcfg, ctx, ACPI_SIG_MCFG, BASL_TABLE_ALIGNMENT));
+
+ /* Header */
+ BASL_EXEC(
+ basl_table_append_header(mcfg, ACPI_SIG_MCFG, BASL_REVISION_MCFG,
+ BASL_OEM_ID, BASL_OEM_TABLE_ID_MCFG, BASL_OEM_REVISION_MCFG));
+ /* Reserved */
+ BASL_EXEC(basl_table_append_int(mcfg, 0, 8));
+ /* Base Address */
+ BASL_EXEC(basl_table_append_int(mcfg, pci_ecfg_base(), 8));
+ /* Segment Group Number */
+ BASL_EXEC(basl_table_append_int(mcfg, 0, 2));
+ /* Start Bus Number */
+ BASL_EXEC(basl_table_append_int(mcfg, 0, 1));
+ /* End Bus Number */
+ BASL_EXEC(basl_table_append_int(mcfg, 0xFF, 1));
+ /* Reserved */
+ BASL_EXEC(basl_table_append_int(mcfg, 0, 4));
+
+ BASL_EXEC(basl_table_append_pointer(rsdt, ACPI_SIG_MCFG,
+ ACPI_RSDT_ENTRY_SIZE));
+ BASL_EXEC(basl_table_append_pointer(xsdt, ACPI_SIG_MCFG,
+ ACPI_XSDT_ENTRY_SIZE));
+
+ return (0);
+}
+
+static int
+build_rsdp(struct vmctx *const ctx)
+{
+ struct basl_table *rsdp;
+
+ BASL_EXEC(basl_table_create(&rsdp, ctx, ACPI_RSDP_NAME,
+ BASL_TABLE_ALIGNMENT));
+
+ /* Signature */
+ BASL_EXEC(basl_table_append_bytes(rsdp, ACPI_SIG_RSDP,
+ sizeof(ACPI_SIG_RSDP) - 1));
+ /* Checksum (patched by guest) */
+ BASL_EXEC(basl_table_append_checksum(rsdp, 0, 20));
+ /* OEM Id */
+ BASL_EXEC(basl_table_append_bytes(rsdp, BASL_OEM_ID, ACPI_OEM_ID_SIZE));
+ /* Revision */
+ BASL_EXEC(basl_table_append_int(rsdp, BASL_REVISION_RSDP, 1));
+ /* RSDT Address (patched by guest) */
+ BASL_EXEC(basl_table_append_pointer(rsdp, ACPI_SIG_RSDT,
+ ACPI_RSDT_ENTRY_SIZE));
+ /* Length (patched by basl_finish) */
+ BASL_EXEC(basl_table_append_length(rsdp, sizeof(UINT32)));
+ /* XSDT Address (patched by guest) */
+ BASL_EXEC(basl_table_append_pointer(rsdp, ACPI_SIG_XSDT,
+ ACPI_XSDT_ENTRY_SIZE));
+ /* Extended Checksum (patched by guest) */
+ BASL_EXEC(basl_table_append_checksum(rsdp, 0,
+ BASL_TABLE_CHECKSUM_LEN_FULL_TABLE));
+ /* Reserved */
+ BASL_EXEC(basl_table_append_int(rsdp, 0, 3));
+
+ return (0);
+}
+
+static int
+build_rsdt(struct vmctx *const ctx)
+{
+ BASL_EXEC(
+ basl_table_create(&rsdt, ctx, ACPI_SIG_RSDT, BASL_TABLE_ALIGNMENT));
+
+ /* Header */
+ BASL_EXEC(
+ basl_table_append_header(rsdt, ACPI_SIG_RSDT, BASL_REVISION_RSDT,
+ BASL_OEM_ID, BASL_OEM_TABLE_ID_RSDT, BASL_OEM_REVISION_RSDT));
+ /* Pointers (added by other build_XXX funcs) */
+
+ return (0);
+}
+
+static int
+build_xsdt(struct vmctx *const ctx)
+{
+ BASL_EXEC(
+ basl_table_create(&xsdt, ctx, ACPI_SIG_XSDT, BASL_TABLE_ALIGNMENT));
+
+ /* Header */
+ BASL_EXEC(
+ basl_table_append_header(xsdt, ACPI_SIG_XSDT, BASL_REVISION_XSDT,
+ BASL_OEM_ID, BASL_OEM_TABLE_ID_XSDT, BASL_OEM_REVISION_XSDT));
+ /* Pointers (added by other build_XXX funcs) */
+
+ return (0);
+}
+
int
acpi_build(struct vmctx *ctx, int ncpu)
{
@@ -968,30 +859,29 @@
if (getenv("BHYVE_ACPI_KEEPTMPS"))
basl_keep_temps = 1;
- err = basl_make_templates();
+ BASL_EXEC(basl_init());
+
+ BASL_EXEC(basl_make_templates());
/*
* Run through all the ASL files, compiling them and
* copying them into guest memory
+ *
+ * According to UEFI Specification v6.3 chapter 5.1 the FADT should be
+ * the first table pointed to by XSDT. For that reason, build it as
+ * first table after XSDT.
*/
- if (err == 0)
- err = basl_compile(ctx, basl_fwrite_rsdp, 0);
- if (err == 0)
- err = basl_compile(ctx, basl_fwrite_rsdt, RSDT_OFFSET);
- if (err == 0)
- err = basl_compile(ctx, basl_fwrite_xsdt, XSDT_OFFSET);
- if (err == 0)
- err = basl_compile(ctx, basl_fwrite_madt, MADT_OFFSET);
- if (err == 0)
- err = basl_compile(ctx, basl_fwrite_fadt, FADT_OFFSET);
- if (err == 0)
- err = basl_compile(ctx, basl_fwrite_hpet, HPET_OFFSET);
- if (err == 0)
- err = basl_compile(ctx, basl_fwrite_mcfg, MCFG_OFFSET);
- if (err == 0)
- err = basl_compile(ctx, basl_fwrite_facs, FACS_OFFSET);
- if (err == 0)
- err = basl_compile(ctx, basl_fwrite_dsdt, DSDT_OFFSET);
+ BASL_EXEC(build_rsdp(ctx));
+ BASL_EXEC(build_rsdt(ctx));
+ BASL_EXEC(build_xsdt(ctx));
+ BASL_EXEC(build_fadt(ctx));
+ BASL_EXEC(build_madt(ctx));
+ BASL_EXEC(build_hpet(ctx));
+ BASL_EXEC(build_mcfg(ctx));
+ BASL_EXEC(build_facs(ctx));
+ BASL_EXEC(build_dsdt(ctx));
+
+ BASL_EXEC(basl_finish());
- return (err);
+ return (0);
}
diff --git a/usr.sbin/bhyve/basl.h b/usr.sbin/bhyve/basl.h
new file mode 100644
--- /dev/null
+++ b/usr.sbin/bhyve/basl.h
@@ -0,0 +1,90 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG
+ * Author: Corvin Köhne <c.koehne@beckhoff.com>
+ */
+
+#pragma once
+
+#include <contrib/dev/acpica/include/acpi.h>
+
+#define ACPI_GAS_ACCESS_WIDTH_LEGACY 0
+#define ACPI_GAS_ACCESS_WIDTH_UNDEFINED 0
+#define ACPI_GAS_ACCESS_WIDTH_BYTE 1
+#define ACPI_GAS_ACCESS_WIDTH_WORD 2
+#define ACPI_GAS_ACCESS_WIDTH_DWORD 3
+#define ACPI_GAS_ACCESS_WIDTH_QWORD 4
+
+#define BHYVE_ACPI_BASE 0xf2400
+
+#define BASL_REVISION_DSDT 2
+#define BASL_REVISION_FADT 5
+#define BASL_REVISION_HPET 1
+#define BASL_REVISION_MADT 1
+#define BASL_REVISION_MCFG 1
+#define BASL_REVISION_RSDP 2
+#define BASL_REVISION_RSDT 1
+#define BASL_REVISION_XSDT 1
+
+#define BASL_OEM_ID "BHYVE "
+
+#define BASL_OEM_TABLE_ID_DSDT "BVDSDT "
+#define BASL_OEM_TABLE_ID_FADT "BVFACP "
+#define BASL_OEM_TABLE_ID_HPET "BVHPET "
+#define BASL_OEM_TABLE_ID_MADT "BVMADT "
+#define BASL_OEM_TABLE_ID_MCFG "BVMCFG "
+#define BASL_OEM_TABLE_ID_RSDT "BVRSDT "
+#define BASL_OEM_TABLE_ID_XSDT "BVXSDT "
+
+#define BASL_OEM_REVISION_DSDT 1
+#define BASL_OEM_REVISION_FADT 1
+#define BASL_OEM_REVISION_HPET 1
+#define BASL_OEM_REVISION_MADT 1
+#define BASL_OEM_REVISION_MCFG 1
+#define BASL_OEM_REVISION_RSDT 1
+#define BASL_OEM_REVISION_XSDT 1
+
+#define BASL_COMPILER_ID "BASL"
+
+#define BASL_COMPILER_REVISION 20220504
+
+#define BASL_TABLE_ALIGNMENT 0x10
+#define BASL_TABLE_ALIGNMENT_FACS 0x40
+
+#define BASL_TABLE_CHECKSUM_LEN_FULL_TABLE (-1)
+
+#define BASL_EXEC(x) \
+ do { \
+ const int error = (x); \
+ if (error) { \
+ warnc(error, \
+ "BASL failed @ %s:%d\n Failed to execute %s", \
+ __func__, __LINE__, #x); \
+ return (error); \
+ } \
+ } while (0)
+
+#define QEMU_FWCFG_MAX_NAME 56
+
+struct basl_table;
+
+int basl_finish();
+int basl_init();
+int basl_table_append_bytes(struct basl_table *table, const void *bytes,
+ uint32_t len);
+int basl_table_append_checksum(struct basl_table *table, uint32_t start,
+ uint32_t len);
+int basl_table_append_gas(struct basl_table *table, uint8_t space_id,
+ uint8_t bit_width, uint8_t bit_offset, uint8_t access_width,
+ uint64_t address);
+int basl_table_append_header(struct basl_table *table,
+ const uint8_t sign[ACPI_NAMESEG_SIZE], uint8_t rev,
+ const uint8_t oem_id[ACPI_OEM_ID_SIZE],
+ const uint8_t oem_table_id[ACPI_OEM_TABLE_ID_SIZE], uint32_t oem_revision);
+int basl_table_append_int(struct basl_table *table, uint64_t val, uint8_t size);
+int basl_table_append_length(struct basl_table *table, uint8_t size);
+int basl_table_append_pointer(struct basl_table *table,
+ const uint8_t src_sign[ACPI_NAMESEG_SIZE], uint8_t size);
+int basl_table_create(struct basl_table **table, struct vmctx *ctx,
+ const uint8_t name[QEMU_FWCFG_MAX_NAME], uint32_t alignment);
diff --git a/usr.sbin/bhyve/basl.c b/usr.sbin/bhyve/basl.c
new file mode 100644
--- /dev/null
+++ b/usr.sbin/bhyve/basl.c
@@ -0,0 +1,544 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG
+ * Author: Corvin Köhne <c.koehne@beckhoff.com>
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/endian.h>
+#include <sys/errno.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <machine/vmm.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <vmmapi.h>
+
+#include "basl.h"
+
+struct basl_table {
+ STAILQ_ENTRY(basl_table) chain;
+ struct vmctx *ctx;
+ uint8_t fwcfg_name[QEMU_FWCFG_MAX_NAME];
+ void *data;
+ uint32_t len;
+ uint32_t off;
+ uint32_t alignment;
+};
+STAILQ_HEAD(basl_table_list, basl_table) basl_tables = STAILQ_HEAD_INITIALIZER(
+ basl_tables);
+
+struct basl_table_checksum {
+ STAILQ_ENTRY(basl_table_checksum) chain;
+ struct basl_table *table;
+ uint32_t off;
+ uint32_t start;
+ uint32_t len;
+};
+STAILQ_HEAD(basl_table_checksum_list, basl_table_checksum) basl_checksums =
+ STAILQ_HEAD_INITIALIZER(basl_checksums);
+
+struct basl_table_length {
+ STAILQ_ENTRY(basl_table_length) chain;
+ struct basl_table *table;
+ uint32_t off;
+ uint8_t size;
+};
+STAILQ_HEAD(basl_table_length_list,
+ basl_table_length) basl_lengths = STAILQ_HEAD_INITIALIZER(basl_lengths);
+
+struct basl_table_pointer {
+ STAILQ_ENTRY(basl_table_pointer) chain;
+ struct basl_table *table;
+ uint8_t src_sign[ACPI_NAMESEG_SIZE];
+ uint32_t off;
+ uint8_t size;
+};
+STAILQ_HEAD(basl_table_pointer_list,
+ basl_table_pointer) basl_pointers = STAILQ_HEAD_INITIALIZER(basl_pointers);
+
+struct qemu_loader *basl_loader;
+
+static int
+basl_dump_table(const struct basl_table *const table, const int mem)
+{
+ const ACPI_TABLE_HEADER *const header = table->data;
+ const uint8_t *data;
+
+ if (!mem) {
+ data = table->data;
+ } else {
+ data = (uint8_t *)vm_map_gpa(table->ctx,
+ BHYVE_ACPI_BASE + table->off, table->len);
+ if (data == NULL) {
+ return (ENOMEM);
+ }
+ }
+
+ printf("%c%c%c%c @ %8x (%s)\n\r", header->Signature[0],
+ header->Signature[1], header->Signature[2], header->Signature[3],
+ BHYVE_ACPI_BASE + table->off, mem ? "Memory" : "FwCfg");
+ for (uint32_t i = 0; i < table->len; i += 0x10) {
+ printf("%08x: ", i);
+ for (uint32_t n = 0; n < 0x10; ++n) {
+ if (table->len <= i + n) {
+ printf(" ");
+ continue;
+ }
+ printf("%02x ", data[i + n]);
+ }
+ printf("| ");
+ for (uint32_t n = 0; n < 0x10; ++n) {
+ if (table->len <= i + n) {
+ printf(" ");
+ continue;
+ }
+ const uint8_t c = data[i + n];
+ if (c < 0x20 || c >= 0x7F) {
+ printf(".");
+ } else {
+ printf("%c", c);
+ }
+ }
+ printf("\n\r");
+ }
+
+ return (0);
+}
+
+static int
+basl_dump(const int mem)
+{
+ struct basl_table *table;
+ STAILQ_FOREACH (table, &basl_tables, chain) {
+ BASL_EXEC(basl_dump_table(table, mem));
+ }
+
+ return (0);
+}
+
+static int
+basl_finish_alloc()
+{
+ struct basl_table *table;
+ uint32_t off = 0;
+ STAILQ_FOREACH (table, &basl_tables, chain) {
+ table->off = roundup2(off, table->alignment);
+ off = table->off + table->len;
+ if (off <= table->off) {
+ warnx("%s: invalid table length 0x%8x @ offset 0x%8x",
+ __func__, table->len, table->off);
+ return (EFAULT);
+ }
+
+ /*
+ * Guest bios versions without qemu fwcfg support search for
+ * ACPI tables in the guest memory and install them as is.
+ * Therefore, copy the tables into the guest memory.
+ */
+ void *gva = vm_map_gpa(table->ctx, BHYVE_ACPI_BASE + table->off,
+ table->len);
+ if (gva == NULL) {
+ warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]",
+ __func__, (uint64_t)BHYVE_ACPI_BASE + table->off,
+ (uint64_t)BHYVE_ACPI_BASE + table->off +
+ table->len);
+ return (ENOMEM);
+ }
+ memcpy(gva, table->data, table->len);
+ }
+
+ return (0);
+}
+
+static int
+basl_finish_patch_checksums()
+{
+ struct basl_table_checksum *checksum;
+ STAILQ_FOREACH (checksum, &basl_checksums, chain) {
+ const struct basl_table *const table = checksum->table;
+
+ uint32_t len = checksum->len;
+ if (len == BASL_TABLE_CHECKSUM_LEN_FULL_TABLE) {
+ len = table->len;
+ }
+
+ /*
+ * Guest bios versions without qemu fwcfg support search for
+ * ACPI tables in the guest memory and install them as is.
+ * Therefore, patch the checksum in the guest memory copies to a
+ * correct value.
+ */
+ const uint64_t gpa = BHYVE_ACPI_BASE + table->off +
+ checksum->start;
+ if ((gpa < BHYVE_ACPI_BASE) ||
+ (gpa < BHYVE_ACPI_BASE + table->off)) {
+ warnx("%s: invalid gpa (off 0x%8x start 0x%8x)",
+ __func__, table->off, checksum->start);
+ return (EFAULT);
+ }
+
+ uint8_t *const gva = (uint8_t *)vm_map_gpa(table->ctx, gpa,
+ len);
+ if (gva == NULL) {
+ warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]",
+ __func__, gpa, gpa + len);
+ return (ENOMEM);
+ }
+ uint8_t *const checksum_gva = gva + checksum->off;
+ if (checksum_gva < gva) {
+ warnx("%s: invalid checksum offset 0x%8x", __func__,
+ checksum->off);
+ return (EFAULT);
+ }
+
+ uint8_t sum = 0;
+ for (uint32_t i = 0; i < len; ++i) {
+ sum += *(gva + i);
+ }
+ *checksum_gva = -sum;
+ }
+
+ return (0);
+}
+
+static struct basl_table *
+basl_get_table_by_sign(const uint8_t sign[ACPI_NAMESEG_SIZE])
+{
+ struct basl_table *table;
+ STAILQ_FOREACH (table, &basl_tables, chain) {
+ const ACPI_TABLE_HEADER *const header =
+ (const ACPI_TABLE_HEADER *)table->data;
+ if (strncmp(header->Signature, sign,
+ sizeof(header->Signature)) == 0) {
+ return (table);
+ }
+ }
+
+ warnx("%s: %c%c%c%c not found", __func__, sign[0], sign[1], sign[2],
+ sign[3]);
+ return (NULL);
+}
+
+static int
+basl_finish_patch_pointers()
+{
+ struct basl_table_pointer *pointer;
+ STAILQ_FOREACH (pointer, &basl_pointers, chain) {
+ const struct basl_table *const table = pointer->table;
+ const struct basl_table *const src_table =
+ basl_get_table_by_sign(pointer->src_sign);
+ if (src_table == NULL) {
+ warnx("%s: could not find ACPI table %c%c%c%c",
+ __func__, pointer->src_sign[0],
+ pointer->src_sign[1], pointer->src_sign[2],
+ pointer->src_sign[3]);
+ return (EFAULT);
+ }
+
+ /*
+ * Guest bios versions without qemu fwcfg support search for
+ * ACPI tables in the guest memory and install them as is.
+ * Therefore, patch the pointers in the guest memory copies
+ * manually.
+ */
+ const uint64_t gpa = BHYVE_ACPI_BASE + table->off;
+ if (gpa < BHYVE_ACPI_BASE) {
+ warnx("%s: table offset of 0x%8x is too large",
+ __func__, table->off);
+ return (EFAULT);
+ }
+
+ uint8_t *const gva = (uint8_t *)vm_map_gpa(table->ctx, gpa,
+ table->len);
+ if (gva == NULL) {
+ warnx("%s: could not map gpa [ 0x%16lx, 0x%16lx ]",
+ __func__, gpa, gpa + table->len);
+ return (ENOMEM);
+ }
+
+ uint64_t val_le = 0;
+ memcpy(&val_le, gva + pointer->off, pointer->size);
+ uint64_t val = le64toh(val_le);
+
+ val += BHYVE_ACPI_BASE + src_table->off;
+
+ val_le = htole64(val);
+ memcpy(gva + pointer->off, &val_le, pointer->size);
+ }
+
+ return (0);
+}
+
+static int
+basl_finish_set_length()
+{
+ struct basl_table_length *length;
+ STAILQ_FOREACH (length, &basl_lengths, chain) {
+ const struct basl_table *const table = length->table;
+
+ uint32_t len_le = htole32(table->len);
+
+ memcpy(table->data + length->off, &len_le, length->size);
+ }
+
+ return (0);
+}
+
+int
+basl_finish()
+{
+ if (STAILQ_EMPTY(&basl_tables)) {
+ warnx("%s: no ACPI tables found", __func__);
+ return (EINVAL);
+ }
+
+ BASL_EXEC(basl_finish_set_length());
+ BASL_EXEC(basl_finish_alloc());
+ BASL_EXEC(basl_finish_patch_pointers());
+ BASL_EXEC(basl_finish_patch_checksums());
+
+ return (0);
+}
+
+int
+basl_init()
+{
+ return (0);
+}
+
+static int
+basl_table_add_checksum(struct basl_table *const table, const uint32_t off,
+ const uint32_t start, const uint32_t len)
+{
+ struct basl_table_checksum *const checksum = calloc(1,
+ sizeof(struct basl_table_checksum));
+ if (checksum == NULL) {
+ warnx("%s: failed to allocate checksum", __func__);
+ return (ENOMEM);
+ }
+
+ checksum->table = table;
+ checksum->off = off;
+ checksum->start = start;
+ checksum->len = len;
+
+ STAILQ_INSERT_TAIL(&basl_checksums, checksum, chain);
+
+ return (0);
+}
+
+static int
+basl_table_add_length(struct basl_table *const table, const uint32_t off,
+ const uint8_t size)
+{
+ struct basl_table_length *const length = calloc(1,
+ sizeof(struct basl_table_length));
+ if (length == NULL) {
+ warnx("%s: failed to allocate length", __func__);
+ return (ENOMEM);
+ }
+
+ length->table = table;
+ length->off = off;
+ length->size = size;
+
+ STAILQ_INSERT_TAIL(&basl_lengths, length, chain);
+
+ return (0);
+}
+
+static int
+basl_table_add_pointer(struct basl_table *const table,
+ const uint8_t src_sign[ACPI_NAMESEG_SIZE], const uint32_t off,
+ const uint8_t size)
+{
+ struct basl_table_pointer *const pointer = calloc(1,
+ sizeof(struct basl_table_pointer));
+ if (pointer == NULL) {
+ warnx("%s: failed to allocate pointer", __func__);
+ return (ENOMEM);
+ }
+
+ pointer->table = table;
+ memcpy(pointer->src_sign, src_sign, sizeof(pointer->src_sign));
+ pointer->off = off;
+ pointer->size = size;
+
+ STAILQ_INSERT_TAIL(&basl_pointers, pointer, chain);
+
+ return (0);
+}
+
+int
+basl_table_append_bytes(struct basl_table *const table, const void *const bytes,
+ const uint32_t len)
+{
+ if (table == NULL || bytes == NULL) {
+ return (EINVAL);
+ }
+ if (table->len + len <= table->len) {
+ warnx("%s: table too large (table->len 0x%8x len 0x%8x)",
+ __func__, table->len, len);
+ return (EFAULT);
+ }
+
+ table->data = reallocf(table->data, table->len + len);
+ if (table->data == NULL) {
+ warnx("%s: failed to realloc table to length 0x%8x", __func__,
+ table->len + len);
+ table->len = 0;
+ return (ENOMEM);
+ }
+ void *const end = (uint8_t *)table->data + table->len;
+ table->len += len;
+
+ memcpy(end, bytes, len);
+
+ return (0);
+}
+
+int
+basl_table_append_checksum(struct basl_table *const table, const uint32_t start,
+ const uint32_t len)
+{
+ if (table == NULL) {
+ return (EINVAL);
+ }
+
+ BASL_EXEC(basl_table_add_checksum(table, table->len, start, len));
+ BASL_EXEC(basl_table_append_int(table, 0, 1));
+
+ return (0);
+}
+
+int
+basl_table_append_gas(struct basl_table *const table, const uint8_t space_id,
+ const uint8_t bit_width, const uint8_t bit_offset,
+ const uint8_t access_width, const uint64_t address)
+{
+ ACPI_GENERIC_ADDRESS gas_le = {
+ .SpaceId = space_id,
+ .BitWidth = bit_width,
+ .BitOffset = bit_offset,
+ .AccessWidth = access_width,
+ .Address = htole64(address),
+ };
+
+ return (basl_table_append_bytes(table, &gas_le, sizeof(gas_le)));
+}
+
+int
+basl_table_append_header(struct basl_table *const table,
+ const uint8_t sign[ACPI_NAMESEG_SIZE], const uint8_t rev,
+ const uint8_t oem_id[ACPI_OEM_ID_SIZE],
+ const uint8_t oem_table_id[ACPI_OEM_TABLE_ID_SIZE],
+ const uint32_t oem_revision)
+{
+ if (table == NULL || table->len != 0) {
+ return (EINVAL);
+ }
+
+ ACPI_TABLE_HEADER header_le;
+
+ memcpy(header_le.Signature, sign, sizeof(header_le.Signature));
+ header_le.Length = 0; /* patched by basl_finish */
+ header_le.Revision = rev;
+ header_le.Checksum = 0; /* patched by basl_finish */
+ memcpy(header_le.OemId, oem_id, sizeof(header_le.OemId));
+ memcpy(header_le.OemTableId, oem_table_id, sizeof(header_le.OemTableId));
+ header_le.OemRevision = htole32(oem_revision);
+ static_assert(sizeof(header_le.AslCompilerId) ==
+ sizeof(BASL_COMPILER_ID) - 1 /* Without '\0' */,
+ "Mismatching ASL compiler id size");
+ memcpy(header_le.AslCompilerId, BASL_COMPILER_ID,
+ sizeof(header_le.AslCompilerId));
+ header_le.AslCompilerRevision = htole32(BASL_COMPILER_REVISION);
+
+ BASL_EXEC(
+ basl_table_append_bytes(table, &header_le, sizeof(header_le)));
+
+ BASL_EXEC(basl_table_add_length(table,
+ offsetof(ACPI_TABLE_HEADER, Length), sizeof(header_le.Length)));
+ BASL_EXEC(basl_table_add_checksum(table,
+ offsetof(ACPI_TABLE_HEADER, Checksum), 0,
+ BASL_TABLE_CHECKSUM_LEN_FULL_TABLE));
+
+ return (0);
+}
+
+int
+basl_table_append_int(struct basl_table *const table, const uint64_t val,
+ const uint8_t size)
+{
+ if (size > sizeof(val)) {
+ return (EINVAL);
+ }
+
+ const uint64_t val_le = htole64(val);
+ return (basl_table_append_bytes(table, &val_le, size));
+}
+
+int
+basl_table_append_length(struct basl_table *const table, const uint8_t size)
+{
+ if (table == NULL || size > sizeof(table->len)) {
+ return (EINVAL);
+ }
+
+ BASL_EXEC(basl_table_add_length(table, table->len, size));
+ BASL_EXEC(basl_table_append_int(table, 0, size));
+
+ return (0);
+}
+
+int
+basl_table_append_pointer(struct basl_table *const table,
+ const uint8_t src_sign[ACPI_NAMESEG_SIZE], const uint8_t size)
+{
+ if (table == NULL || size > sizeof(UINT64)) {
+ return (EINVAL);
+ }
+
+ BASL_EXEC(basl_table_add_pointer(table, src_sign, table->len, size));
+ BASL_EXEC(basl_table_append_int(table, 0, size));
+
+ return (0);
+}
+
+int
+basl_table_create(struct basl_table **const table, struct vmctx *ctx,
+ const uint8_t name[QEMU_FWCFG_MAX_NAME], const uint32_t alignment)
+{
+ if (table == NULL) {
+ return (EINVAL);
+ }
+
+ struct basl_table *const new_table = (struct basl_table *)calloc(1,
+ sizeof(struct basl_table));
+ if (new_table == NULL) {
+ warnx("%s: failed to allocate table", __func__);
+ return (ENOMEM);
+ }
+
+ new_table->ctx = ctx;
+
+ snprintf(new_table->fwcfg_name, sizeof(new_table->fwcfg_name),
+ "etc/acpi/%s", name);
+
+ new_table->alignment = alignment;
+
+ STAILQ_INSERT_TAIL(&basl_tables, new_table, chain);
+
+ *table = new_table;
+
+ return (0);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 16, 12:52 AM (8 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14650178
Default Alt Text
D36983.id111782.diff (56 KB)
Attached To
Mode
D36983: bhyve: improve acpi table generation
Attached
Detach File
Event Timeline
Log In to Comment