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
next 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: linkBe 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.