Page MenuHomeFreeBSD

D36983.id111782.diff
No OneTemporary

D36983.id111782.diff

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

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)

Event Timeline