From: David Gibson <david@gibson.dropbear.id.au>
To: Bharata B Rao <bharata@linux.vnet.ibm.com>
Cc: qemu-devel@nongnu.org, qemu-ppc@nongnu.org, afaerber@suse.de,
imammedo@redhat.com, armbru@redhat.com, thuth@redhat.com,
aik@ozlabs.ru, agraf@suse.de, pbonzini@redhat.com,
ehabkost@redhat.com, pkrempa@redhat.com,
mdroth@linux.vnet.ibm.com, eblake@redhat.com,
mjrosato@linux.vnet.ibm.com, borntraeger@de.ibm.com
Subject: Re: [Qemu-devel] [for-2.7 PATCH v3 09/15] spapr: CPU hotplug support
Date: Fri, 3 Jun 2016 16:10:59 +1000 [thread overview]
Message-ID: <20160603061059.GM1087@voom.fritz.box> (raw)
In-Reply-To: <1463024905-28401-10-git-send-email-bharata@linux.vnet.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 13583 bytes --]
On Thu, May 12, 2016 at 09:18:19AM +0530, Bharata B Rao wrote:
> Set up device tree entries for the hotplugged CPU core and use the
> exising RTAS event logging infrastructure to send CPU hotplug notification
> to the guest.
>
> Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
> ---
> hw/ppc/spapr.c | 91 ++++++++++++++++++++++++++++++++++-------
> hw/ppc/spapr_cpu_core.c | 69 +++++++++++++++++++++++++++++++
> hw/ppc/spapr_events.c | 3 ++
> hw/ppc/spapr_rtas.c | 24 +++++++++++
> include/hw/ppc/spapr.h | 2 +
> include/hw/ppc/spapr_cpu_core.h | 2 +
> 6 files changed, 176 insertions(+), 15 deletions(-)
>
> diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
> index 0f64218..8c3100d 100644
> --- a/hw/ppc/spapr.c
> +++ b/hw/ppc/spapr.c
> @@ -605,6 +605,16 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset,
> size_t page_sizes_prop_size;
> uint32_t vcpus_per_socket = smp_threads * smp_cores;
> uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)};
> + sPAPRDRConnector *drc;
> + sPAPRDRConnectorClass *drck;
> + int drc_index;
> +
> + drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index);
> + if (drc) {
> + drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
> + drc_index = drck->get_index(drc);
> + _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index)));
> + }
>
> /* Note: we keep CI large pages off for now because a 64K capable guest
> * provisioned with large pages might otherwise try to map a qemu
> @@ -988,6 +998,16 @@ static void spapr_finalize_fdt(sPAPRMachineState *spapr,
> _FDT(spapr_drc_populate_dt(fdt, 0, NULL, SPAPR_DR_CONNECTOR_TYPE_LMB));
> }
>
> + if (smc->dr_cpu_enabled) {
> + int offset = fdt_path_offset(fdt, "/cpus");
> + ret = spapr_drc_populate_dt(fdt, offset, NULL,
> + SPAPR_DR_CONNECTOR_TYPE_CPU);
> + if (ret < 0) {
> + error_report("Couldn't set up CPU DR device tree properties");
> + exit(1);
> + }
> + }
> +
> _FDT((fdt_pack(fdt)));
>
> if (fdt_totalsize(fdt) > FDT_MAX_SIZE) {
> @@ -1613,6 +1633,8 @@ static void spapr_boot_set(void *opaque, const char *boot_device,
> void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, Error **errp)
> {
> CPUPPCState *env = &cpu->env;
> + CPUState *cs = CPU(cpu);
> + int i;
>
> /* Set time-base frequency to 512 MHz */
> cpu_ppc_tb_init(env, TIMEBASE_FREQ);
> @@ -1630,6 +1652,14 @@ void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, Error **errp)
> }
> }
>
> + /* Set NUMA node for the added CPUs */
> + for (i = 0; i < nb_numa_nodes; i++) {
> + if (test_bit(cs->cpu_index, numa_info[i].node_cpu)) {
> + cs->numa_node = i;
> + break;
> + }
> + }
> +
> xics_cpu_setup(spapr->icp, cpu);
>
> qemu_register_reset(spapr_cpu_reset, cpu);
> @@ -1807,23 +1837,31 @@ static void ppc_spapr_init(MachineState *machine)
> if (smc->dr_cpu_enabled) {
> spapr->cores = g_new0(Object *, spapr_max_cores);
>
> - for (i = 0; i < spapr_cores; i++) {
> + for (i = 0; i < spapr_max_cores; i++) {
> int core_dt_id = i * smt;
> - char *type = spapr_get_cpu_core_type(machine->cpu_model);
> - Object *core;
> -
> - if (!object_class_by_name(type)) {
> - error_report("Unable to find sPAPR CPU Core definition");
> - exit(1);
> + sPAPRDRConnector *drc =
> + spapr_dr_connector_new(OBJECT(spapr),
> + SPAPR_DR_CONNECTOR_TYPE_CPU, core_dt_id);
> +
> + qemu_register_reset(spapr_drc_reset, drc);
> +
> + if (i < spapr_cores) {
> + char *type = spapr_get_cpu_core_type(machine->cpu_model);
> + Object *core;
> +
> + if (!object_class_by_name(type)) {
> + error_report("Unable to find sPAPR CPU Core definition");
> + exit(1);
> + }
> +
> + core = object_new(type);
> + g_free(type);
> + object_property_set_int(core, smp_threads, "threads",
> + &error_fatal);
> + object_property_set_int(core, core_dt_id, CPU_CORE_PROP_CORE,
> + &error_fatal);
> + object_property_set_bool(core, true, "realized", &error_fatal);
> }
> -
> - core = object_new(type);
> - g_free(type);
> - object_property_set_int(core, smp_threads, "threads",
> - &error_fatal);
> - object_property_set_int(core, core_dt_id, CPU_CORE_PROP_CORE,
> - &error_fatal);
> - object_property_set_bool(core, true, "realized", &error_fatal);
> }
> } else {
> for (i = 0; i < smp_cpus; i++) {
> @@ -2234,6 +2272,27 @@ out:
> error_propagate(errp, local_err);
> }
>
> +void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset,
> + sPAPRMachineState *spapr)
> +{
> + PowerPCCPU *cpu = POWERPC_CPU(cs);
> + DeviceClass *dc = DEVICE_GET_CLASS(cs);
> + int id = ppc_get_vcpu_dt_id(cpu);
> + void *fdt;
> + int offset, fdt_size;
> + char *nodename;
> +
> + fdt = create_device_tree(&fdt_size);
> + nodename = g_strdup_printf("%s@%x", dc->fw_name, id);
> + offset = fdt_add_subnode(fdt, 0, nodename);
> +
> + spapr_populate_cpu_dt(cs, fdt, offset, spapr);
> + g_free(nodename);
> +
> + *fdt_offset = offset;
> + return fdt;
> +}
> +
> static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
> DeviceState *dev, Error **errp)
> {
> @@ -2278,6 +2337,8 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev,
> }
>
> spapr_memory_plug(hotplug_dev, dev, node, errp);
> + } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
> + spapr_core_plug(hotplug_dev, dev, errp);
> }
> }
>
> diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
> index 4450362..ed36beb 100644
> --- a/hw/ppc/spapr_cpu_core.c
> +++ b/hw/ppc/spapr_cpu_core.c
> @@ -28,10 +28,74 @@ char *spapr_get_cpu_core_type(const char *model)
> return g_strdup(core_type);
> }
>
> +void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
> + Error **errp)
> +{
> + sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(OBJECT(hotplug_dev));
> + sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
> + sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev));
> + CPUCore *cc = CPU_CORE(dev);
> + CPUState *cs = CPU(&core->threads[0]);
> + sPAPRDRConnector *drc;
> + sPAPRDRConnectorClass *drck;
> + Error *local_err = NULL;
> + void *fdt = NULL;
> + int fdt_offset = 0;
> + int index;
> + int smt = kvmppc_smt_threads();
> +
> + drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, cc->core);
> + index = cc->core / smt;
> + spapr->cores[index] = OBJECT(dev);
> +
> + if (!smc->dr_cpu_enabled) {
> + /*
> + * This is a cold plugged CPU core but the machine doesn't support
> + * DR. So skip the hotplug path ensuring that the core is brought
> + * up online with out an associated DR connector.
> + */
> + return;
> + }
> +
> + g_assert(drc);
> +
> + /*
> + * Setup CPU DT entries only for hotplugged CPUs. For boot time or
> + * coldplugged CPUs DT entries are setup in spapr_finalize_fdt().
> + */
> + if (dev->hotplugged) {
> + fdt = spapr_populate_hotplug_cpu_dt(cs, &fdt_offset, spapr);
> + }
> +
> + drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
> + drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, &local_err);
> + if (local_err) {
> + g_free(fdt);
> + spapr->cores[index] = NULL;
> + error_propagate(errp, local_err);
> + return;
> + }
> +
> + if (dev->hotplugged) {
> + /*
> + * Send hotplug notification interrupt to the guest only in case
> + * of hotplugged CPUs.
> + */
> + spapr_hotplug_req_add_by_index(drc);
> + } else {
> + /*
> + * Set the right DRC states for cold plugged CPU.
> + */
> + drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_USABLE);
> + drck->set_isolation_state(drc, SPAPR_DR_ISOLATION_STATE_UNISOLATED);
> + }
> +}
> +
> void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
> Error **errp)
> {
> MachineState *machine = MACHINE(OBJECT(hotplug_dev));
> + sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(OBJECT(hotplug_dev));
> sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
> int spapr_max_cores = max_cpus / smp_threads;
> int index;
> @@ -46,6 +110,11 @@ void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
> goto out;
> }
>
> + if (!smc->dr_cpu_enabled && dev->hotplugged) {
> + error_setg(&local_err, "CPU hotplug not supported for this machine");
> + goto out;
> + }
> +
> if (cc->threads != smp_threads) {
> error_setg(&local_err, "threads must be %d", smp_threads);
> goto out;
> diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
> index 049fb1b..af80992 100644
> --- a/hw/ppc/spapr_events.c
> +++ b/hw/ppc/spapr_events.c
> @@ -449,6 +449,9 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
> case SPAPR_DR_CONNECTOR_TYPE_LMB:
> hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_MEMORY;
> break;
> + case SPAPR_DR_CONNECTOR_TYPE_CPU:
> + hp->hotplug_type = RTAS_LOG_V6_HP_TYPE_CPU;
> + break;
> default:
> /* we shouldn't be signaling hotplug events for resources
> * that don't support them
> diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> index f073258..e53ecc0 100644
> --- a/hw/ppc/spapr_rtas.c
> +++ b/hw/ppc/spapr_rtas.c
> @@ -34,6 +34,7 @@
>
> #include "hw/ppc/spapr.h"
> #include "hw/ppc/spapr_vio.h"
> +#include "hw/ppc/ppc.h"
> #include "qapi-event.h"
> #include "hw/boards.h"
>
> @@ -162,6 +163,27 @@ static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
> rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> }
>
> +/*
> + * Set the timebase offset of the CPU to that of first CPU.
> + * This helps hotplugged CPU to have the correct timebase offset.
> + */
> +static void spapr_cpu_update_tb_offset(PowerPCCPU *cpu)
> +{
> + PowerPCCPU *fcpu = POWERPC_CPU(first_cpu);
> +
> + cpu->env.tb_env->tb_offset = fcpu->env.tb_env->tb_offset;
> +}
> +
> +static void spapr_cpu_set_endianness(PowerPCCPU *cpu)
> +{
> + PowerPCCPU *fcpu = POWERPC_CPU(first_cpu);
> + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(fcpu);
> +
> + if (!pcc->interrupts_big_endian(fcpu)) {
> + cpu->env.spr[SPR_LPCR] |= LPCR_ILE;
> + }
> +}
> +
> static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPRMachineState *spapr,
> uint32_t token, uint32_t nargs,
> target_ulong args,
> @@ -198,6 +220,8 @@ static void rtas_start_cpu(PowerPCCPU *cpu_, sPAPRMachineState *spapr,
> env->nip = start;
> env->gpr[3] = r3;
> cs->halted = 0;
> + spapr_cpu_set_endianness(cpu);
> + spapr_cpu_update_tb_offset(cpu);
>
> qemu_cpu_kick(cs);
>
> diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
> index 1b3eeee..ca4ae3e 100644
> --- a/include/hw/ppc/spapr.h
> +++ b/include/hw/ppc/spapr.h
> @@ -583,6 +583,8 @@ void spapr_hotplug_req_add_by_count(sPAPRDRConnectorType drc_type,
> void spapr_hotplug_req_remove_by_count(sPAPRDRConnectorType drc_type,
> uint32_t count);
> void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu, Error **errp);
> +void *spapr_populate_hotplug_cpu_dt(CPUState *cs, int *fdt_offset,
> + sPAPRMachineState *spapr);
>
> /* rtas-configure-connector state */
> struct sPAPRConfigureConnectorState {
> diff --git a/include/hw/ppc/spapr_cpu_core.h b/include/hw/ppc/spapr_cpu_core.h
> index f1ebd85..4cd837e 100644
> --- a/include/hw/ppc/spapr_cpu_core.h
> +++ b/include/hw/ppc/spapr_cpu_core.h
> @@ -28,4 +28,6 @@ typedef struct sPAPRCPUCore {
> void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
> Error **errp);
> char *spapr_get_cpu_core_type(const char *model);
> +void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
> + Error **errp);
> #endif
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
next prev parent reply other threads:[~2016-06-03 6:52 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-12 3:48 [Qemu-devel] [for-2.7 PATCH v3 00/15] Core based CPU hotplug for PowerPC sPAPR Bharata B Rao
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 01/15] exec: Remove cpu from cpus list during cpu_exec_exit() Bharata B Rao
2016-05-26 10:12 ` Paolo Bonzini
2016-05-27 3:07 ` David Gibson
2016-05-27 9:51 ` Paolo Bonzini
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 02/15] exec: Do vmstate unregistration from cpu_exec_exit() Bharata B Rao
2016-05-26 10:22 ` Paolo Bonzini
2016-05-30 15:22 ` [Qemu-devel] [PATCH] fixup! " Igor Mammedov
2016-05-31 0:02 ` David Gibson
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 03/15] cpu: Reclaim vCPU objects Bharata B Rao
2016-05-26 10:19 ` Paolo Bonzini
2016-05-26 10:47 ` Bharata B Rao
[not found] ` <201605261048.u4QAibq4039252@mx0a-001b2d01.pphosted.com>
2016-05-26 10:51 ` Paolo Bonzini
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 04/15] cpu: Add a sync version of cpu_remove() Bharata B Rao
2016-05-26 10:22 ` Paolo Bonzini
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 05/15] qdev: hotplug: Introduce HotplugHandler.pre_plug() callback Bharata B Rao
2016-06-02 1:15 ` David Gibson
2016-06-02 9:32 ` Igor Mammedov
2016-06-03 5:10 ` David Gibson
2016-06-03 9:23 ` Igor Mammedov
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 06/15] cpu: Abstract CPU core type Bharata B Rao
2016-06-02 3:38 ` David Gibson
2016-06-02 9:35 ` Igor Mammedov
2016-06-02 18:12 ` Eduardo Habkost
2016-06-03 5:06 ` David Gibson
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 07/15] spapr: Abstract CPU core device and type specific core devices Bharata B Rao
2016-06-03 5:25 ` David Gibson
2016-06-08 9:42 ` Bharata B Rao
2016-06-09 0:45 ` David Gibson
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 08/15] spapr: convert boot CPUs into CPU " Bharata B Rao
2016-06-03 5:32 ` David Gibson
2016-06-08 12:23 ` Bharata B Rao
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 09/15] spapr: CPU hotplug support Bharata B Rao
2016-06-03 6:10 ` David Gibson [this message]
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 10/15] xics, xics_kvm: Handle CPU unplug correctly Bharata B Rao
2016-06-03 6:14 ` David Gibson
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 11/15] spapr_drc: Prevent detach racing against attach for CPU DR Bharata B Rao
2016-06-03 6:17 ` David Gibson
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 12/15] spapr: CPU hot unplug support Bharata B Rao
2016-06-03 6:27 ` David Gibson
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 13/15] QMP: Add query-hotpluggable-cpus Bharata B Rao
2016-06-06 5:28 ` David Gibson
2016-06-06 8:42 ` Igor Mammedov
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 14/15] hmp: Add 'info hotpluggable-cpus' HMP command Bharata B Rao
2016-06-06 5:29 ` David Gibson
2016-05-12 3:48 ` [Qemu-devel] [for-2.7 PATCH v3 15/15] spapr: implement query-hotpluggable-cpus callback Bharata B Rao
2016-06-06 5:37 ` David Gibson
2016-05-25 6:54 ` [Qemu-devel] [for-2.7 PATCH v3 00/15] Core based CPU hotplug for PowerPC sPAPR Thomas Huth
2016-05-25 16:03 ` Andreas Färber
2016-05-26 6:20 ` David Gibson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160603061059.GM1087@voom.fritz.box \
--to=david@gibson.dropbear.id.au \
--cc=afaerber@suse.de \
--cc=agraf@suse.de \
--cc=aik@ozlabs.ru \
--cc=armbru@redhat.com \
--cc=bharata@linux.vnet.ibm.com \
--cc=borntraeger@de.ibm.com \
--cc=eblake@redhat.com \
--cc=ehabkost@redhat.com \
--cc=imammedo@redhat.com \
--cc=mdroth@linux.vnet.ibm.com \
--cc=mjrosato@linux.vnet.ibm.com \
--cc=pbonzini@redhat.com \
--cc=pkrempa@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.