From patchwork Fri Jul 3 14:41:56 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 33961 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n63EhaJu025362 for ; Fri, 3 Jul 2009 14:43:36 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754480AbZGCOn3 (ORCPT ); Fri, 3 Jul 2009 10:43:29 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1754181AbZGCOn3 (ORCPT ); Fri, 3 Jul 2009 10:43:29 -0400 Received: from outbound-sin.frontbridge.com ([207.46.51.80]:56565 "EHLO SG2EHSOBE006.bigfish.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754016AbZGCOn2 (ORCPT ); Fri, 3 Jul 2009 10:43:28 -0400 Received: from mail1-sin-R.bigfish.com (10.210.100.250) by SG2EHSOBE006.bigfish.com (10.210.112.26) with Microsoft SMTP Server id 8.1.340.0; Fri, 3 Jul 2009 14:43:30 +0000 Received: from mail1-sin (localhost.localdomain [127.0.0.1]) by mail1-sin-R.bigfish.com (Postfix) with ESMTP id 384341A4830D; Fri, 3 Jul 2009 14:43:37 +0000 (UTC) X-SpamScore: 1 X-BigFish: VPS1(zzzz1202hzzz32i65h) X-Spam-TCS-SCL: 4:0 Received: by mail1-sin (MessageSwitch) id 1246632212227631_9979; Fri, 3 Jul 2009 14:43:32 +0000 (UCT) Received: from ausb3extmailp02.amd.com (ausb3extmailp02.amd.com [163.181.251.22]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail1-sin.bigfish.com (Postfix) with ESMTP id C17A24F8056; Fri, 3 Jul 2009 14:42:58 +0000 (UTC) Received: from ausb3twp01.amd.com (ausb3twp01.amd.com [163.181.250.37]) by ausb3extmailp02.amd.com (Switch-3.2.7/Switch-3.2.7) with ESMTP id n63EgiZ8018347; Fri, 3 Jul 2009 09:42:47 -0500 X-WSS-ID: 0KM7NIZ-01-XC5-01 Received: from sausexbh1.amd.com (sausexbh1.amd.com [163.181.22.101]) by ausb3twp01.amd.com (Tumbleweed MailGate 3.5.1) with ESMTP id 2A7301943FF; Fri, 3 Jul 2009 09:42:34 -0500 (CDT) Received: from sausexmb5.amd.com ([163.181.49.129]) by sausexbh1.amd.com with Microsoft SMTPSVC(6.0.3790.3959); Fri, 3 Jul 2009 09:42:42 -0500 Received: from SDRSEXMB1.amd.com ([172.20.3.116]) by sausexmb5.amd.com with Microsoft SMTPSVC(6.0.3790.3959); Fri, 3 Jul 2009 09:42:41 -0500 Received: from localhost.localdomain ([165.204.15.42]) by SDRSEXMB1.amd.com with Microsoft SMTPSVC(6.0.3790.3959); Fri, 3 Jul 2009 16:41:48 +0200 From: Andre Przywara To: avi@redhat.com, anthony@codemonkey.ws CC: qemu-devel@nongnu.org, kvm@vger.kernel.org, Andre Przywara Subject: [RFC] allow multi-core guests: introduce cores= option to -cpu Date: Fri, 3 Jul 2009 16:41:56 +0200 Message-ID: <1246632116-31366-1-git-send-email-andre.przywara@amd.com> X-Mailer: git-send-email 1.6.1.3 X-OriginalArrivalTime: 03 Jul 2009 14:41:48.0018 (UTC) FILETIME=[64E25D20:01C9FBEC] MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Hi, currently SMP guests happen to see vCPUs as 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 --- 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 */