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 @@ -36,20 +36,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 @@ -78,32 +64,6 @@ #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 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" @@ -334,7 +294,7 @@ } static int -basl_load(struct vmctx *ctx, int fd, uint64_t off) +basl_load(struct vmctx *ctx, int fd) { struct stat sb; void *addr; @@ -353,15 +313,14 @@ 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, off)); + 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]; @@ -395,7 +354,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]); @@ -453,7 +412,7 @@ static int build_dsdt(struct vmctx *const ctx) { - BASL_EXEC(basl_compile(ctx, basl_fwrite_dsdt, DSDT_OFFSET)); + BASL_EXEC(basl_compile(ctx, basl_fwrite_dsdt)); return (0); } @@ -465,7 +424,7 @@ struct basl_table *table; BASL_EXEC(basl_table_create(&table, ctx, ACPI_SIG_FACS, - BASL_TABLE_ALIGNMENT_FACS, FACS_OFFSET)); + BASL_TABLE_ALIGNMENT_FACS)); memset(&facs, 0, sizeof(facs)); memcpy(facs.Signature, ACPI_SIG_FACS, ACPI_NAMESEG_SIZE); @@ -483,7 +442,7 @@ struct basl_table *table; BASL_EXEC(basl_table_create(&table, ctx, ACPI_SIG_FADT, - BASL_TABLE_ALIGNMENT, FADT_OFFSET)); + BASL_TABLE_ALIGNMENT)); memset(&fadt, 0, sizeof(fadt)); BASL_EXEC(basl_table_append_header(table, ACPI_SIG_FADT, 5, 1)); @@ -559,7 +518,7 @@ struct basl_table *table; BASL_EXEC(basl_table_create(&table, ctx, ACPI_SIG_HPET, - BASL_TABLE_ALIGNMENT, HPET_OFFSET)); + BASL_TABLE_ALIGNMENT)); memset(&hpet, 0, sizeof(hpet)); BASL_EXEC(basl_table_append_header(table, ACPI_SIG_HPET, 1, 1)); @@ -588,7 +547,7 @@ struct basl_table *table; BASL_EXEC(basl_table_create(&table, ctx, ACPI_SIG_MADT, - BASL_TABLE_ALIGNMENT, MADT_OFFSET)); + BASL_TABLE_ALIGNMENT)); memset(&madt, 0, sizeof(madt)); BASL_EXEC(basl_table_append_header(table, ACPI_SIG_MADT, 1, 1)); @@ -663,7 +622,7 @@ struct basl_table *table; BASL_EXEC(basl_table_create(&table, ctx, ACPI_SIG_MCFG, - BASL_TABLE_ALIGNMENT, MCFG_OFFSET)); + BASL_TABLE_ALIGNMENT)); memset(&mcfg, 0, sizeof(mcfg)); BASL_EXEC(basl_table_append_header(table, ACPI_SIG_MCFG, 1, 1)); @@ -690,7 +649,7 @@ struct basl_table *table; BASL_EXEC(basl_table_create(&table, ctx, ACPI_RSDP_NAME, - BASL_TABLE_ALIGNMENT, 0)); + BASL_TABLE_ALIGNMENT)); memset(&rsdp, 0, sizeof(rsdp)); memcpy(rsdp.Signature, ACPI_SIG_RSDP, 8); @@ -723,8 +682,8 @@ static int build_rsdt(struct vmctx *const ctx) { - BASL_EXEC(basl_table_create(&rsdt, ctx, ACPI_SIG_RSDT, - BASL_TABLE_ALIGNMENT, RSDT_OFFSET)); + BASL_EXEC( + basl_table_create(&rsdt, ctx, ACPI_SIG_RSDT, BASL_TABLE_ALIGNMENT)); /* Header */ BASL_EXEC(basl_table_append_header(rsdt, ACPI_SIG_RSDT, 1, 1)); @@ -736,8 +695,8 @@ static int build_xsdt(struct vmctx *const ctx) { - BASL_EXEC(basl_table_create(&xsdt, ctx, ACPI_SIG_XSDT, - BASL_TABLE_ALIGNMENT, XSDT_OFFSET)); + BASL_EXEC( + basl_table_create(&xsdt, ctx, ACPI_SIG_XSDT, BASL_TABLE_ALIGNMENT)); /* Header */ BASL_EXEC(basl_table_append_header(xsdt, ACPI_SIG_XSDT, 1, 1)); diff --git a/usr.sbin/bhyve/basl.h b/usr.sbin/bhyve/basl.h --- a/usr.sbin/bhyve/basl.h +++ b/usr.sbin/bhyve/basl.h @@ -70,4 +70,4 @@ int basl_table_append_pointer(struct basl_table *table, const uint8_t src_signature[ACPI_NAMESEG_SIZE], uint8_t size); int basl_table_create(struct basl_table **table, struct vmctx *ctx, - const uint8_t *name, uint32_t alignment, uint32_t off); + const uint8_t *name, uint32_t alignment); diff --git a/usr.sbin/bhyve/basl.c b/usr.sbin/bhyve/basl.c --- a/usr.sbin/bhyve/basl.c +++ b/usr.sbin/bhyve/basl.c @@ -136,10 +136,18 @@ } static int -basl_finish_install_guest_tables(struct basl_table *const table) +basl_finish_install_guest_tables(struct basl_table *const table, uint32_t *const off) { void *gva; + 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); + } + /* * Install ACPI tables directly in guest memory for use by guests which * do not boot via EFI. EFI ROMs provide a pointer to the firmware @@ -303,6 +311,7 @@ basl_finish(void) { struct basl_table *table; + uint32_t off = 0; if (STAILQ_EMPTY(&basl_tables)) { warnx("%s: no ACPI tables found", __func__); @@ -316,7 +325,7 @@ */ STAILQ_FOREACH(table, &basl_tables, chain) { BASL_EXEC(basl_finish_set_length(table)); - BASL_EXEC(basl_finish_install_guest_tables(table)); + BASL_EXEC(basl_finish_install_guest_tables(table, &off)); } STAILQ_FOREACH(table, &basl_tables, chain) { BASL_EXEC(basl_finish_patch_pointers(table)); @@ -553,8 +562,7 @@ int basl_table_create(struct basl_table **const table, struct vmctx *ctx, - const uint8_t *const name, const uint32_t alignment, - const uint32_t off) + const uint8_t *const name, const uint32_t alignment) { struct basl_table *new_table; @@ -572,7 +580,6 @@ "etc/acpi/%s", name); new_table->alignment = alignment; - new_table->off = off; STAILQ_INIT(&new_table->checksums); STAILQ_INIT(&new_table->lengths);