On Fri, 7 Jun 2013 13:28:06 -0400 "Jason J. Herne" <jjhe...@us.ibm.com> wrote:
> From: "Jason J. Herne" <jjhe...@us.ibm.com> > > Add infrastructure for treating cpus as devices. This patch allows cpus to be > specified using a combination of '-smp' and '-device cpu'. This approach > forces a change in the way cpus are counted via smp_cpus. > > Signed-off-by: Jason J. Herne <jjhe...@us.ibm.com> > --- > include/hw/boards.h | 3 ++ > vl.c | 95 > +++++++++++++++++++++++++++++++++++++++++++-------- > 2 files changed, 84 insertions(+), 14 deletions(-) > > diff --git a/include/hw/boards.h b/include/hw/boards.h > index ed427a1..b0c86bf 100644 > --- a/include/hw/boards.h > +++ b/include/hw/boards.h > @@ -47,8 +47,11 @@ typedef struct QEMUMachine { > GlobalProperty *compat_props; > struct QEMUMachine *next; > const char *hw_version; > + const char *cpu_device_str; > } QEMUMachine; > > +#define CPUS_ARE_DEVICES(qemu_mach) (qemu_mach->cpu_device_str != NULL) > + > int qemu_register_machine(QEMUMachine *m); > QEMUMachine *find_default_machine(void); > > diff --git a/vl.c b/vl.c > index 71e1e6d..873834f 100644 > --- a/vl.c > +++ b/vl.c > @@ -546,6 +546,46 @@ static int default_driver_check(QemuOpts *opts, void > *opaque) > return 0; > } > > +static void convert_smp_to_cpu_devices(QEMUMachine *machine) > +{ > + int i; > + QemuOpts *opts; > + > + for (i = 0; i < smp_cpus; i++) { > + opts = qemu_opts_create_nofail(qemu_find_opts("device")); > + qemu_opt_set(opts, "driver", machine->cpu_device_str); ^^ could be default_cpu and probably stored in .default_machine_opts? > + } > + smp_cpus = 0; > +} > + > +static int count_cpu_devices(QemuOpts *opts, void *opaque) > +{ > + const char *driver = qemu_opt_get(opts, "driver"); > + QEMUMachine *machine = (QEMUMachine *)opaque; > + > + /* Skip non-cpu devices*/ > + if (!driver || strcmp(driver, machine->cpu_device_str) != 0) { find type by driver name and dynamic cast it to common CPU, if cast is successful it's CPU device > + return 0; > + } > + > + smp_cpus += 1; > + return 0; > +} -smp smp_cpus could be treated as a number of startup cpus including CPUs specified by -device if number of "-device CPU" more than smp_cpus QEMU could just print error and die at init stage asking user to correct command line. > +static int handle_cpu_device(QemuOpts *opts, void *opaque) > +{ > + const char *driver = qemu_opt_get(opts, "driver"); > + QEMUMachine *machine = (QEMUMachine *)opaque; > + > + /* Skip non-cpu devices*/ > + if (!driver || strcmp(driver, machine->cpu_device_str) != 0) { > + return 0; > + } > + > + qdev_device_add(opts); > + return 0; > +} > + > /***********************************************************/ > /* QEMU state */ > > @@ -2318,6 +2358,13 @@ static int device_help_func(QemuOpts *opts, void > *opaque) > static int device_init_func(QemuOpts *opts, void *opaque) > { > DeviceState *dev; > + const char *driver = qemu_opt_get(opts, "driver"); > + QEMUMachine *machine = (QEMUMachine *)opaque; > + > + /* Skip cpu devices*/ > + if (!driver || strcmp(driver, machine->cpu_device_str) == 0) { > + return 0; > + } > > dev = qdev_device_add(opts); > if (!dev) > @@ -3630,19 +3677,6 @@ int main(int argc, char **argv, char **envp) > break; > case QEMU_OPTION_smp: > smp_parse(optarg); > - if (smp_cpus < 1) { > - fprintf(stderr, "Invalid number of CPUs\n"); > - exit(1); > - } > - if (max_cpus < smp_cpus) { > - fprintf(stderr, "maxcpus must be equal to or greater > than " > - "smp\n"); > - exit(1); > - } > - if (max_cpus > 255) { > - fprintf(stderr, "Unsupported number of maxcpus\n"); > - exit(1); > - } > break; > case QEMU_OPTION_vnc: > #ifdef CONFIG_VNC > @@ -3965,6 +3999,16 @@ int main(int argc, char **argv, char **envp) > } > > /* > + * Count cpu devices. Cpu count is determied by adding -device cpu > + * statements to the number of cpus specified on the -smp statement. > + */ > + if (CPUS_ARE_DEVICES(machine)) { > + convert_smp_to_cpu_devices(machine); > + qemu_opts_foreach(qemu_find_opts("device"), count_cpu_devices, > + machine, 0); > + } > + > + /* > * Default to max_cpus = smp_cpus, in case the user doesn't > * specify a max_cpus value. > */ > @@ -3979,6 +4023,20 @@ int main(int argc, char **argv, char **envp) > exit(1); > } > > + if (smp_cpus < 1) { > + fprintf(stderr, "Invalid number of CPUs\n"); > + exit(1); > + } > + if (max_cpus < smp_cpus) { > + fprintf(stderr, "maxcpus must be equal to or greater than the number > of" > + " cpus defined\n"); > + exit(1); > + } > + if (max_cpus > 255) { > + fprintf(stderr, "Unsupported number of maxcpus\n"); > + exit(1); > + } > + > /* > * Get the default machine options from the machine if it is not already > * specified either by the configuration file or by the command line. > @@ -4305,6 +4363,13 @@ int main(int argc, char **argv, char **envp) > .cpu_model = cpu_model }; > machine->init(&args); > > + /* Create cpu devices */ > + if (CPUS_ARE_DEVICES(machine)) { > + smp_cpus = 0; /* Reset this because each cpu will count itself */ > + qemu_opts_foreach(qemu_find_opts("device"), handle_cpu_device, > + machine, 0); > + } > + > if (machine->post_cpu_init) { > machine->post_cpu_init(); > } > @@ -4324,8 +4389,10 @@ int main(int argc, char **argv, char **envp) > } > > /* init generic devices */ > - if (qemu_opts_foreach(qemu_find_opts("device"), device_init_func, NULL, > 1) != 0) > + if (qemu_opts_foreach(qemu_find_opts("device"), > + device_init_func, machine, 1) != 0) { > exit(1); > + } > > net_check_clients(); >