[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-arm] [Qemu-devel] [PATCH 5/9] pc: acpi: isolate FADT specific
From: |
Igor Mammedov |
Subject: |
Re: [Qemu-arm] [Qemu-devel] [PATCH 5/9] pc: acpi: isolate FADT specific data into AcpiFadtData structure |
Date: |
Tue, 27 Feb 2018 16:44:24 +0100 |
On Tue, 27 Feb 2018 14:47:16 +0100
Auger Eric <address@hidden> wrote:
> Hi Igor,
>
> On 22/02/18 13:42, Igor Mammedov wrote:
> > move FADT data initialization out of fadt_setup() into dedicated
> > init_fadt_data() that will set common for pc/q35 values in
> > AcpiFadtData structure and acpi_get_pm_info() will complement
> > it with pc/q35 specific values initialization.
> acpi_get_pm_info only adds reset stuff + version info on top of
> previously initialized common data, right?
yep
> > That will allow to get rid of fadt_setup() and generalize
> > build_fadt() so it could be easily extended for rev5 and
> > reused by ARM target.
> >
> > While at it also move facs/dsdt/xdsdt offsets from build_fadt()
> > arg list into AcpiFadtData, as they belong to the same dataset.
> >
> > Signed-off-by: Igor Mammedov <address@hidden>
> > ---
> > include/hw/acpi/acpi-defs.h | 28 ++++++
> > hw/i386/acpi-build.c | 204
> > ++++++++++++++++++++++++--------------------
> > 2 files changed, 138 insertions(+), 94 deletions(-)
> >
> > diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
> > index 9942bc5..e0accc4 100644
> > --- a/include/hw/acpi/acpi-defs.h
> > +++ b/include/hw/acpi/acpi-defs.h
> > @@ -175,6 +175,34 @@ struct AcpiFadtDescriptorRev5_1 {
> >
> > typedef struct AcpiFadtDescriptorRev5_1 AcpiFadtDescriptorRev5_1;
> >
> > +typedef struct AcpiFadtData {
> > + struct AcpiGenericAddress pm1_cnt; /* PM1a_CNT_BLK */
> Any reason why we don't use the same field names as in
> AcpiFadtDescriptorRev3?
I'll amend it on respin as you suggest.
>
> for instance pm1a_cnt?
> > + struct AcpiGenericAddress pm1_evt; /* PM1a_EVT_BLK */
> pm1a_evt?
> > + struct AcpiGenericAddress pm_tmr; /* PM_TMR_BLK */
> > + struct AcpiGenericAddress gpe0_blk; /* GPE0_BLK */
> > + struct AcpiGenericAddress reset_reg; /* RESET_REG */
> > + uint8_t reset_val; /* RESET_VALUE */
> > + uint8_t rev; /* Revision */
> > + uint32_t flags; /* Flags */
> > + uint32_t smi_cmd; /* SMI_CMD */
> > + uint16_t sci_int; /* SCI_INT */
> > + uint8_t int_model; /* INT_MODEL */
> > + uint8_t acpi_enable_cmd; /* ACPI_ENABLE */
> > + uint8_t acpi_disable_cmd; /* ACPI_DISABLE */
> > + uint8_t rtc_century; /* CENTURY */
> > + uint16_t c2_latency; /* P_LVL2_LAT */
> same?
> > + uint16_t c3_latency; /* P_LVL3_LAT */
> > +
> > + /*
> > + * respective tables offsets within ACPI_BUILD_TABLE_FILE,
> > + * NULL if table doesn't exist (in that case field's value
> > + * won't be patched by linker and will be kept set to 0)
> > + */
> > + unsigned *facs_tbl_offset; /* FACS offset in */
> > + unsigned *dsdt_tbl_offset;
> > + unsigned *xdsdt_tbl_offset;
> > +} AcpiFadtData;
> > +
> > #define ACPI_FADT_ARM_PSCI_COMPLIANT (1 << 0)
> > #define ACPI_FADT_ARM_PSCI_USE_HVC (1 << 1)
> >
> > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > index b85fefe..706ba35 100644
> > --- a/hw/i386/acpi-build.c
> > +++ b/hw/i386/acpi-build.c
> > @@ -91,17 +91,11 @@ typedef struct AcpiMcfgInfo {
> > } AcpiMcfgInfo;
> >
> > typedef struct AcpiPmInfo {
> > - bool force_rev1_fadt;
> > bool s3_disabled;
> > bool s4_disabled;
> > bool pcihp_bridge_en;
> > uint8_t s4_val;
> > - uint16_t sci_int;
> > - uint8_t acpi_enable_cmd;
> > - uint8_t acpi_disable_cmd;
> > - uint32_t gpe0_blk;
> > - uint32_t gpe0_blk_len;
> > - uint32_t io_base;
> > + AcpiFadtData fadt;
> > uint16_t cpu_hp_io_base;
> > uint16_t pcihp_io_base;
> > uint16_t pcihp_io_len;
> > @@ -124,20 +118,60 @@ typedef struct AcpiBuildPciBusHotplugState {
> > bool pcihp_bridge_en;
> > } AcpiBuildPciBusHotplugState;
> >
> > +#define ACPI_PORT_SMI_CMD 0x00b2 /* TODO: this is APM_CNT_IOPORT
> > */
> Can't we take benefit of this series to move that define in hw/isa/apm.h?
> > +
> > +static void init_fadt_data(Object *o, AcpiFadtData *data)
> > +{
> > + uint32_t io = object_property_get_uint(o, ACPI_PM_PROP_PM_IO_BASE,
> > NULL);
> > + AmlAddressSpace as = AML_AS_SYSTEM_IO;
> > + AcpiFadtData fadt = {
> > + .rev = 3,
> > + .flags =
> > + (1 << ACPI_FADT_F_WBINVD) |
> > + (1 << ACPI_FADT_F_PROC_C1) |
> > + (1 << ACPI_FADT_F_SLP_BUTTON) |
> > + (1 << ACPI_FADT_F_RTC_S4) |
> > + (1 << ACPI_FADT_F_USE_PLATFORM_CLOCK) |
> > + /* APIC destination mode ("Flat Logical") has an upper limit
> > of 8
> > + * CPUs for more than 8 CPUs, "Clustered Logical" mode has to
> > be
> > + * used
> > + */
> > + ((max_cpus > 8) ? (1 << ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL)
> > : 0),
> > + .int_model = 1 /* Multiple APIC */,
> > + .rtc_century = RTC_CENTURY,
> > + .c2_latency = 0xfff /* C2 state not supported */,
> > + .c3_latency = 0xfff /* C3 state not supported */,
> > + .smi_cmd = ACPI_PORT_SMI_CMD,
> > + .sci_int = object_property_get_uint(o, ACPI_PM_PROP_SCI_INT, NULL),
> > + .acpi_enable_cmd =
> > + object_property_get_uint(o, ACPI_PM_PROP_ACPI_ENABLE_CMD,
> > NULL),
> > + .acpi_disable_cmd =
> > + object_property_get_uint(o, ACPI_PM_PROP_ACPI_DISABLE_CMD,
> > NULL),
> > + .pm1_evt = { .space_id = as, .bit_width = 4 * 8, .address = io },
> > + .pm1_cnt = { .space_id = as, .bit_width = 2 * 8, .address = io +
> > 0x04 },
> > + .pm_tmr = { .space_id = as, .bit_width = 4 * 8, .address = io +
> > 0x08 },
> > + .gpe0_blk = { .space_id = as, .bit_width =
> > + object_property_get_uint(o, ACPI_PM_PROP_GPE0_BLK_LEN, NULL) *
> > 8,
> > + .address = object_property_get_uint(o, ACPI_PM_PROP_GPE0_BLK,
> > NULL)
> > + },
> > + };
> > + *data = fadt;
> > +}
> > +
> > static void acpi_get_pm_info(AcpiPmInfo *pm)
> > {
> > Object *piix = piix4_pm_find();
> > Object *lpc = ich9_lpc_find();
> > Object *obj = piix ? piix : lpc;
> > QObject *o;
> > -
> > - pm->force_rev1_fadt = false;
> > pm->cpu_hp_io_base = 0;
> > pm->pcihp_io_base = 0;
> > pm->pcihp_io_len = 0;
> > +
> > + init_fadt_data(obj, &pm->fadt);
> > if (piix) {
> > /* w2k requires FADT(rev1) or it won't boot, keep PC compatible */
> > - pm->force_rev1_fadt = true;
> > + pm->fadt.rev = 1;
> > pm->cpu_hp_io_base = PIIX4_CPU_HOTPLUG_IO_BASE;
> > pm->pcihp_io_base =
> > object_property_get_uint(obj, ACPI_PCIHP_IO_BASE_PROP, NULL);
> > @@ -145,10 +179,19 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
> > object_property_get_uint(obj, ACPI_PCIHP_IO_LEN_PROP, NULL);
> > }
> > if (lpc) {
> > + struct AcpiGenericAddress r = { .space_id = AML_AS_SYSTEM_IO,
> > + .bit_width = 8, .address = ICH9_RST_CNT_IOPORT };
> > + pm->fadt.reset_reg = r;
> > + pm->fadt.reset_val = 0xf;
> > + pm->fadt.flags |= 1 << ACPI_FADT_F_RESET_REG_SUP;
> > pm->cpu_hp_io_base = ICH9_CPU_HOTPLUG_IO_BASE;
> Wouldn't it be possible to pass an other parameter to init_fadt_data()
> to tell whether we are in pc or q35 or the target rev and do those
> initializations there?
It's possible but I wanted to keep pc/q35 specific pieces explicitly
split from common data initialization as personally for me this way
it's easier to see difference (i.e. there is no need to jump into
init_fadt_data()).
Perhaps I should rename init_fadt_data() to init_common_fadt_data().
> > }
> > assert(obj);
> >
> > + /* The above need not be conditional on machine type because the reset
> > port
> > + * happens to be the same on PIIX (pc) and ICH9 (q35). */
> > + QEMU_BUILD_BUG_ON(ICH9_RST_CNT_IOPORT != RCR_IOPORT);
> > +
> > /* Fill in optional s3/s4 related properties */
> > o = object_property_get_qobject(obj, ACPI_PM_PROP_S3_DISABLED, NULL);
> > if (o) {
> > @@ -172,22 +215,6 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
> > }
> > qobject_decref(o);
> >
> > - /* Fill in mandatory properties */
> > - pm->sci_int = object_property_get_uint(obj, ACPI_PM_PROP_SCI_INT,
> > NULL);
> > -
> > - pm->acpi_enable_cmd = object_property_get_uint(obj,
> > -
> > ACPI_PM_PROP_ACPI_ENABLE_CMD,
> > - NULL);
> > - pm->acpi_disable_cmd =
> > - object_property_get_uint(obj,
> > - ACPI_PM_PROP_ACPI_DISABLE_CMD,
> > - NULL);
> > - pm->io_base = object_property_get_uint(obj, ACPI_PM_PROP_PM_IO_BASE,
> > - NULL);
> > - pm->gpe0_blk = object_property_get_uint(obj, ACPI_PM_PROP_GPE0_BLK,
> > - NULL);
> > - pm->gpe0_blk_len = object_property_get_uint(obj,
> > ACPI_PM_PROP_GPE0_BLK_LEN,
> > - NULL);
> > pm->pcihp_bridge_en =
> > object_property_get_bool(obj,
> > "acpi-pci-hotplug-with-bridge-support",
> > NULL);
> > @@ -255,8 +282,6 @@ static void acpi_get_pci_holes(Range *hole, Range
> > *hole64)
> > NULL));
> > }
> >
> > -#define ACPI_PORT_SMI_CMD 0x00b2 /* TODO: this is APM_CNT_IOPORT
> > */
> > -
> > static void acpi_align_size(GArray *blob, unsigned align)
> > {
> > /* Align size to multiple of given size. This reduces the chance
> > @@ -275,73 +300,53 @@ build_facs(GArray *table_data, BIOSLinker *linker)
> > }
> >
> > /* Load chipset information in FADT */
> > -static void fadt_setup(AcpiFadtDescriptorRev3 *fadt, AcpiPmInfo *pm)
> > +static void fadt_setup(AcpiFadtDescriptorRev3 *fadt, AcpiFadtData f)
> > {
> > - fadt->model = 1;
> > + fadt->model = f.int_model;
> > fadt->reserved1 = 0;
> > - fadt->sci_int = cpu_to_le16(pm->sci_int);
> > - fadt->smi_cmd = cpu_to_le32(ACPI_PORT_SMI_CMD);
> > - fadt->acpi_enable = pm->acpi_enable_cmd;
> > - fadt->acpi_disable = pm->acpi_disable_cmd;
> > + fadt->sci_int = cpu_to_le16(f.sci_int);
> > + fadt->smi_cmd = cpu_to_le32(f.smi_cmd);
> > + fadt->acpi_enable = f.acpi_enable_cmd;
> > + fadt->acpi_disable = f.acpi_disable_cmd;
> > /* EVT, CNT, TMR offset matches hw/acpi/core.c */
> > - fadt->pm1a_evt_blk = cpu_to_le32(pm->io_base);
> > - fadt->pm1a_cnt_blk = cpu_to_le32(pm->io_base + 0x04);
> > - fadt->pm_tmr_blk = cpu_to_le32(pm->io_base + 0x08);
> > - fadt->gpe0_blk = cpu_to_le32(pm->gpe0_blk);
> > + fadt->pm1a_evt_blk = cpu_to_le32(f.pm1_evt.address);
> > + fadt->pm1a_cnt_blk = cpu_to_le32(f.pm1_cnt.address);
> > + fadt->pm_tmr_blk = cpu_to_le32(f.pm_tmr.address);
> > + fadt->gpe0_blk = cpu_to_le32(f.gpe0_blk.address);
> > /* EVT, CNT, TMR length matches hw/acpi/core.c */
> > - fadt->pm1_evt_len = 4;
> > - fadt->pm1_cnt_len = 2;
> > - fadt->pm_tmr_len = 4;
> > - fadt->gpe0_blk_len = pm->gpe0_blk_len;
> > - fadt->plvl2_lat = cpu_to_le16(0xfff); /* C2 state not supported */
> > - fadt->plvl3_lat = cpu_to_le16(0xfff); /* C3 state not supported */
> > - fadt->flags = cpu_to_le32((1 << ACPI_FADT_F_WBINVD) |
> > - (1 << ACPI_FADT_F_PROC_C1) |
> > - (1 << ACPI_FADT_F_SLP_BUTTON) |
> > - (1 << ACPI_FADT_F_RTC_S4));
> > - fadt->flags |= cpu_to_le32(1 << ACPI_FADT_F_USE_PLATFORM_CLOCK);
> > - /* APIC destination mode ("Flat Logical") has an upper limit of 8 CPUs
> > - * For more than 8 CPUs, "Clustered Logical" mode has to be used
> > - */
> > - if (max_cpus > 8) {
> > - fadt->flags |= cpu_to_le32(1 <<
> > ACPI_FADT_F_FORCE_APIC_CLUSTER_MODEL);
> > - }
> > - fadt->century = RTC_CENTURY;
> > - if (pm->force_rev1_fadt) {
> > + fadt->pm1_evt_len = f.pm1_evt.bit_width / 8;
> > + fadt->pm1_cnt_len = f.pm1_cnt.bit_width / 8;
> > + fadt->pm_tmr_len = f.pm_tmr.bit_width / 8;
> > + fadt->gpe0_blk_len = f.gpe0_blk.bit_width / 8;
> > + fadt->plvl2_lat = cpu_to_le16(f.c2_latency);
> > + fadt->plvl3_lat = cpu_to_le16(f.c3_latency);
> > + fadt->flags = cpu_to_le32(f.flags);
> > + fadt->century = f.rtc_century;
> > + if (f.rev == 1) {
> > return;
> > }
> >
> > - fadt->flags |= cpu_to_le32(1 << ACPI_FADT_F_RESET_REG_SUP);
> > - fadt->reset_value = 0xf;
> > - fadt->reset_register.space_id = AML_SYSTEM_IO;
> > - fadt->reset_register.bit_width = 8;
> > - fadt->reset_register.address = cpu_to_le64(ICH9_RST_CNT_IOPORT);
> > - /* The above need not be conditional on machine type because the reset
> > port
> > - * happens to be the same on PIIX (pc) and ICH9 (q35). */
> > - QEMU_BUILD_BUG_ON(ICH9_RST_CNT_IOPORT != RCR_IOPORT);
> > + fadt->reset_value = f.reset_val;
> > + fadt->reset_register = f.reset_reg;
> > + fadt->reset_register.address = cpu_to_le64(f.reset_reg.address);
> >
> > - fadt->xpm1a_event_block.space_id = AML_SYSTEM_IO;
> > - fadt->xpm1a_event_block.bit_width = fadt->pm1_evt_len * 8;
> > - fadt->xpm1a_event_block.address = cpu_to_le64(pm->io_base);
> > + fadt->xpm1a_event_block = f.pm1_evt;
> > + fadt->xpm1a_event_block.address = cpu_to_le64(f.pm1_evt.address);
> >
> > - fadt->xpm1a_control_block.space_id = AML_SYSTEM_IO;
> > - fadt->xpm1a_control_block.bit_width = fadt->pm1_cnt_len * 8;
> > - fadt->xpm1a_control_block.address = cpu_to_le64(pm->io_base + 0x4);
> > + fadt->xpm1a_control_block = f.pm1_cnt;
> > + fadt->xpm1a_control_block.address = cpu_to_le64(f.pm1_cnt.address);
> >
> > - fadt->xpm_timer_block.space_id = AML_SYSTEM_IO;
> > - fadt->xpm_timer_block.bit_width = fadt->pm_tmr_len * 8;
> > - fadt->xpm_timer_block.address = cpu_to_le64(pm->io_base + 0x8);
> > + fadt->xpm_timer_block = f.pm_tmr;
> > + fadt->xpm_timer_block.address = cpu_to_le64(f.pm_tmr.address);
> >
> > - fadt->xgpe0_block.space_id = AML_SYSTEM_IO;
> > - fadt->xgpe0_block.bit_width = pm->gpe0_blk_len * 8;
> > - fadt->xgpe0_block.address = cpu_to_le64(pm->gpe0_blk);
> > + fadt->xgpe0_block = f.gpe0_blk;
> > + fadt->xgpe0_block.address = cpu_to_le64(f.gpe0_blk.address);
> > }
> >
> >
> > /* FADT */
> > static void
> > -build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm,
> > - unsigned facs_tbl_offset, unsigned dsdt_tbl_offset,
> > +build_fadt(GArray *table_data, BIOSLinker *linker, AcpiFadtData *f,
> > const char *oem_id, const char *oem_table_id)
> > {
> > AcpiFadtDescriptorRev3 *fadt = acpi_data_push(table_data,
> > sizeof(*fadt));
> > @@ -349,29 +354,32 @@ build_fadt(GArray *table_data, BIOSLinker *linker,
> > AcpiPmInfo *pm,
> > unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data;
> > unsigned xdsdt_entry_offset = (char *)&fadt->x_dsdt - table_data->data;
> > int fadt_size = sizeof(*fadt);
> > - int rev = 3;
> >
> > /* FACS address to be filled by Guest linker */
> > - bios_linker_loader_add_pointer(linker,
> > - ACPI_BUILD_TABLE_FILE, fw_ctrl_offset, sizeof(fadt->firmware_ctrl),
> > - ACPI_BUILD_TABLE_FILE, facs_tbl_offset);
> > + if (f->facs_tbl_offset) {
> this test was not there originally. How does it relate to above changes?
[...]
> > + if (f->dsdt_tbl_offset) {
> same
I guess it is sort of slipped in from (7/9) patch,
as this fields can be 0 and don't need dynamic patching.
Theoretically facs/dsdt could be 0 for x86 too if we drop support
for 32bit guests (which isn't going to happen).
I can move it to 7/9 which moves build_fadt into generic code from x86 specific,
which is more appropriate place for it.
> > + bios_linker_loader_add_pointer(linker,
> > + ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->dsdt),
> > + ACPI_BUILD_TABLE_FILE, *f->dsdt_tbl_offset);
> > + }
> > + if (f->rev == 1) {
> > fadt_size = offsetof(typeof(*fadt), reset_register);
> > - } else {
> > + } else if (f->xdsdt_tbl_offset) {
> > bios_linker_loader_add_pointer(linker,
> > ACPI_BUILD_TABLE_FILE, xdsdt_entry_offset,
> > sizeof(fadt->x_dsdt),
> > - ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset);
> > + ACPI_BUILD_TABLE_FILE, *f->xdsdt_tbl_offset);
> > }
> >
> > build_header(linker, table_data,
> > - (void *)fadt, "FACP", fadt_size, rev, oem_id,
> > oem_table_id);
> > + (void *)fadt, "FACP", fadt_size, f->rev,
> > + oem_id, oem_table_id);
> > }
> >
> > void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
> > @@ -2051,7 +2059,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> > aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
> > crs = aml_resource_template();
> > aml_append(crs,
> > - aml_io(AML_DECODE16, pm->gpe0_blk, pm->gpe0_blk, 1,
> > pm->gpe0_blk_len)
> > + aml_io(
> > + AML_DECODE16,
> > + pm->fadt.gpe0_blk.address,
> > + pm->fadt.gpe0_blk.address,
> > + 1,
> > + pm->fadt.gpe0_blk.bit_width / 8)
> > );
> > aml_append(dev, aml_name_decl("_CRS", crs));
> > aml_append(scope, dev);
> > @@ -2698,7 +2711,10 @@ void acpi_build(AcpiBuildTables *tables,
> > MachineState *machine)
> > /* ACPI tables pointed to by RSDT */
> > fadt = tables_blob->len;
> > acpi_add_table(table_offsets, tables_blob);
> > - build_fadt(tables_blob, tables->linker, &pm, facs, dsdt,
> > + pm.fadt.facs_tbl_offset = &facs;
> > + pm.fadt.dsdt_tbl_offset = &dsdt;
> > + pm.fadt.xdsdt_tbl_offset = &dsdt;
> > + build_fadt(tables_blob, tables->linker, &pm.fadt,
> > slic_oem.id, slic_oem.table_id);
> > aml_len += tables_blob->len - fadt;
> >
> >
> Otherwise looks good to me.
>
> Thanks
>
> Eric
- Re: [Qemu-arm] [Qemu-devel] [PATCH 1/9] acpi: remove unused acpi-dsdt.aml, (continued)
- [Qemu-arm] [PATCH 3/9] acpi: reuse AcpiGenericAddress instead of Acpi20GenericAddress, Igor Mammedov, 2018/02/22
- [Qemu-arm] [PATCH 2/9] pc: replace pm object initialization with one-liner in acpi_get_pm_info(), Igor Mammedov, 2018/02/22
- [Qemu-arm] [PATCH 4/9] acpi: add build_append_gas() helper for Generic Address Structure, Igor Mammedov, 2018/02/22
- [Qemu-arm] [PATCH 5/9] pc: acpi: isolate FADT specific data into AcpiFadtData structure, Igor Mammedov, 2018/02/22
- [Qemu-arm] [PATCH 6/9] pc: acpi: use build_append_foo() API to construct FADT, Igor Mammedov, 2018/02/22
- [Qemu-arm] [PATCH 7/9] acpi: move build_fadt() from i386 specific to generic ACPI source, Igor Mammedov, 2018/02/22
- [Qemu-arm] [PATCH 8/9] virt_arm: acpi: reuse common build_fadt(), Igor Mammedov, 2018/02/22
- [Qemu-arm] [PATCH 9/9] tests: acpi: don't read all fields in test_acpi_fadt_table(), Igor Mammedov, 2018/02/22