qemu-devel
[Top][All Lists]
Advanced

[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  




reply via email to

[Prev in Thread] Current Thread [Next in Thread]