All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andre Przywara <andre.przywara@amd.com>
To: avi@redhat.com, anthony@codemonkey.ws
Cc: qemu-devel@nongnu.org, kvm@vger.kernel.org,
	Andre Przywara <andre.przywara@amd.com>
Subject: [RFC] allow multi-core guests: introduce cores= option to -cpu
Date: Fri, 3 Jul 2009 16:41:56 +0200	[thread overview]
Message-ID: <1246632116-31366-1-git-send-email-andre.przywara@amd.com> (raw)

Hi,

currently SMP guests happen to see <n> vCPUs as <n> different sockets.
Some guests (Windows comes to mind) have license restrictions and refuse
to run on multi-socket machines.
So lets introduce a "cores=" parameter to the -cpu option to let the user
specify the number of _cores_ the guest should see.

This patch has not been tested with all corner cases, so I just want to
hear your comments whether
a) we need such an option  and
b) you like this particular approach.

Applying this qemu.git patch to qemu-kvm.git fixes Windows SMP boot on
some versions, I successfully tried up to -smp 16 -cpu host,cores=8 with
WindowsXP Pro.                                                                  

Regards,
Andre.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/cpu.h    |    1 +
 target-i386/helper.c |   26 ++++++++++++++++++++++++--
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 4a8608e..96fa471 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -657,6 +657,7 @@ typedef struct CPUX86State {
     uint32_t cpuid_ext3_features;
     uint32_t cpuid_apic_id;
     int cpuid_vendor_override;
+    int cpuid_cores;
 
     /* MTRRs */
     uint64_t mtrr_fixed[11];
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 82e1ff1..9c54fb9 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -103,6 +103,7 @@ typedef struct x86_def_t {
     uint32_t xlevel;
     char model_id[48];
     int vendor_override;
+    int cores;
 } x86_def_t;
 
 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
@@ -351,7 +352,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
     char *featurestr, *name = strtok(s, ",");
     uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0;
     uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0;
-    int family = -1, model = -1, stepping = -1;
+    int family = -1, model = -1, stepping = -1, cores = 1;
 
     def = NULL;
     for (i = 0; i < ARRAY_SIZE(x86_defs); i++) {
@@ -406,6 +407,14 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
                     goto error;
                 }
                 x86_cpu_def->stepping = stepping;
+            } else if (!strcmp(featurestr, "cores")) {
+                char *err;
+                cores = strtol(val, &err, 10);
+                if (!*val || *err || cores < 1 || cores > 0xff) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                x86_cpu_def->cores = cores;
             } else if (!strcmp(featurestr, "vendor")) {
                 if (strlen(val) != 12) {
                     fprintf(stderr, "vendor string must be 12 chars long\n");
@@ -473,6 +482,7 @@ static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
         env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
     }
     env->cpuid_vendor_override = def->vendor_override;
+    env->cpuid_cores = def->cores;
     env->cpuid_level = def->level;
     if (def->family > 0x0f)
         env->cpuid_version = 0xf00 | ((def->family - 0x0f) << 20);
@@ -1562,9 +1572,14 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         break;
     case 1:
         *eax = env->cpuid_version;
-        *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
+        /* CLFLUSH size in quad words, Linux wants it. */
+        *ebx = (env->cpuid_apic_id << 24) | 8 << 8;
         *ecx = env->cpuid_ext_features;
         *edx = env->cpuid_features;
+        if (env->cpuid_cores > 1) {
+            *ebx |= env->cpuid_cores << 16;   /* LogicalProcessorCount */
+            *edx |= 1 << 28;    /* HTT bit */
+        }
         break;
     case 2:
         /* cache info: needed for Pentium Pro compatibility */
@@ -1642,6 +1657,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         *ecx = env->cpuid_ext3_features;
         *edx = env->cpuid_ext2_features;
 
+        if (env->cpuid_cores > 1) {
+            *ecx |= 1 << 1;    /* CmpLegacy bit */
+        }
+
         if (kvm_enabled()) {
             /* Nested SVM not yet supported in KVM */
             *ecx &= ~CPUID_EXT3_SVM;
@@ -1696,6 +1715,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         *ebx = 0;
         *ecx = 0;
         *edx = 0;
+        if (env->cpuid_cores > 1) {
+            *ecx |= env->cpuid_cores - 1;    /* NC: Number of CPU cores */
+        }
         break;
     case 0x8000000A:
         *eax = 0x00000001; /* SVM Revision */
-- 
1.6.1.3



WARNING: multiple messages have this Message-ID (diff)
From: Andre Przywara <andre.przywara@amd.com>
To: avi@redhat.com, anthony@codemonkey.ws
Cc: Andre Przywara <andre.przywara@amd.com>,
	qemu-devel@nongnu.org, kvm@vger.kernel.org
Subject: [Qemu-devel] [RFC] allow multi-core guests: introduce cores= option to -cpu
Date: Fri, 3 Jul 2009 16:41:56 +0200	[thread overview]
Message-ID: <1246632116-31366-1-git-send-email-andre.przywara@amd.com> (raw)

Hi,

currently SMP guests happen to see <n> vCPUs as <n> different sockets.
Some guests (Windows comes to mind) have license restrictions and refuse
to run on multi-socket machines.
So lets introduce a "cores=" parameter to the -cpu option to let the user
specify the number of _cores_ the guest should see.

This patch has not been tested with all corner cases, so I just want to
hear your comments whether
a) we need such an option  and
b) you like this particular approach.

