On Wed, Jan 13, 2016 at 10:58:06AM +1100, Alexey Kardashevskiy wrote: > On 01/08/2016 05:55 PM, Bharata B Rao wrote: > >Support CPU hotplug via device-add command like this: > > > >(qemu) device_add powerpc64-cpu-core,id=core2 > > > >In response to device_add, CPU core device will be created. CPU core > >device creates and realizes CPU thread devices. If the machine type > >supports CPU hotplug, boot-time CPUs are created as CPU core devices > >otherwise they continue to be created as individual CPU devices. > > > >Set up device tree entries for the hotplugged CPU core and use the > >exising EPOW event infrastructure to send CPU hotplug notification to > >the guest. > > > >Signed-off-by: Bharata B Rao <bhar...@linux.vnet.ibm.com> > >--- > > hw/ppc/spapr.c | 183 > > ++++++++++++++++++++++++++++++++++++++++++-- > > hw/ppc/spapr_events.c | 3 + > > hw/ppc/spapr_rtas.c | 24 ++++++ > > include/hw/ppc/spapr.h | 5 ++ > > target-ppc/translate_init.c | 8 ++ > > 5 files changed, 216 insertions(+), 7 deletions(-) > > > >diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c > >index a3ce1db..c2af9ca 100644 > >--- a/hw/ppc/spapr.c > >+++ b/hw/ppc/spapr.c > >@@ -63,6 +63,7 @@ > > > > #include "hw/compat.h" > > #include "qemu-common.h" > >+#include "hw/ppc/cpu-core.h" > > > > #include <libfdt.h> > > > >@@ -600,6 +601,18 @@ 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)}; > >+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); > >+ sPAPRDRConnector *drc; > >+ sPAPRDRConnectorClass *drck; > >+ int drc_index; > >+ > >+ if (smc->dr_cpu_enabled) { > >+ drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index); > >+ g_assert(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 > >@@ -1743,6 +1756,8 @@ static void ppc_spapr_init(MachineState *machine) > > char *filename; > > int smt = kvmppc_smt_threads(); > > int smp_max_cores = max_cpus/smp_threads; > >+ int spapr_smp_cores = smp_cpus/smp_threads; > >+ Object *core; > > > > msi_supported = true; > > > >@@ -1822,13 +1837,22 @@ static void ppc_spapr_init(MachineState *machine) > > if (machine->cpu_model == NULL) { > > machine->cpu_model = kvm_enabled() ? "host" : "POWER7"; > > } > >- for (i = 0; i < smp_cpus; i++) { > >- cpu = cpu_ppc_init(machine->cpu_model); > >- if (cpu == NULL) { > >- fprintf(stderr, "Unable to find PowerPC CPU definition\n"); > >- exit(1); > >+ > >+ if (smc->dr_cpu_enabled) { > >+ for (i = 0; i < spapr_smp_cores; i++) { > >+ core = object_new(TYPE_POWERPC_CPU_CORE); > >+ object_property_set_bool(core, true, "realized", &error_abort); > >+ } > >+ } else { > >+ for (i = 0; i < smp_cpus; i++) { > >+ cpu = cpu_ppc_init(machine->cpu_model); > >+ if (cpu == NULL) { > >+ fprintf(stderr, "Unable to find PowerPC CPU definition\n"); > >+ exit(1); > >+ } > >+ object_property_set_bool(OBJECT(cpu), true, "realized", > >+ &error_abort); > > } > >- spapr_cpu_init(spapr, cpu); > > } > > > > if (kvm_enabled()) { > >@@ -2222,10 +2246,125 @@ out: > > error_propagate(errp, local_err); > > } > > > >+static void *spapr_populate_hotplug_cpu_dt(DeviceState *dev, 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 int spapr_core_attach(Object *obj, void *opaque) > >+{ > >+ sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(qdev_get_machine()); > >+ sPAPRMachineState *ms = SPAPR_MACHINE(qdev_get_machine()); > >+ sPAPRCoreState *core = opaque; > >+ DeviceState *dev = DEVICE(obj); > >+ CPUState *cs = CPU(dev); > >+ PowerPCCPU *cpu = POWERPC_CPU(cs); > >+ int id = ppc_get_vcpu_dt_id(cpu); > >+ sPAPRDRConnector *drc = > >+ spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, id); > >+ sPAPRDRConnectorClass *drck; > >+ int smt = kvmppc_smt_threads(); > >+ Error *local_err = NULL; > >+ void *fdt = NULL; > >+ int fdt_offset = 0; > >+ > >+ /* > >+ * Only main SMT thread (thread 0) will continue and signal the > >+ * hotplug event to the guest. Other threads of the core will > >+ * return from here. > >+ */ > >+ if ((id % smt) != 0) { > >+ return 0; > >+ } > >+ > >+ if (!smc->dr_cpu_enabled) { > >+ /* > >+ * This is a cold plugged CPU but the machine doesn't support > >+ * DR. So skip the hotplug path ensuring that the CPU is brought > >+ * up online with out an associated DR connector. > >+ */ > >+ return 0; > >+ } > >+ > >+ 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(dev, cs, &fdt_offset, ms); > >+ } > > > spapr_core_attach() is only called from spapr_core_plug() which is only > called from spapr_machine_device_plug() which is a hotplug handler so the > check for dev->hotplugged seems redundant here and below, no? Or this is > called at the boot time for cold-plug devices?
->plug() handler will be called for cold plugged CPUs too. For those CPUs specified using -smp option and for those specified using -device option, ->plug() handler will be called because I am initializing these boot time CPUs as CPU core devices. Regards, Bharata.