Message ID | a0a25b78b9a593b7cf3c73b54342ee9b331688da.1470643610.git.lv.zheng@intel.com |
---|---|
State | New |
Headers | show |
On 08/08/2016 10:16, Lv Zheng wrote: > This patch allows FADT to be built with different revisions. When the revision > is greater than 1.0, 64-bit address fields may also be filled. > > Note that FADT revision 2 has never been defined by the ACPI specification. So > this patch only adds an option -acpifadt to allow revision 1,3,5 to be > configured by the users. > > 1. Tested by booting a linux image, the 64-bit addresses are correctly filled > in the dumped FADT. > 2. Tested by booting a Windows image, no boot failure can be seen. > > Signed-off-by: Lv Zheng <lv.zheng@intel.com> Hi, please make this a suboption of -acpitable instead. We try not to add new command-line options without supporting them in QemuOpts too. Paolo > --- > History: > > v2: Fix coding style issues. > --- > hw/i386/acpi-build.c | 62 ++++++++++++++++++++++++++++++++++++++++++------ > include/hw/acpi/acpi.h | 1 + > qemu-options.hx | 9 +++++++ > vl.c | 23 ++++++++++++++++++ > 4 files changed, 88 insertions(+), 7 deletions(-) > > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c > index ce7cbc5..4479695 100644 > --- a/hw/i386/acpi-build.c > +++ b/hw/i386/acpi-build.c > @@ -276,8 +276,22 @@ build_facs(GArray *table_data, BIOSLinker *linker) > facs->length = cpu_to_le32(sizeof(*facs)); > } > > +/* GAS */ > +static void > +build_gas(struct AcpiGenericAddress *gas, uint8_t space_id, > + uint8_t bit_width, uint8_t bit_offset, > + uint8_t access_width, uint64_t address) > +{ > + gas->space_id = space_id; > + gas->bit_width = bit_width; > + gas->bit_offset = bit_offset; > + gas->access_width = access_width; > + gas->address = address; > +} > + > /* Load chipset information in FADT */ > -static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm) > +static void fadt_setup(AcpiFadtDescriptorRev5_1 *fadt, AcpiPmInfo *pm, > + uint8_t revision) > { > fadt->model = 1; > fadt->reserved1 = 0; > @@ -309,6 +323,25 @@ static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm) > fadt->flags |= cpu_to_le32(1 << ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL); > } > fadt->century = RTC_CENTURY; > + > + /* Build ACPI 2.0 (FADT version 3+) GAS fields */ > + if (revision >= 3) { > + /* EVT, CNT, TMR register matches hw/acpi/core.c */ > + build_gas(&fadt->xpm1a_event_block, AML_SYSTEM_IO, > + 32, 0, 0, cpu_to_le64(pm->io_base)); > + build_gas(&fadt->xpm1a_control_block, AML_SYSTEM_IO, > + 16, 0, 0, cpu_to_le64(pm->io_base + 0x04)); > + build_gas(&fadt->xpm_timer_block, AML_SYSTEM_IO, > + 32, 0, 0, cpu_to_le64(pm->io_base + 0x08)); > + build_gas(&fadt->xgpe0_block, AML_SYSTEM_IO, > + pm->gpe0_blk_len << 3, 0, 0, cpu_to_le64(pm->gpe0_blk)); > + } > + > + /* Build dummy ACPI 5.0 fields */ > + if (revision >= 5) { > + build_gas(&fadt->sleep_control, AML_SYSTEM_MEMORY, 0, 0, 0, 0); > + build_gas(&fadt->sleep_status, AML_SYSTEM_MEMORY, 0, 0, 0, 0); > + } > } > > > @@ -316,9 +349,9 @@ static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm) > static void > build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm, > unsigned facs_tbl_offset, unsigned dsdt_tbl_offset, > - const char *oem_id, const char *oem_table_id) > + const char *oem_id, const char *oem_table_id, uint8_t revision) > { > - AcpiFadtDescriptorRev1 *fadt = acpi_data_push(table_data, sizeof(*fadt)); > + AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt)); > unsigned fw_ctrl_offset = (char *)&fadt->firmware_ctrl - table_data->data; > unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data; > > @@ -328,13 +361,28 @@ build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm, > ACPI_BUILD_TABLE_FILE, facs_tbl_offset); > > /* DSDT address to be filled by Guest linker */ > - fadt_setup(fadt, pm); > bios_linker_loader_add_pointer(linker, > ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->dsdt), > ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset); > > - build_header(linker, table_data, > - (void *)fadt, "FACP", sizeof(*fadt), 1, oem_id, oem_table_id); > + if (revision > 2) { > + fw_ctrl_offset = (char *)&fadt->Xfacs - table_data->data; > + dsdt_entry_offset = (char *)&fadt->Xdsdt - table_data->data; > + > + /* FACS address to be filled by Guest linker */ > + bios_linker_loader_add_pointer(linker, > + ACPI_BUILD_TABLE_FILE, fw_ctrl_offset, sizeof(fadt->Xfacs), > + ACPI_BUILD_TABLE_FILE, facs_tbl_offset); > + > + /* DSDT address to be filled by Guest linker */ > + bios_linker_loader_add_pointer(linker, > + ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->Xdsdt), > + ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset); > + } > + > + fadt_setup(fadt, pm, revision); > + build_header(linker, table_data, (void *)fadt, "FACP", sizeof(*fadt), > + revision, oem_id, oem_table_id); > } > > void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, > @@ -2681,7 +2729,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) > fadt = tables_blob->len; > acpi_add_table(table_offsets, tables_blob); > build_fadt(tables_blob, tables->linker, &pm, facs, dsdt, > - slic_oem.id, slic_oem.table_id); > + slic_oem.id, slic_oem.table_id, acpi_fadt_rev); > aml_len += tables_blob->len - fadt; > > acpi_add_table(table_offsets, tables_blob); > diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h > index 7b3d93c..63df38d 100644 > --- a/include/hw/acpi/acpi.h > +++ b/include/hw/acpi/acpi.h > @@ -173,6 +173,7 @@ void acpi_update_sci(ACPIREGS *acpi_regs, qemu_irq irq); > > /* acpi.c */ > extern int acpi_enabled; > +extern uint8_t acpi_fadt_rev; > extern char unsigned *acpi_tables; > extern size_t acpi_tables_len; > > diff --git a/qemu-options.hx b/qemu-options.hx > index a71aaf8..cff34f6 100644 > --- a/qemu-options.hx > +++ b/qemu-options.hx > @@ -1492,6 +1492,15 @@ STEXI > Disable HPET support. > ETEXI > > +DEF("acpifadt", HAS_ARG, QEMU_OPTION_acpifadt, \ > + "-acpifadt n configure FADT revision number (1, 3, 5)\n", > + QEMU_ARCH_ALL) > +STEXI > +@item -acpifadt @var{n} > +@findex -acpifadt > +Configure FADT revision number, default is 1. > +ETEXI > + > DEF("acpitable", HAS_ARG, QEMU_OPTION_acpitable, > "-acpitable [sig=str][,rev=n][,oem_id=str][,oem_table_id=str][,oem_rev=n][,asl_compiler_id=str][,asl_compiler_rev=n][,{data|file}=file1[:file2]...]\n" > " ACPI table description\n", QEMU_ARCH_I386) > diff --git a/vl.c b/vl.c > index e7c2c62..220e36d 100644 > --- a/vl.c > +++ b/vl.c > @@ -64,6 +64,7 @@ int main(int argc, char **argv) > #include "hw/bt.h" > #include "sysemu/watchdog.h" > #include "hw/smbios/smbios.h" > +#include "hw/acpi/acpi.h" > #include "hw/xen/xen.h" > #include "hw/qdev.h" > #include "hw/loader.h" > @@ -158,6 +159,7 @@ int max_cpus = 1; > int smp_cores = 1; > int smp_threads = 1; > int acpi_enabled = 1; > +uint8_t acpi_fadt_rev = 1; > int no_hpet = 0; > int fd_bootchk = 1; > static int no_reboot; > @@ -2301,6 +2303,24 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp) > return 0; > } > > +static void fadt_parse(const char *arg) > +{ > + unsigned long rev; > + int err; > + > + err = qemu_strtoul(arg, NULL, 10, &rev); > + if (err) { > + error_printf("Invalid FADT revision.\n"); > + exit(1); > + } > + if (rev != 1 && rev != 3 && rev != 5) { > + error_printf("Unsupported FADT revision %lu, " > + "please specify 1,3,5.\n", rev); > + exit(1); > + } > + acpi_fadt_rev = rev; > +} > + > static int device_help_func(void *opaque, QemuOpts *opts, Error **errp) > { > return qdev_device_help(opts); > @@ -3622,6 +3642,9 @@ int main(int argc, char **argv, char **envp) > qdev_prop_register_global(&slew_lost_ticks); > break; > } > + case QEMU_OPTION_acpifadt: > + fadt_parse(optarg); > + break; > case QEMU_OPTION_acpitable: > opts = qemu_opts_parse_noisily(qemu_find_opts("acpi"), > optarg, true); >
Hi, > From: Paolo Bonzini [mailto:paolo.bonzini@gmail.com] On Behalf Of Paolo > Bonzini > Subject: Re: [PATCH v2] ACPI: Add -acpifadt to allow FADT revision changes > > > > On 08/08/2016 10:16, Lv Zheng wrote: > > This patch allows FADT to be built with different revisions. When the > revision > > is greater than 1.0, 64-bit address fields may also be filled. > > > > Note that FADT revision 2 has never been defined by the ACPI > specification. So > > this patch only adds an option -acpifadt to allow revision 1,3,5 to be > > configured by the users. > > > > 1. Tested by booting a linux image, the 64-bit addresses are correctly > filled > > in the dumped FADT. > > 2. Tested by booting a Windows image, no boot failure can be seen. > > > > Signed-off-by: Lv Zheng <lv.zheng@intel.com> > > Hi, please make this a suboption of -acpitable instead. We try not to > add new command-line options without supporting them in QemuOpts > too. [Lv Zheng] OK. I'll prepare a v3 patch to address this. Thanks for the review. Cheers -Lv > > Paolo > > > --- > > History: > > > > v2: Fix coding style issues. > > --- > > hw/i386/acpi-build.c | 62 > ++++++++++++++++++++++++++++++++++++++++++------ > > include/hw/acpi/acpi.h | 1 + > > qemu-options.hx | 9 +++++++ > > vl.c | 23 ++++++++++++++++++ > > 4 files changed, 88 insertions(+), 7 deletions(-) > > > > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c > > index ce7cbc5..4479695 100644 > > --- a/hw/i386/acpi-build.c > > +++ b/hw/i386/acpi-build.c > > @@ -276,8 +276,22 @@ build_facs(GArray *table_data, BIOSLinker > *linker) > > facs->length = cpu_to_le32(sizeof(*facs)); > > } > > > > +/* GAS */ > > +static void > > +build_gas(struct AcpiGenericAddress *gas, uint8_t space_id, > > + uint8_t bit_width, uint8_t bit_offset, > > + uint8_t access_width, uint64_t address) > > +{ > > + gas->space_id = space_id; > > + gas->bit_width = bit_width; > > + gas->bit_offset = bit_offset; > > + gas->access_width = access_width; > > + gas->address = address; > > +} > > + > > /* Load chipset information in FADT */ > > -static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm) > > +static void fadt_setup(AcpiFadtDescriptorRev5_1 *fadt, AcpiPmInfo > *pm, > > + uint8_t revision) > > { > > fadt->model = 1; > > fadt->reserved1 = 0; > > @@ -309,6 +323,25 @@ static void fadt_setup(AcpiFadtDescriptorRev1 > *fadt, AcpiPmInfo *pm) > > fadt->flags |= cpu_to_le32(1 << > ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL); > > } > > fadt->century = RTC_CENTURY; > > + > > + /* Build ACPI 2.0 (FADT version 3+) GAS fields */ > > + if (revision >= 3) { > > + /* EVT, CNT, TMR register matches hw/acpi/core.c */ > > + build_gas(&fadt->xpm1a_event_block, AML_SYSTEM_IO, > > + 32, 0, 0, cpu_to_le64(pm->io_base)); > > + build_gas(&fadt->xpm1a_control_block, AML_SYSTEM_IO, > > + 16, 0, 0, cpu_to_le64(pm->io_base + 0x04)); > > + build_gas(&fadt->xpm_timer_block, AML_SYSTEM_IO, > > + 32, 0, 0, cpu_to_le64(pm->io_base + 0x08)); > > + build_gas(&fadt->xgpe0_block, AML_SYSTEM_IO, > > + pm->gpe0_blk_len << 3, 0, 0, cpu_to_le64(pm->gpe0_blk)); > > + } > > + > > + /* Build dummy ACPI 5.0 fields */ > > + if (revision >= 5) { > > + build_gas(&fadt->sleep_control, AML_SYSTEM_MEMORY, 0, 0, 0, > 0); > > + build_gas(&fadt->sleep_status, AML_SYSTEM_MEMORY, 0, 0, 0, 0); > > + } > > } > > > > > > @@ -316,9 +349,9 @@ static void fadt_setup(AcpiFadtDescriptorRev1 > *fadt, AcpiPmInfo *pm) > > static void > > build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm, > > unsigned facs_tbl_offset, unsigned dsdt_tbl_offset, > > - const char *oem_id, const char *oem_table_id) > > + const char *oem_id, const char *oem_table_id, uint8_t revision) > > { > > - AcpiFadtDescriptorRev1 *fadt = acpi_data_push(table_data, > sizeof(*fadt)); > > + AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, > sizeof(*fadt)); > > unsigned fw_ctrl_offset = (char *)&fadt->firmware_ctrl - table_data- > >data; > > unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data; > > > > @@ -328,13 +361,28 @@ build_fadt(GArray *table_data, BIOSLinker > *linker, AcpiPmInfo *pm, > > ACPI_BUILD_TABLE_FILE, facs_tbl_offset); > > > > /* DSDT address to be filled by Guest linker */ > > - fadt_setup(fadt, pm); > > bios_linker_loader_add_pointer(linker, > > ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->dsdt), > > ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset); > > > > - build_header(linker, table_data, > > - (void *)fadt, "FACP", sizeof(*fadt), 1, oem_id, oem_table_id); > > + if (revision > 2) { > > + fw_ctrl_offset = (char *)&fadt->Xfacs - table_data->data; > > + dsdt_entry_offset = (char *)&fadt->Xdsdt - table_data->data; > > + > > + /* FACS address to be filled by Guest linker */ > > + bios_linker_loader_add_pointer(linker, > > + ACPI_BUILD_TABLE_FILE, fw_ctrl_offset, sizeof(fadt->Xfacs), > > + ACPI_BUILD_TABLE_FILE, facs_tbl_offset); > > + > > + /* DSDT address to be filled by Guest linker */ > > + bios_linker_loader_add_pointer(linker, > > + ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->Xdsdt), > > + ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset); > > + } > > + > > + fadt_setup(fadt, pm, revision); > > + build_header(linker, table_data, (void *)fadt, "FACP", sizeof(*fadt), > > + revision, oem_id, oem_table_id); > > } > > > > void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, > > @@ -2681,7 +2729,7 @@ void acpi_build(AcpiBuildTables *tables, > MachineState *machine) > > fadt = tables_blob->len; > > acpi_add_table(table_offsets, tables_blob); > > build_fadt(tables_blob, tables->linker, &pm, facs, dsdt, > > - slic_oem.id, slic_oem.table_id); > > + slic_oem.id, slic_oem.table_id, acpi_fadt_rev); > > aml_len += tables_blob->len - fadt; > > > > acpi_add_table(table_offsets, tables_blob); > > diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h > > index 7b3d93c..63df38d 100644 > > --- a/include/hw/acpi/acpi.h > > +++ b/include/hw/acpi/acpi.h > > @@ -173,6 +173,7 @@ void acpi_update_sci(ACPIREGS *acpi_regs, > qemu_irq irq); > > > > /* acpi.c */ > > extern int acpi_enabled; > > +extern uint8_t acpi_fadt_rev; > > extern char unsigned *acpi_tables; > > extern size_t acpi_tables_len; > > > > diff --git a/qemu-options.hx b/qemu-options.hx > > index a71aaf8..cff34f6 100644 > > --- a/qemu-options.hx > > +++ b/qemu-options.hx > > @@ -1492,6 +1492,15 @@ STEXI > > Disable HPET support. > > ETEXI > > > > +DEF("acpifadt", HAS_ARG, QEMU_OPTION_acpifadt, \ > > + "-acpifadt n configure FADT revision number (1, 3, 5)\n", > > + QEMU_ARCH_ALL) > > +STEXI > > +@item -acpifadt @var{n} > > +@findex -acpifadt > > +Configure FADT revision number, default is 1. > > +ETEXI > > + > > DEF("acpitable", HAS_ARG, QEMU_OPTION_acpitable, > > "-acpitable > [sig=str][,rev=n][,oem_id=str][,oem_table_id=str][,oem_rev=n][,asl_compi > ler_id=str][,asl_compiler_rev=n][,{data|file}=file1[:file2]...]\n" > > " ACPI table description\n", QEMU_ARCH_I386) > > diff --git a/vl.c b/vl.c > > index e7c2c62..220e36d 100644 > > --- a/vl.c > > +++ b/vl.c > > @@ -64,6 +64,7 @@ int main(int argc, char **argv) > > #include "hw/bt.h" > > #include "sysemu/watchdog.h" > > #include "hw/smbios/smbios.h" > > +#include "hw/acpi/acpi.h" > > #include "hw/xen/xen.h" > > #include "hw/qdev.h" > > #include "hw/loader.h" > > @@ -158,6 +159,7 @@ int max_cpus = 1; > > int smp_cores = 1; > > int smp_threads = 1; > > int acpi_enabled = 1; > > +uint8_t acpi_fadt_rev = 1; > > int no_hpet = 0; > > int fd_bootchk = 1; > > static int no_reboot; > > @@ -2301,6 +2303,24 @@ static int parse_fw_cfg(void *opaque, > QemuOpts *opts, Error **errp) > > return 0; > > } > > > > +static void fadt_parse(const char *arg) > > +{ > > + unsigned long rev; > > + int err; > > + > > + err = qemu_strtoul(arg, NULL, 10, &rev); > > + if (err) { > > + error_printf("Invalid FADT revision.\n"); > > + exit(1); > > + } > > + if (rev != 1 && rev != 3 && rev != 5) { > > + error_printf("Unsupported FADT revision %lu, " > > + "please specify 1,3,5.\n", rev); > > + exit(1); > > + } > > + acpi_fadt_rev = rev; > > +} > > + > > static int device_help_func(void *opaque, QemuOpts *opts, Error > **errp) > > { > > return qdev_device_help(opts); > > @@ -3622,6 +3642,9 @@ int main(int argc, char **argv, char **envp) > > qdev_prop_register_global(&slew_lost_ticks); > > break; > > } > > + case QEMU_OPTION_acpifadt: > > + fadt_parse(optarg); > > + break; > > case QEMU_OPTION_acpitable: > > opts = qemu_opts_parse_noisily(qemu_find_opts("acpi"), > > optarg, true); > >
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index ce7cbc5..4479695 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -276,8 +276,22 @@ build_facs(GArray *table_data, BIOSLinker *linker) facs->length = cpu_to_le32(sizeof(*facs)); } +/* GAS */ +static void +build_gas(struct AcpiGenericAddress *gas, uint8_t space_id, + uint8_t bit_width, uint8_t bit_offset, + uint8_t access_width, uint64_t address) +{ + gas->space_id = space_id; + gas->bit_width = bit_width; + gas->bit_offset = bit_offset; + gas->access_width = access_width; + gas->address = address; +} + /* Load chipset information in FADT */ -static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm) +static void fadt_setup(AcpiFadtDescriptorRev5_1 *fadt, AcpiPmInfo *pm, + uint8_t revision) { fadt->model = 1; fadt->reserved1 = 0; @@ -309,6 +323,25 @@ static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm) fadt->flags |= cpu_to_le32(1 << ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL); } fadt->century = RTC_CENTURY; + + /* Build ACPI 2.0 (FADT version 3+) GAS fields */ + if (revision >= 3) { + /* EVT, CNT, TMR register matches hw/acpi/core.c */ + build_gas(&fadt->xpm1a_event_block, AML_SYSTEM_IO, + 32, 0, 0, cpu_to_le64(pm->io_base)); + build_gas(&fadt->xpm1a_control_block, AML_SYSTEM_IO, + 16, 0, 0, cpu_to_le64(pm->io_base + 0x04)); + build_gas(&fadt->xpm_timer_block, AML_SYSTEM_IO, + 32, 0, 0, cpu_to_le64(pm->io_base + 0x08)); + build_gas(&fadt->xgpe0_block, AML_SYSTEM_IO, + pm->gpe0_blk_len << 3, 0, 0, cpu_to_le64(pm->gpe0_blk)); + } + + /* Build dummy ACPI 5.0 fields */ + if (revision >= 5) { + build_gas(&fadt->sleep_control, AML_SYSTEM_MEMORY, 0, 0, 0, 0); + build_gas(&fadt->sleep_status, AML_SYSTEM_MEMORY, 0, 0, 0, 0); + } } @@ -316,9 +349,9 @@ static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm) static void build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm, unsigned facs_tbl_offset, unsigned dsdt_tbl_offset, - const char *oem_id, const char *oem_table_id) + const char *oem_id, const char *oem_table_id, uint8_t revision) { - AcpiFadtDescriptorRev1 *fadt = acpi_data_push(table_data, sizeof(*fadt)); + AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt)); unsigned fw_ctrl_offset = (char *)&fadt->firmware_ctrl - table_data->data; unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data; @@ -328,13 +361,28 @@ build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm, ACPI_BUILD_TABLE_FILE, facs_tbl_offset); /* DSDT address to be filled by Guest linker */ - fadt_setup(fadt, pm); bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->dsdt), ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset); - build_header(linker, table_data, - (void *)fadt, "FACP", sizeof(*fadt), 1, oem_id, oem_table_id); + if (revision > 2) { + fw_ctrl_offset = (char *)&fadt->Xfacs - table_data->data; + dsdt_entry_offset = (char *)&fadt->Xdsdt - table_data->data; + + /* FACS address to be filled by Guest linker */ + bios_linker_loader_add_pointer(linker, + ACPI_BUILD_TABLE_FILE, fw_ctrl_offset, sizeof(fadt->Xfacs), + ACPI_BUILD_TABLE_FILE, facs_tbl_offset); + + /* DSDT address to be filled by Guest linker */ + bios_linker_loader_add_pointer(linker, + ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->Xdsdt), + ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset); + } + + fadt_setup(fadt, pm, revision); + build_header(linker, table_data, (void *)fadt, "FACP", sizeof(*fadt), + revision, oem_id, oem_table_id); } void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, @@ -2681,7 +2729,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) fadt = tables_blob->len; acpi_add_table(table_offsets, tables_blob); build_fadt(tables_blob, tables->linker, &pm, facs, dsdt, - slic_oem.id, slic_oem.table_id); + slic_oem.id, slic_oem.table_id, acpi_fadt_rev); aml_len += tables_blob->len - fadt; acpi_add_table(table_offsets, tables_blob); diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h index 7b3d93c..63df38d 100644 --- a/include/hw/acpi/acpi.h +++ b/include/hw/acpi/acpi.h @@ -173,6 +173,7 @@ void acpi_update_sci(ACPIREGS *acpi_regs, qemu_irq irq); /* acpi.c */ extern int acpi_enabled; +extern uint8_t acpi_fadt_rev; extern char unsigned *acpi_tables; extern size_t acpi_tables_len; diff --git a/qemu-options.hx b/qemu-options.hx index a71aaf8..cff34f6 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1492,6 +1492,15 @@ STEXI Disable HPET support. ETEXI +DEF("acpifadt", HAS_ARG, QEMU_OPTION_acpifadt, \ + "-acpifadt n configure FADT revision number (1, 3, 5)\n", + QEMU_ARCH_ALL) +STEXI +@item -acpifadt @var{n} +@findex -acpifadt +Configure FADT revision number, default is 1. +ETEXI + DEF("acpitable", HAS_ARG, QEMU_OPTION_acpitable, "-acpitable [sig=str][,rev=n][,oem_id=str][,oem_table_id=str][,oem_rev=n][,asl_compiler_id=str][,asl_compiler_rev=n][,{data|file}=file1[:file2]...]\n" " ACPI table description\n", QEMU_ARCH_I386) diff --git a/vl.c b/vl.c index e7c2c62..220e36d 100644 --- a/vl.c +++ b/vl.c @@ -64,6 +64,7 @@ int main(int argc, char **argv) #include "hw/bt.h" #include "sysemu/watchdog.h" #include "hw/smbios/smbios.h" +#include "hw/acpi/acpi.h" #include "hw/xen/xen.h" #include "hw/qdev.h" #include "hw/loader.h" @@ -158,6 +159,7 @@ int max_cpus = 1; int smp_cores = 1; int smp_threads = 1; int acpi_enabled = 1; +uint8_t acpi_fadt_rev = 1; int no_hpet = 0; int fd_bootchk = 1; static int no_reboot; @@ -2301,6 +2303,24 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp) return 0; } +static void fadt_parse(const char *arg) +{ + unsigned long rev; + int err; + + err = qemu_strtoul(arg, NULL, 10, &rev); + if (err) { + error_printf("Invalid FADT revision.\n"); + exit(1); + } + if (rev != 1 && rev != 3 && rev != 5) { + error_printf("Unsupported FADT revision %lu, " + "please specify 1,3,5.\n", rev); + exit(1); + } + acpi_fadt_rev = rev; +} + static int device_help_func(void *opaque, QemuOpts *opts, Error **errp) { return qdev_device_help(opts); @@ -3622,6 +3642,9 @@ int main(int argc, char **argv, char **envp) qdev_prop_register_global(&slew_lost_ticks); break; } + case QEMU_OPTION_acpifadt: + fadt_parse(optarg); + break; case QEMU_OPTION_acpitable: opts = qemu_opts_parse_noisily(qemu_find_opts("acpi"), optarg, true);
This patch allows FADT to be built with different revisions. When the revision is greater than 1.0, 64-bit address fields may also be filled. Note that FADT revision 2 has never been defined by the ACPI specification. So this patch only adds an option -acpifadt to allow revision 1,3,5 to be configured by the users. 1. Tested by booting a linux image, the 64-bit addresses are correctly filled in the dumped FADT. 2. Tested by booting a Windows image, no boot failure can be seen. Signed-off-by: Lv Zheng <lv.zheng@intel.com> --- History: v2: Fix coding style issues. --- hw/i386/acpi-build.c | 62 ++++++++++++++++++++++++++++++++++++++++++------ include/hw/acpi/acpi.h | 1 + qemu-options.hx | 9 +++++++ vl.c | 23 ++++++++++++++++++ 4 files changed, 88 insertions(+), 7 deletions(-)