From patchwork Mon May 2 12:33:37 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Igor Mammedov X-Patchwork-Id: 8992141 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B3A249F1D3 for ; Mon, 2 May 2016 12:48:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BE087201FE for ; Mon, 2 May 2016 12:48:18 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8A478201FA for ; Mon, 2 May 2016 12:48:17 +0000 (UTC) Received: from localhost ([::1]:36462 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1axDGn-00039l-O1 for patchwork-qemu-devel@patchwork.kernel.org; Mon, 02 May 2016 08:48:13 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35689) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1axD46-000734-1X for qemu-devel@nongnu.org; Mon, 02 May 2016 08:35:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1axD3t-00007X-PU for qemu-devel@nongnu.org; Mon, 02 May 2016 08:35:00 -0400 Received: from mx1.redhat.com ([209.132.183.28]:33931) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1axD3t-0008VG-Ir for qemu-devel@nongnu.org; Mon, 02 May 2016 08:34:53 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7AF34C04B31B for ; Mon, 2 May 2016 12:34:42 +0000 (UTC) Received: from dell-r430-03.lab.eng.brq.redhat.com (dell-r430-03.lab.eng.brq.redhat.com [10.34.112.60]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u42CXqcF000450; Mon, 2 May 2016 08:34:41 -0400 From: Igor Mammedov To: qemu-devel@nongnu.org Date: Mon, 2 May 2016 14:33:37 +0200 Message-Id: <1462192431-146342-29-git-send-email-imammedo@redhat.com> In-Reply-To: <1462192431-146342-1-git-send-email-imammedo@redhat.com> References: <1462192431-146342-1-git-send-email-imammedo@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [RFC 28/42] acpi: add CPU hotplug methods to DSDT X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: drjones@redhat.com, ehabkost@redhat.com, mst@redhat.com, armbru@redhat.com, marcel@redhat.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add necessary CPU hotplug methods to handle hotplug events if it's enabled. Signed-off-by: Igor Mammedov --- hw/acpi/cpu.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++- hw/i386/acpi-build.c | 3 +- include/hw/acpi/cpu.h | 4 +- 3 files changed, 204 insertions(+), 4 deletions(-) diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c index 6dab4d6..f61d5a8 100644 --- a/hw/acpi/cpu.c +++ b/hw/acpi/cpu.c @@ -218,20 +218,177 @@ 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); + + if (machine->cpu_hotplug) { + 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"))); + if (machine->cpu_hotplug) { + method = aml_method(CPU_NOTIFY_METHOD, 2, AML_NOTSERIALIZED); + for (i = 0; i < arch_ids->len; i++) { + 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; @@ -246,11 +403,51 @@ void build_cpus_aml(Aml *table, MachineState *machine, bool acpi1_compat) aml_append(dev, aml_name_decl("_UID", uid)); } + if (machine->cpu_hotplug) { + method = aml_method("_STA", 0, AML_SERIALIZED); + aml_append(method, aml_return(aml_call1(CPU_STS_METHOD, uid))); + aml_append(dev, method); + + method = aml_method("_MAT", 0, AML_SERIALIZED); + { + Aml *madt = aml_local(1); + GArray *buf = g_array_new(0, 1, 1); + + adevc->madt_cpu(adev, i, arch_ids, buf); + switch (buf->data[0]) { + case ACPI_APIC_PROCESSOR: { + AcpiMadtProcessorApic *apic = (void *)buf->data; + apic->flags = cpu_to_le32(1); + break; + } + default: + assert(0); + } + aml_append(method, + aml_store(aml_buffer(buf->len, (uint8_t *)buf->data), + madt)); + aml_append(method, aml_return(madt)); + g_array_free(buf, true); + } + + aml_append(dev, method); + + 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); + if (machine->cpu_hotplug) { + 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 466eebd..b27502a 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 da087bf..829114f 100644 --- a/include/hw/acpi/cpu.h +++ b/include/hw/acpi/cpu.h @@ -46,7 +46,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) \