[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC 2/3] target-i386: add -smp X,apics=0x option
From: |
Chen Fan |
Subject: |
[Qemu-devel] [RFC 2/3] target-i386: add -smp X,apics=0x option |
Date: |
Tue, 14 Jan 2014 17:27:21 +0800 |
This option provides the infrastructure for specifying apicids when
boot VM, For example:
#boot with apicid 0 and 2:
-smp 2,apics=0xA,maxcpus=4 /* 1010 */
#boot with apicid 1 and 7:
-smp 2,apics=0x41,maxcpus=8 /* 0100 0001 */
Signed-off-by: Chen Fan <address@hidden>
---
hw/i386/pc.c | 9 +++++--
include/sysemu/sysemu.h | 4 ++++
qemu-options.hx | 15 +++++++++---
vl.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 84 insertions(+), 6 deletions(-)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 963446f..3582167 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -991,8 +991,13 @@ void pc_cpus_init(const char *cpu_model, DeviceState
*icc_bridge)
current_cpu_model = cpu_model;
for (i = 0; i < smp_cpus; i++) {
- cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
- icc_bridge, &error);
+ int64_t apic_id;
+ if (nb_boot_apics == 0) {
+ apic_id = x86_cpu_apic_id_from_index(i);
+ } else {
+ apic_id = x86_cpu_apic_id_from_index(boot_apics[i]);
+ }
+ cpu = pc_new_cpu(cpu_model, apic_id, icc_bridge, &error);
if (error) {
error_report("%s", error_get_pretty(error));
error_free(error);
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 495dae8..510a626 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -149,6 +149,10 @@ extern int nb_option_roms;
extern const char *prom_envs[MAX_PROM_ENVS];
extern unsigned int nb_prom_envs;
+#define MAX_APICS 255
+extern int nb_boot_apics;
+extern int64_t boot_apics[MAX_APICS];
+
/* pci-hotplug */
void pci_device_hot_add(Monitor *mon, const QDict *qdict);
int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo);
diff --git a/qemu-options.hx b/qemu-options.hx
index bcfe9ea..7f86519 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -73,16 +73,17 @@ Select CPU model (@code{-cpu help} for list and additional
feature selection)
ETEXI
DEF("smp", HAS_ARG, QEMU_OPTION_smp,
- "-smp
[cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets]\n"
+ "-smp
[cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets][,apics=apics]\n"
" set the number of CPUs to 'n' [default=1]\n"
" maxcpus= maximum number of total cpus, including\n"
" offline CPUs for hotplug, etc\n"
" cores= number of CPU cores on one socket\n"
" threads= number of threads on one CPU core\n"
- " sockets= number of discrete sockets in the system\n",
+ " sockets= number of discrete sockets in the system\n"
+ " apics= a hex number with leading '0x' as boot bitmap of
existed apicid\n",
QEMU_ARCH_ALL)
STEXI
address@hidden -smp
address@hidden,address@hidden,address@hidden,address@hidden,address@hidden
address@hidden -smp
address@hidden,address@hidden,address@hidden,address@hidden,address@hidden,address@hidden
@findex -smp
Simulate an SMP system with @var{n} CPUs. On the PC target, up to 255
CPUs are supported. On Sparc32 target, Linux limits the number of usable CPUs
@@ -92,6 +93,14 @@ of @var{threads} per cores and the total number of
@var{sockets} can be
specified. Missing values will be computed. If any on the three values is
given, the total number of CPUs @var{n} can be omitted. @var{maxcpus}
specifies the maximum number of hotpluggable CPUs.
address@hidden specifies the boot bitmap of existed apicid.
+
address@hidden
+#specify the boot bitmap of apicid with 0 and 2:
+qemu-system-i386 -smp 2,apics=0xA,maxcpus=4 /* 1010 */
+#specify the boot bitmap of apicid with 1 and 7:
+qemu-system-i386 -smp 2,apics=0x41,maxcpus=8 /* 0100 0001 */
address@hidden example
ETEXI
DEF("numa", HAS_ARG, QEMU_OPTION_numa,
diff --git a/vl.c b/vl.c
index 7511e70..870b1bd 100644
--- a/vl.c
+++ b/vl.c
@@ -254,6 +254,9 @@ unsigned long *node_cpumask[MAX_NODES];
uint8_t qemu_uuid[16];
bool qemu_uuid_set;
+int nb_boot_apics;
+int64_t boot_apics[MAX_APICS];
+
static QEMUBootSetHandler *boot_set_handler;
static void *boot_set_opaque;
@@ -1379,6 +1382,9 @@ static QemuOptsList qemu_smp_opts = {
}, {
.name = "maxcpus",
.type = QEMU_OPT_NUMBER,
+ }, {
+ .name = "apics",
+ .type = QEMU_OPT_STRING,
},
{ /*End of list */ }
},
@@ -1392,6 +1398,7 @@ static void smp_parse(QemuOpts *opts)
unsigned sockets = qemu_opt_get_number(opts, "sockets", 0);
unsigned cores = qemu_opt_get_number(opts, "cores", 0);
unsigned threads = qemu_opt_get_number(opts, "threads", 0);
+ const char *apics = qemu_opt_get(opts, "apics");
/* compute missing values, prefer sockets over cores over threads */
if (cpus == 0 || sockets == 0) {
@@ -1416,6 +1423,55 @@ static void smp_parse(QemuOpts *opts)
smp_cores = cores > 0 ? cores : 1;
smp_threads = threads > 0 ? threads : 1;
+ if (apics) {
+ if (strstart(apics, "0x", &apics)) {
+ if (*apics != '\0') {
+ int i, count;
+ int64_t max_apicid = 0;
+ uint32_t val;
+ char tmp[2];
+
+ count = strlen(apics);
+
+ for (i = 0; i < count; i++) {
+ tmp[0] = apics[i];
+ tmp[1] = '\0';
+ sscanf(tmp, "%x", &val);
+
+ if (val & 1 << 3) {
+ boot_apics[nb_boot_apics++] = i * 4;
+ }
+ if (val & 1 << 2) {
+ boot_apics[nb_boot_apics++] = i * 4 + 1;
+ }
+ if (val & 1 << 1) {
+ boot_apics[nb_boot_apics++] = i * 4 + 2;
+ }
+ if (val & 1 << 0) {
+ boot_apics[nb_boot_apics++] = i * 4 + 3;
+ }
+ if (max_apicid < boot_apics[nb_boot_apics - 1]) {
+ max_apicid = boot_apics[nb_boot_apics - 1];
+ }
+ }
+
+ if ((max_cpus == 0 && max_apicid > smp_cpus - 1) ||
+ (max_cpus != 0 && max_apicid > max_cpus - 1)) {
+ fprintf(stderr, "specified apicid"
+ " must be smaller than maxcpus\n");
+ exit(1);
+ }
+ } else {
+ fprintf(stderr, "must specify"
+ " one or more digits in apics\n");
+ exit(1);
+ }
+ } else {
+ fprintf(stderr, "could not parse apics: %s,"
+ " apics must use a leading '0x' digits\n", apics);
+ exit(1);
+ }
+ }
}
if (max_cpus == 0) {
@@ -1430,7 +1486,11 @@ static void smp_parse(QemuOpts *opts)
fprintf(stderr, "maxcpus must be equal to or greater than smp\n");
exit(1);
}
-
+ if (nb_boot_apics && nb_boot_apics != smp_cpus) {
+ fprintf(stderr, "the count of specified apics: %d"
+ " is not equal to smp: %d\n", nb_boot_apics, smp_cpus);
+ exit(1);
+ }
}
static void configure_realtime(QemuOpts *opts)
--
1.8.1.4
- Re: [Qemu-devel] [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn(), (continued)
- Re: [Qemu-devel] [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn(), Igor Mammedov, 2014/01/14
- Re: [Qemu-devel] [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn(), Chen Fan, 2014/01/15
- Re: [Qemu-devel] [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn(), Igor Mammedov, 2014/01/15
- [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn()), Eduardo Habkost, 2014/01/17
- Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn()), Igor Mammedov, 2014/01/20
- Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn()), Chen Fan, 2014/01/21
- Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn()), Igor Mammedov, 2014/01/21
- Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn()), Chen Fan, 2014/01/21
- Re: [Qemu-devel] Exposing and calculating CPU APIC IDs (was Re: [RFC 1/3] target-i386: moving registers of vmstate from cpu_exec_init() to x86_cpu_realizefn()), Andreas Färber, 2014/01/21
[Qemu-devel] [RFC 3/3] target-i386: add qmp command 'query-cpus' to display apic_id, Chen Fan, 2014/01/14
[Qemu-devel] [RFC 2/3] target-i386: add -smp X,apics=0x option,
Chen Fan <=