qemu-devel
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]