Applying this qemu.git patch to qemu-kvm.git fixes Windows SMP boot on
some versions, I successfully tried up to -smp 16 -cpu host,cores=8 with
WindowsXP Pro.                                                                  

Regards,
Andre.

Signed-off-by: Andre Przywara <andre.przywara@amd.com>
---
 target-i386/cpu.h    |    1 +
 target-i386/helper.c |   26 ++++++++++++++++++++++++--
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 4a8608e..96fa471 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -657,6 +657,7 @@ typedef struct CPUX86State {
     uint32_t cpuid_ext3_features;
     uint32_t cpuid_apic_id;
     int cpuid_vendor_override;
+    int cpuid_cores;
 
     /* MTRRs */
     uint64_t mtrr_fixed[11];
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 82e1ff1..9c54fb9 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -103,6 +103,7 @@ typedef struct x86_def_t {
     uint32_t xlevel;
     char model_id[48];
     int vendor_override;
+    int cores;
 } x86_def_t;
 
 #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE)
@@ -351,7 +352,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
     char *featurestr, *name = strtok(s, ",");
     uint32_t plus_features = 0, plus_ext_features = 0, plus_ext2_features = 0, plus_ext3_features = 0;
     uint32_t minus_features = 0, minus_ext_features = 0, minus_ext2_features = 0, minus_ext3_features = 0;
-    int family = -1, model = -1, stepping = -1;
+    int family = -1, model = -1, stepping = -1, cores = 1;
 
     def = NULL;
     for (i = 0; i < ARRAY_SIZE(x86_defs); i++) {
@@ -406,6 +407,14 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
                     goto error;
                 }
                 x86_cpu_def->stepping = stepping;
+            } else if (!strcmp(featurestr, "cores")) {
+                char *err;
+                cores = strtol(val, &err, 10);
+                if (!*val || *err || cores < 1 || cores > 0xff) {
+                    fprintf(stderr, "bad numerical value %s\n", val);
+                    goto error;
+                }
+                x86_cpu_def->cores = cores;
             } else if (!strcmp(featurestr, "vendor")) {
                 if (strlen(val) != 12) {
                     fprintf(stderr, "vendor string must be 12 chars long\n");
@@ -473,6 +482,7 @@ static int cpu_x86_register (CPUX86State *env, const char *cpu_model)
         env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
     }
     env->cpuid_vendor_override = def->vendor_override;
+    env->cpuid_cores = def->cores;
     env->cpuid_level = def->level;
     if (def->family > 0x0f)
         env->cpuid_version = 0xf00 | ((def->family - 0x0f) << 20);
@@ -1562,9 +1572,14 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         break;
     case 1:
         *eax = env->cpuid_version;
-        *ebx = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */
+        /* CLFLUSH size in quad words, Linux wants it. */
+        *ebx = (env->cpuid_apic_id << 24) | 8 << 8;
         *ecx = env->cpuid_ext_features;
         *edx = env->cpuid_features;
+        if (env->cpuid_cores > 1) {
+            *ebx |= env->cpuid_cores << 16;   /* LogicalProcessorCount */
+            *edx |= 1 << 28;    /* HTT bit */
+        }
         break;
     case 2:
         /* cache info: needed for Pentium Pro compatibility */
@@ -1642,6 +1657,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         *ecx = env->cpuid_ext3_features;
         *edx = env->cpuid_ext2_features;
 
+        if (env->cpuid_cores > 1) {
+            *ecx |= 1 << 1;    /* CmpLegacy bit */
+        }
+
         if (kvm_enabled()) {
             /* Nested SVM not yet supported in KVM */
             *ecx &= ~CPUID_EXT3_SVM;
@@ -1696,6 +1715,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
         *ebx = 0;
         *ecx = 0;
         *edx = 0;
+        if (env->cpuid_cores > 1) {
+            *ecx |= env->cpuid_cores - 1;    /* NC: Number of CPU cores */
+        }
         break;
     case 0x8000000A:
         *eax = 0x00000001; /* SVM Revision */
-- 
1.6.1.3

             reply	other threads:[~2009-07-03 14:43 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-07-03 14:41 Andre Przywara [this message]
2009-07-03 14:41 ` [Qemu-devel] [RFC] allow multi-core guests: introduce cores= option to -cpu Andre Przywara
2009-07-03 14:52 ` Samuel Thibault
2009-07-03 14:52   ` [Qemu-devel] " Samuel Thibault
2009-07-03 23:28   ` Andre Przywara
2009-07-03 23:53     ` Samuel Thibault
2009-07-03 23:53       ` [Qemu-devel] " Samuel Thibault
2009-07-03 15:16 ` Brian Jackson
2009-07-03 15:16   ` [Qemu-devel] " Brian Jackson
2009-07-03 22:52   ` Andre Przywara
2009-07-03 22:52     ` [Qemu-devel] " Andre Przywara
2009-07-04  0:04     ` Jamie Lokier
2009-07-04  7:18     ` Gleb Natapov
2009-07-03 15:46 ` [Qemu-devel] " Paul Brook
2009-07-03 15:46   ` Paul Brook
2009-07-03 23:45   ` Andre Przywara
2009-07-04  5:58     ` Paul Brook
2009-07-04 15:25 ` Avi Kivity
2009-07-04 15:25   ` [Qemu-devel] " Avi Kivity
2009-07-05 13:23   ` Alexander Graf
2009-07-05 13:23     ` [Qemu-devel] " Alexander Graf
2009-07-05 14:53     ` Avi Kivity
2009-07-05 14:53       ` [Qemu-devel] " Avi Kivity
2009-07-05 15:04       ` Gleb Natapov
2009-07-05 15:04         ` [Qemu-devel] " Gleb Natapov
2009-07-05 15:11         ` Avi Kivity
2009-07-05 15:11           ` [Qemu-devel] " Avi Kivity
2009-07-05 15:11           ` Alexander Graf
2009-07-05 15:11             ` [Qemu-devel] " Alexander Graf
2009-07-05 15:17             ` Avi Kivity
2009-07-05 15:17               ` [Qemu-devel] " Avi Kivity

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=1246632116-31366-1-git-send-email-andre.przywara@amd.com \
    --to=andre.przywara@amd.com \
    --cc=anthony@codemonkey.ws \
    --cc=avi@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=qemu-devel@nongnu.org \
    /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.