[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 24/33] acpi: add CPU hotplug methods to DSDT
From: |
Igor Mammedov |
Subject: |
Re: [Qemu-devel] [PATCH 24/33] acpi: add CPU hotplug methods to DSDT |
Date: |
Tue, 31 May 2016 10:45:00 +0200 |
On Tue, 31 May 2016 07:38:08 +0300
"Michael S. Tsirkin" <address@hidden> wrote:
> On Tue, May 17, 2016 at 04:43:16PM +0200, Igor Mammedov wrote:
> > Add necessary CPU hotplug methods to handle hotplug
> > events.
> >
> > Signed-off-by: Igor Mammedov <address@hidden>
> > ---
> > v1:
> > - make replace _MAT method with named buffer object
> > as its content is static
> > ---
> > hw/acpi/cpu.c | 187
> > +++++++++++++++++++++++++++++++++++++++++++++++++-
> > hw/i386/acpi-build.c | 3 +-
> > include/hw/acpi/cpu.h | 4 +-
> > 3 files changed, 190 insertions(+), 4 deletions(-)
> >
> > diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
> > index b3e1cca..28d3894 100644
> > --- a/hw/acpi/cpu.c
> > +++ b/hw/acpi/cpu.c
> > @@ -207,24 +207,178 @@ const VMStateDescription vmstate_cpu_hotplug = {
> > };
> >
> > #define CPU_NAME_FMT "C%.03X"
> > -
> > -void build_cpus_aml(Aml *table, MachineState *machine, bool acpi1_compat)
> > +#define CPUHP_RES_DEVICE "PRES"
> > +#define CPU_LOCK "CPLK"
> > +#define CPU_STS_METHOD "CSTA"
> > +#define CPU_SCAN_METHOD "CSCN"
> > +#define CPU_EJECT_METHOD "CEJ0"
> > +#define CPU_NOTIFY_METHOD "CTFY"
> > +
> > +#define CPU_ENABLED "CPEN"
> > +#define CPU_SELECTOR "CSEL"
> > +#define CPU_EJECT_EVENT "CEJ0"
> > +#define CPU_INSERT_EVENT "CINS"
> > +#define CPU_REMOVE_EVENT "CRMV"
> > +
> > +void build_cpus_aml(Aml *table, MachineState *machine, bool acpi1_compat,
> > + const char *res_root, const char *event_handler_method,
> > + hwaddr io_base)
> > {
> > + Aml *ifctx;
> > + Aml *field;
> > + Aml *method;
> > + Aml *cpu_ctrl_dev;
> > Aml *cpus_dev;
> > + Aml *zero = aml_int(0);
> > Aml *sb_scope = aml_scope("_SB");
> > MachineClass *mc = MACHINE_GET_CLASS(machine);
> > CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(machine);
> > + char *cphp_res_path = g_strdup_printf("%s." CPUHP_RES_DEVICE,
> > res_root);
> > + Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, NULL);
> > + AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
> > + AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);
> > +
> > + cpu_ctrl_dev = aml_device("%s", cphp_res_path);
> > + {
> > + Aml *crs;
> > +
> > + aml_append(cpu_ctrl_dev,
> > + aml_name_decl("_HID", aml_eisaid("PNP0A06")));
> > + aml_append(cpu_ctrl_dev,
> > + aml_name_decl("_UID", aml_string("CPU Hotplug resources")));
> > + aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0));
> > +
> > + crs = aml_resource_template();
> > + aml_append(crs, aml_io(AML_DECODE16, io_base, io_base, 1,
> > + ACPI_CPU_HOTPLUG_REG_LEN));
> > + aml_append(cpu_ctrl_dev, aml_name_decl("_CRS", crs));
> > +
> > + /* declare CPU hotplug MMIO region with related access fields */
> > + aml_append(cpu_ctrl_dev,
> > + aml_operation_region("PRST", AML_SYSTEM_IO, aml_int(io_base),
> > + ACPI_CPU_HOTPLUG_REG_LEN));
> > +
> > + field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK,
> > + AML_WRITE_AS_ZEROS);
> > + aml_append(field, aml_reserved_field(ACPI_CPU_FLAGS_OFFSET_RW *
> > 8));
> > + /* 1 if enabled, read only */
> > + aml_append(field, aml_named_field(CPU_ENABLED, 1));
> > + /* (read) 1 if has a insert event. (write) 1 to clear event */
> > + aml_append(field, aml_named_field(CPU_INSERT_EVENT, 1));
> > + /* (read) 1 if has a remove event. (write) 1 to clear event */
> > + aml_append(field, aml_named_field(CPU_REMOVE_EVENT, 1));
> > + /* initiates device eject, write only */
> > + aml_append(field, aml_named_field(CPU_EJECT_EVENT, 1));
> > + aml_append(cpu_ctrl_dev, field);
> > +
> > + field = aml_field("PRST", AML_DWORD_ACC, AML_NOLOCK, AML_PRESERVE);
> > + /* CPU selector, write only */
> > + aml_append(field, aml_named_field(CPU_SELECTOR, 32));
> > + aml_append(cpu_ctrl_dev, field);
> > +
> > + }
> > + aml_append(sb_scope, cpu_ctrl_dev);
> > +
> > cpus_dev = aml_device("\\_SB.CPUS");
> > {
> > int i;
> > + Aml *one = aml_int(1);
> > + Aml *cpu_selector = aml_name("%s.%s", cphp_res_path, CPU_SELECTOR);
> > + Aml *ins_evt = aml_name("%s.%s", cphp_res_path, CPU_INSERT_EVENT);
> > + Aml *rm_evt = aml_name("%s.%s", cphp_res_path, CPU_REMOVE_EVENT);
> > + Aml *ej_evt = aml_name("%s.%s", cphp_res_path, CPU_EJECT_EVENT);
> > + Aml *is_enabled = aml_name("%s.%s", cphp_res_path, CPU_ENABLED);
> > + Aml *ctrl_lock = aml_name("%s.%s", cphp_res_path, CPU_LOCK);
> >
> > aml_append(cpus_dev, aml_name_decl("_HID",
> > aml_string("ACPI0010")));
> > aml_append(cpus_dev, aml_name_decl("_CID", aml_eisaid("PNP0A05")));
> >
> > + method = aml_method(CPU_NOTIFY_METHOD, 2, AML_NOTSERIALIZED);
> > + for (i = 0; i < arch_ids->len; i++) {
>
> wow that will be a ton of acpi code. why not create an AML loop?
I wish I could that would shrink corresponding current CPU/PCI/MEM hotplug
notifiers a lot.
I've spend several days trying to convince Notify() to take anything
else except of plain NameString which according to spec should
be possible but I failed miserably with different degree of
failure/success depending on linux/windows versions.
If you have any idea how to construct name string inside AML using
AML operators I'm all ears.
I've also tried other way around by sending bus check event to \_SB.CPUS,
that partially worked, i.e. for linux or windows (I don't remember which one)
and also depended on OS version.
So I've done it the old way, as we were doing it for current CPU/PCI/MEM
hotplug.
> > + Aml *cpu = aml_name(CPU_NAME_FMT, i);
> > + Aml *uid = aml_arg(0);
> > + Aml *event = aml_arg(1);
> > +
> > + ifctx = aml_if(aml_equal(uid, aml_int(i)));
> > + {
> > + aml_append(ifctx, aml_notify(cpu, event));
> > + }
> > + aml_append(method, ifctx);
> > + }
> > + aml_append(cpus_dev, method);
> > +
> > + method = aml_method(CPU_STS_METHOD, 1, AML_SERIALIZED);
> > + {
> > + Aml *idx = aml_arg(0);
> > + Aml *sta = aml_local(0);
> > +
> > + aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
> > + aml_append(method, aml_store(idx, cpu_selector));
> > + aml_append(method, aml_store(zero, sta));
> > + ifctx = aml_if(aml_equal(is_enabled, one));
> > + {
> > + aml_append(ifctx, aml_store(aml_int(0xF), sta));
> > + }
> > + aml_append(method, ifctx);
> > + aml_append(method, aml_release(ctrl_lock));
> > + aml_append(method, aml_return(sta));
> > + }
> > + aml_append(cpus_dev, method);
> > +
> > + method = aml_method(CPU_EJECT_METHOD, 1, AML_SERIALIZED);
> > + {
> > + Aml *idx = aml_arg(0);
> > +
> > + aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
> > + aml_append(method, aml_store(idx, cpu_selector));
> > + aml_append(method, aml_store(one, ej_evt));
> > + aml_append(method, aml_release(ctrl_lock));
> > + }
> > + aml_append(cpus_dev, method);
> > +
> > + method = aml_method(CPU_SCAN_METHOD, 0, AML_SERIALIZED);
> > + {
> > + Aml *else_ctx;
> > + Aml *while_ctx;
> > + Aml *idx = aml_local(0);
> > + Aml *eject_req = aml_int(3);
> > + Aml *dev_chk = aml_int(1);
> > + Aml *cpus_count = aml_int(arch_ids->len);
> > +
> > + aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
> > + aml_append(method, aml_store(zero, idx));
> > + while_ctx = aml_while(aml_lless(idx, cpus_count));
> > + {
> > + aml_append(while_ctx, aml_store(idx, cpu_selector));
> > + ifctx = aml_if(aml_equal(ins_evt, one));
> > + {
> > + aml_append(ifctx,
> > + aml_call2(CPU_NOTIFY_METHOD, idx, dev_chk));
> > + aml_append(ifctx, aml_store(one, ins_evt));
> > + }
> > + aml_append(while_ctx, ifctx);
> > + else_ctx = aml_else();
> > + ifctx = aml_if(aml_equal(rm_evt, one));
> > + {
> > + aml_append(ifctx,
> > + aml_call2(CPU_NOTIFY_METHOD, idx, eject_req));
> > + aml_append(ifctx, aml_store(one, rm_evt));
> > + }
> > + aml_append(else_ctx, ifctx);
> > + aml_append(while_ctx, else_ctx);
> > +
> > + aml_append(while_ctx, aml_add(idx, one, idx));
> > + }
> > + aml_append(method, while_ctx);
> > + aml_append(method, aml_release(ctrl_lock));
> > + }
> > + aml_append(cpus_dev, method);
> > +
> > /* build Processor object for each processor */
> > for (i = 0; i < arch_ids->len; i++) {
> > Aml *dev;
> > Aml *uid = aml_int(i);
> > + GArray *madt_buf = g_array_new(0, 1, 1);
> > int arch_id = arch_ids->cpus[i].arch_id;
> >
> > if (acpi1_compat && arch_id < 255) {
> > @@ -235,11 +389,40 @@ void build_cpus_aml(Aml *table, MachineState
> > *machine, bool acpi1_compat)
> > aml_append(dev, aml_name_decl("_UID", uid));
> > }
> >
> > + method = aml_method("_STA", 0, AML_SERIALIZED);
> > + aml_append(method, aml_return(aml_call1(CPU_STS_METHOD, uid)));
> > + aml_append(dev, method);
> > +
> > + /* build _MAT object */
> > + assert(adevc && adevc->madt_cpu);
> > + adevc->madt_cpu(adev, i, arch_ids, madt_buf);
> > + switch (madt_buf->data[0]) {
> > + case ACPI_APIC_PROCESSOR: {
> > + AcpiMadtProcessorApic *apic = (void *)madt_buf->data;
> > + apic->flags = cpu_to_le32(1);
> > + break;
> > + }
> > + default:
> > + assert(0);
> > + }
> > + aml_append(dev, aml_name_decl("_MAT",
> > + aml_buffer(madt_buf->len, (uint8_t *)madt_buf->data)));
> > + g_array_free(madt_buf, true);
> > +
> > + method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
> > + aml_append(method, aml_call1(CPU_EJECT_METHOD, uid));
> > + aml_append(dev, method);
> > +
> > aml_append(cpus_dev, dev);
> > }
> > }
> > aml_append(sb_scope, cpus_dev);
> > aml_append(table, sb_scope);
> >
> > + method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
> > + aml_append(method, aml_call0("\\_SB.CPUS." CPU_SCAN_METHOD));
> > + aml_append(table, method);
> > +
> > + g_free(cphp_res_path);
> > g_free(arch_ids);
> > }
> > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > index 47d4182..c62c020 100644
> > --- a/hw/i386/acpi-build.c
> > +++ b/hw/i386/acpi-build.c
> > @@ -1949,7 +1949,8 @@ build_dsdt(GArray *table_data, GArray *linker,
> > if (pm->legacy_cpu_hp) {
> > build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base);
> > } else {
> > - build_cpus_aml(dsdt, machine, true);
> > + build_cpus_aml(dsdt, machine, true,
> > + "\\_SB.PCI0", "\\_GPE._E02", pm->cpu_hp_io_base);
> > }
> > build_memory_hotplug_aml(dsdt, nr_mem, pm->mem_hp_io_base,
> > pm->mem_hp_io_len);
> > diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
> > index ca32e07..0346f24 100644
> > --- a/include/hw/acpi/cpu.h
> > +++ b/include/hw/acpi/cpu.h
> > @@ -45,7 +45,9 @@ void acpi_cpu_unplug_cb(CPUHotplugState *cpu_st,
> > void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
> > CPUHotplugState *state, hwaddr base_addr);
> >
> > -void build_cpus_aml(Aml *table, MachineState *machine, bool apci1_compat);
> > +void build_cpus_aml(Aml *table, MachineState *machine, bool apci1_compat,
> > + const char *res_root, const char *event_handler_method,
> > + hwaddr io_base);
> >
> > extern const VMStateDescription vmstate_cpu_hotplug;
> > #define VMSTATE_CPU_HOTPLUG(cpuhp, state) \
> > --
> > 1.8.3.1
- Re: [Qemu-devel] [PATCH 15/33] docs: update ACPI CPU hotplug spec with new protocol, (continued)
- [Qemu-devel] [PATCH 17/33] pc: add generic CPU unplug callbacks, Igor Mammedov, 2016/05/17
- [Qemu-devel] [PATCH 14/33] pc: use AcpiDeviceIfClass.send_event to issue GPE events, Igor Mammedov, 2016/05/17
- [Qemu-devel] [PATCH 18/33] pc: add 2.7 machine, Igor Mammedov, 2016/05/17
- [Qemu-devel] [PATCH 21/33] pc: piix4: initialize new CPU hotplug hw, Igor Mammedov, 2016/05/17
- [Qemu-devel] [PATCH 24/33] acpi: add CPU hotplug methods to DSDT, Igor Mammedov, 2016/05/17
- [Qemu-devel] [PATCH 22/33] pc: acpi: introduce AcpiDeviceIfClass.madt_cpu hook, Igor Mammedov, 2016/05/17
- [Qemu-devel] [PATCH 25/33] qdev: hotplug: Introduce HotplugHandler.pre_plug() callback, Igor Mammedov, 2016/05/17
- [Qemu-devel] [PATCH 20/33] pc: q35: initialize new CPU hotplug hw, Igor Mammedov, 2016/05/17
- Re: [Qemu-devel] [PATCH 20/33] pc: q35: initialize new CPU hotplug hw, Marcel Apfelbaum, 2016/05/30
- Re: [Qemu-devel] [PATCH 20/33] pc: q35: initialize new CPU hotplug hw, Igor Mammedov, 2016/05/31
- Re: [Qemu-devel] [PATCH 20/33] pc: q35: initialize new CPU hotplug hw, Marcel Apfelbaum, 2016/05/31
- Re: [Qemu-devel] [PATCH 20/33] pc: q35: initialize new CPU hotplug hw, Igor Mammedov, 2016/05/31
- Re: [Qemu-devel] [PATCH 20/33] pc: q35: initialize new CPU hotplug hw, Michael S. Tsirkin, 2016/05/31
- Re: [Qemu-devel] [PATCH 20/33] pc: q35: initialize new CPU hotplug hw, Igor Mammedov, 2016/05/31
[Qemu-devel] [PATCH 31/33] tests: acpi: update expected tables with new cpu-hotplug methods enabled by default, Igor Mammedov, 2016/05/17