* [Qemu-devel] [PATCH qom-cpu 0/5] x86 CPU cleanup, part 4 @ 2013-01-17 15:16 Igor Mammedov 2013-01-17 15:16 ` [Qemu-devel] [PATCH 1/5] target-i386: print deprecated warning if xlevel < 0x80000000 Igor Mammedov ` (4 more replies) 0 siblings, 5 replies; 16+ messages in thread From: Igor Mammedov @ 2013-01-17 15:16 UTC (permalink / raw) To: qemu-devel; +Cc: ehabkost, afaerber It's rebase of remnants of "[PATCH qom-cpu 00/17] x86 CPU cleanup, part 3" [1] taking in account comments of reviewers. This series is several cleanups, moved out from CPU properties series, since they do not really depend on CPU properties re-factoring and could simplify CPU subclasses work as well. Series doesn't depend on cpu as device or any other series, and applies to current master. git tree for testing: https://github.com/imammedo/qemu/tree/x86_cpu_cleanup.part4 vendor related changes are tested with: https://github.com/imammedo/virt-test/tree/cpuid_features following command was used to run test: ./run -t kvm --qemu-bin=$QEMU --tests="qemu_cpu.qemu13 cpuid.custom_vendor" *1 - http://lists.gnu.org/archive/html/qemu-devel/2013-01/msg01732.html v6: - patches 1-3 from previous series already in master, dropped - patches 4-5 from previous series are sqashed in one - patches 7-8,10-17 from previous series are sqashed in one and cpu_x86_parse_featurestr() rewritten to set properties directly on CPU v5: - dropped patch "[PATCH 06/20] target-i386: move out CPU features initialization in separate func" due to Andreas objection - fixed x86cpu to x86_cpu new function prefixes - rebased on top of "disable kvm_mmu + -cpu "enforce" fixes (v3)" due conflicts - patches 1-4 from "[PATCH 00/20 v4] x86 CPU cleanup (wave 2)", already in master. So dropped from here - added patches 16-17 to deal with tsc_freq parsing without introducing new new visitor v4: - rename [01/20] from: target-i386: filter out not TCG features if running without kvm at realize time to: target-i386: filter out unsupported features at realize time - make commit lines shorter for: target-i386: move kvm_check_features_against_host() check to realize time - restore removed by mistake host_cpuid() call in: target-i386: replace uint32_t vendor fields by vendor string in x86_def_t - fix spelling in: target-i386: print depricated warning if xlevel < 0x80000000 - use qstring_append_int() for converting xlevel to string in: target-i386: set custom 'xlevel' without intermediate x86_def_t v3: - [07/20] sets error if cpu name is empty, restore return -1 on error - get rid of *vendor_override field in CPUX86State & co - mark xlevel < 0x80000000 as depricated - squash idef-ing kvm specific functions in [08/20] - expand comment of [12/20] and reorder it right before "set custom" patches v2: - cleanup commit message and style fixes in [PATCH 2/6] target-i386: sanitize AMD's ext2_features at realize time - extracted more patches [07-20] from cpu properties series, that were more cleanups and code reorganizing than conversion to static properties. Igor Mammedov (5): target-i386: print deprecated warning if xlevel < 0x80000000 target-i386: replace uint32_t vendor fields by vendor string in x86_def_t target-i386: remove vendor_override field from CPUX86State target-i386: set custom features/properties without intermediate x86_def_t target-i386: remove setting tsc-frequency from x86_def_t target-i386/cpu.c | 322 ++++++++++++++++++++++------------------------------- target-i386/cpu.h | 7 +- 2 files changed, 138 insertions(+), 191 deletions(-) ^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 1/5] target-i386: print deprecated warning if xlevel < 0x80000000 2013-01-17 15:16 [Qemu-devel] [PATCH qom-cpu 0/5] x86 CPU cleanup, part 4 Igor Mammedov @ 2013-01-17 15:16 ` Igor Mammedov 2013-01-21 8:39 ` Andreas Färber 2013-01-17 15:16 ` [Qemu-devel] [PATCH 2/5] target-i386: replace uint32_t vendor fields by vendor string in x86_def_t Igor Mammedov ` (3 subsequent siblings) 4 siblings, 1 reply; 16+ messages in thread From: Igor Mammedov @ 2013-01-17 15:16 UTC (permalink / raw) To: qemu-devel; +Cc: ehabkost, afaerber Signed-off-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> --- target-i386/cpu.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 333745b..ce914da 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1399,6 +1399,8 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) goto error; } if (numvalue < 0x80000000) { + fprintf(stderr, "xlevel value shall always be >= 0x80000000" + ", fixup will be deprecated in future versions\n"); numvalue += 0x80000000; } x86_cpu_def->xlevel = numvalue; -- 1.7.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] target-i386: print deprecated warning if xlevel < 0x80000000 2013-01-17 15:16 ` [Qemu-devel] [PATCH 1/5] target-i386: print deprecated warning if xlevel < 0x80000000 Igor Mammedov @ 2013-01-21 8:39 ` Andreas Färber 2013-01-21 12:14 ` Igor Mammedov 0 siblings, 1 reply; 16+ messages in thread From: Andreas Färber @ 2013-01-21 8:39 UTC (permalink / raw) To: Igor Mammedov; +Cc: qemu-devel, Anthony Liguori, ehabkost Am 17.01.2013 16:16, schrieb Igor Mammedov: > Signed-off-by: Igor Mammedov <imammedo@redhat.com> > Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> > --- > target-i386/cpu.c | 2 ++ > 1 files changed, 2 insertions(+), 0 deletions(-) > > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > index 333745b..ce914da 100644 > --- a/target-i386/cpu.c > +++ b/target-i386/cpu.c > @@ -1399,6 +1399,8 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) > goto error; > } > if (numvalue < 0x80000000) { > + fprintf(stderr, "xlevel value shall always be >= 0x80000000" > + ", fixup will be deprecated in future versions\n"); > numvalue += 0x80000000; > } > x86_cpu_def->xlevel = numvalue; This has been reviewed without objections so far, so I would apply it for 1.4. Either way you should document this intent for users already: http://wiki.qemu.org/ChangeLog/1.4 We had such discussions before, around removing cpudef support. When do you plan to remove this, and being deprecated, shouldn't it rather read "fixup will be removed in future versions"? ;) If it fits within 80 chars I can edit it myself. Cheers, Andreas -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [PATCH 1/5] target-i386: print deprecated warning if xlevel < 0x80000000 2013-01-21 8:39 ` Andreas Färber @ 2013-01-21 12:14 ` Igor Mammedov 0 siblings, 0 replies; 16+ messages in thread From: Igor Mammedov @ 2013-01-21 12:14 UTC (permalink / raw) To: Andreas Färber; +Cc: qemu-devel, Anthony Liguori, ehabkost On Mon, 21 Jan 2013 09:39:07 +0100 Andreas Färber <afaerber@suse.de> wrote: > Am 17.01.2013 16:16, schrieb Igor Mammedov: > > Signed-off-by: Igor Mammedov <imammedo@redhat.com> > > Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> > > --- > > target-i386/cpu.c | 2 ++ > > 1 files changed, 2 insertions(+), 0 deletions(-) > > > > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > > index 333745b..ce914da 100644 > > --- a/target-i386/cpu.c > > +++ b/target-i386/cpu.c > > @@ -1399,6 +1399,8 @@ static int cpu_x86_parse_featurestr(x86_def_t > > *x86_cpu_def, char *features) goto error; > > } > > if (numvalue < 0x800000 00) { > > + fprintf(stderr, "xlevel value shall always be >= > > 0x80000000" > > + ", fixup will be deprecated in future > > versions\n"); numvalue += 0x80000000; > > } > > x86_cpu_def->xlevel = numvalue; > > This has been reviewed without objections so far, so I would apply it > for 1.4. Either way you should document this intent for users already: > http://wiki.qemu.org/ChangeLog/1.4 Would be something like this suitable: xlevel argument for -cpu option, currently fix-ups it's value if it's less than 0x80000000. Fix-up will be removed in QEMU 1.6 release and users are expected to provide valid xlevel value or qemu will fail to start. > > We had such discussions before, around removing cpudef support. > > When do you plan to remove this, and being deprecated, shouldn't it > rather read "fixup will be removed in future versions"? ;) > If it fits within 80 chars I can edit it myself. No need for it, I'll fix it and respin series. > > Cheers, > Andreas > Thanks, Igor ^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 2/5] target-i386: replace uint32_t vendor fields by vendor string in x86_def_t 2013-01-17 15:16 [Qemu-devel] [PATCH qom-cpu 0/5] x86 CPU cleanup, part 4 Igor Mammedov 2013-01-17 15:16 ` [Qemu-devel] [PATCH 1/5] target-i386: print deprecated warning if xlevel < 0x80000000 Igor Mammedov @ 2013-01-17 15:16 ` Igor Mammedov 2013-01-17 15:29 ` Eduardo Habkost ` (2 more replies) 2013-01-17 15:16 ` [Qemu-devel] [PATCH 3/5] target-i386: remove vendor_override field from CPUX86State Igor Mammedov ` (2 subsequent siblings) 4 siblings, 3 replies; 16+ messages in thread From: Igor Mammedov @ 2013-01-17 15:16 UTC (permalink / raw) To: qemu-devel; +Cc: ehabkost, afaerber Vendor property setter takes string as vendor value but cpudefs use uint32_t vendor[123] fields to define vendor value. It makes it difficult to unify and use property setter for values from cpudefs. Simplify code by using vendor property setter, vendor[123] fields are converted into vendor[13] array to keep its value. And vendor property setter is used to access/set value on CPU. - Make for() cycle reusable for the next patch by adding x86_cpu_vendor_words2str() Intel's CPUID spec[1] says: " 5.1.1 ... These registers contain the ASCII string: GenuineIntel ... " List[2] of known vendor values shows that they all are 12 ASCII characters long, padded where necessary with space Current supported values are all ASCII characters packed in ebx, edx, ecx. So lets state that qemu supports 12 ASCII characters packed in ebx, edx, ecx registers for cpuid(0) instruction. *1 - http://www.intel.com/Assets/PDF/appnote/241618.pdf *2 - http://en.wikipedia.org/wiki/CPUID#EAX.3D0:_Get_vendor_ID Signed-off-by: Igor Mammedov <imammedo@redhat.com> --- v4: - add to commit msg that supported vendor should be 12 ASCII characters long string - squash in "add x86_cpu_vendor_words2str()" patch - use strncmp() instead of strcmp() Suggested-By: Andreas Färber <afaerber@suse.de> - style fix: align args on next line properly v3: - replace x86cpu_vendor_words2str() with x86_cpu_vendor_words2str() due to renaming of the last in previous patch - rebased with "target-i386: move out CPU features initialization in separate func" patch dropped v2: - restore deleted host_cpuid() call in kvm_cpu_fill_host() Spotted-By: Eduardo Habkost <ehabkost@redhat.com> --- target-i386/cpu.c | 148 ++++++++++++++++------------------------------------- target-i386/cpu.h | 6 +- 2 files changed, 48 insertions(+), 106 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index ce914da..ab80dbe 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -45,6 +45,18 @@ #include "hw/apic_internal.h" #endif +static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, + uint32_t vendor2, uint32_t vendor3) +{ + int i; + for (i = 0; i < 4; i++) { + dst[i] = vendor1 >> (8 * i); + dst[i + 4] = vendor2 >> (8 * i); + dst[i + 8] = vendor3 >> (8 * i); + } + dst[CPUID_VENDOR_SZ] = '\0'; +} + /* feature flags taken from "Intel Processor Identification and the CPUID * Instruction" and AMD's "CPUID Specification". In cases of disagreement * between feature naming conventions, aliases may be added. @@ -341,7 +353,7 @@ typedef struct x86_def_t { struct x86_def_t *next; const char *name; uint32_t level; - uint32_t vendor1, vendor2, vendor3; + char vendor[CPUID_VENDOR_SZ + 1]; int family; int model; int stepping; @@ -406,9 +418,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "qemu64", .level = 4, - .vendor1 = CPUID_VENDOR_AMD_1, - .vendor2 = CPUID_VENDOR_AMD_2, - .vendor3 = CPUID_VENDOR_AMD_3, + .vendor = CPUID_VENDOR_AMD, .family = 6, .model = 2, .stepping = 3, @@ -425,9 +435,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "phenom", .level = 5, - .vendor1 = CPUID_VENDOR_AMD_1, - .vendor2 = CPUID_VENDOR_AMD_2, - .vendor3 = CPUID_VENDOR_AMD_3, + .vendor = CPUID_VENDOR_AMD, .family = 16, .model = 2, .stepping = 3, @@ -453,9 +461,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "core2duo", .level = 10, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 15, .stepping = 11, @@ -474,9 +480,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "kvm64", .level = 5, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 15, .model = 6, .stepping = 1, @@ -500,9 +504,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "qemu32", .level = 4, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 3, .stepping = 3, @@ -513,9 +515,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "kvm32", .level = 5, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 15, .model = 6, .stepping = 1, @@ -530,9 +530,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "coreduo", .level = 10, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 14, .stepping = 8, @@ -548,9 +546,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "486", .level = 1, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 4, .model = 0, .stepping = 0, @@ -560,9 +556,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "pentium", .level = 1, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 5, .model = 4, .stepping = 3, @@ -572,9 +566,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "pentium2", .level = 2, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 5, .stepping = 2, @@ -584,9 +576,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "pentium3", .level = 2, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 7, .stepping = 3, @@ -596,9 +586,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "athlon", .level = 2, - .vendor1 = CPUID_VENDOR_AMD_1, - .vendor2 = CPUID_VENDOR_AMD_2, - .vendor3 = CPUID_VENDOR_AMD_3, + .vendor = CPUID_VENDOR_AMD, .family = 6, .model = 2, .stepping = 3, @@ -612,9 +600,7 @@ static x86_def_t builtin_x86_defs[] = { .name = "n270", /* original is on level 10 */ .level = 5, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 28, .stepping = 2, @@ -633,9 +619,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "Conroe", .level = 2, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 2, .stepping = 3, @@ -653,9 +637,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "Penryn", .level = 2, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 2, .stepping = 3, @@ -674,9 +656,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "Nehalem", .level = 2, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 2, .stepping = 3, @@ -695,9 +675,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "Westmere", .level = 11, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 44, .stepping = 1, @@ -717,9 +695,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "SandyBridge", .level = 0xd, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 42, .stepping = 1, @@ -742,9 +718,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "Haswell", .level = 0xd, - .vendor1 = CPUID_VENDOR_INTEL_1, - .vendor2 = CPUID_VENDOR_INTEL_2, - .vendor3 = CPUID_VENDOR_INTEL_3, + .vendor = CPUID_VENDOR_INTEL, .family = 6, .model = 60, .stepping = 1, @@ -772,9 +746,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "Opteron_G1", .level = 5, - .vendor1 = CPUID_VENDOR_AMD_1, - .vendor2 = CPUID_VENDOR_AMD_2, - .vendor3 = CPUID_VENDOR_AMD_3, + .vendor = CPUID_VENDOR_AMD, .family = 15, .model = 6, .stepping = 1, @@ -796,9 +768,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "Opteron_G2", .level = 5, - .vendor1 = CPUID_VENDOR_AMD_1, - .vendor2 = CPUID_VENDOR_AMD_2, - .vendor3 = CPUID_VENDOR_AMD_3, + .vendor = CPUID_VENDOR_AMD, .family = 15, .model = 6, .stepping = 1, @@ -822,9 +792,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "Opteron_G3", .level = 5, - .vendor1 = CPUID_VENDOR_AMD_1, - .vendor2 = CPUID_VENDOR_AMD_2, - .vendor3 = CPUID_VENDOR_AMD_3, + .vendor = CPUID_VENDOR_AMD, .family = 15, .model = 6, .stepping = 1, @@ -850,9 +818,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "Opteron_G4", .level = 0xd, - .vendor1 = CPUID_VENDOR_AMD_1, - .vendor2 = CPUID_VENDOR_AMD_2, - .vendor3 = CPUID_VENDOR_AMD_3, + .vendor = CPUID_VENDOR_AMD, .family = 21, .model = 1, .stepping = 2, @@ -882,9 +848,7 @@ static x86_def_t builtin_x86_defs[] = { { .name = "Opteron_G5", .level = 0xd, - .vendor1 = CPUID_VENDOR_AMD_1, - .vendor2 = CPUID_VENDOR_AMD_2, - .vendor3 = CPUID_VENDOR_AMD_3, + .vendor = CPUID_VENDOR_AMD, .family = 21, .model = 2, .stepping = 0, @@ -945,9 +909,7 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def->name = "host"; host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); - x86_cpu_def->vendor1 = ebx; - x86_cpu_def->vendor2 = edx; - x86_cpu_def->vendor3 = ecx; + x86_cpu_vendor_words2str(x86_cpu_def->vendor, ebx, edx, ecx); host_cpuid(0x1, 0, &eax, &ebx, &ecx, &edx); x86_cpu_def->family = ((eax >> 8) & 0x0F) + ((eax >> 20) & 0xFF); @@ -975,9 +937,8 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def->vendor_override = 0; /* Call Centaur's CPUID instruction. */ - if (x86_cpu_def->vendor1 == CPUID_VENDOR_VIA_1 && - x86_cpu_def->vendor2 == CPUID_VENDOR_VIA_2 && - x86_cpu_def->vendor3 == CPUID_VENDOR_VIA_3) { + if (!strncmp(x86_cpu_def->vendor, CPUID_VENDOR_VIA, + sizeof(x86_cpu_def->vendor))) { host_cpuid(0xC0000000, 0, &eax, &ebx, &ecx, &edx); eax = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX); if (eax >= 0xC0000001) { @@ -1213,15 +1174,10 @@ static char *x86_cpuid_get_vendor(Object *obj, Error **errp) X86CPU *cpu = X86_CPU(obj); CPUX86State *env = &cpu->env; char *value; - int i; value = (char *)g_malloc(CPUID_VENDOR_SZ + 1); - for (i = 0; i < 4; i++) { - value[i ] = env->cpuid_vendor1 >> (8 * i); - value[i + 4] = env->cpuid_vendor2 >> (8 * i); - value[i + 8] = env->cpuid_vendor3 >> (8 * i); - } - value[CPUID_VENDOR_SZ] = '\0'; + x86_cpu_vendor_words2str(value, env->cpuid_vendor1, env->cpuid_vendor2, + env->cpuid_vendor3); return value; } @@ -1341,7 +1297,6 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name) */ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) { - unsigned int i; char *featurestr; /* Single 'key=value" string being parsed */ /* Features to be added */ FeatureWordArray plus_features = { 0 }; @@ -1405,18 +1360,7 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) } x86_cpu_def->xlevel = numvalue; } else if (!strcmp(featurestr, "vendor")) { - if (strlen(val) != 12) { - fprintf(stderr, "vendor string must be 12 chars long\n"); - goto error; - } - x86_cpu_def->vendor1 = 0; - x86_cpu_def->vendor2 = 0; - x86_cpu_def->vendor3 = 0; - for(i = 0; i < 4; i++) { - x86_cpu_def->vendor1 |= ((uint8_t)val[i ]) << (8 * i); - x86_cpu_def->vendor2 |= ((uint8_t)val[i + 4]) << (8 * i); - x86_cpu_def->vendor3 |= ((uint8_t)val[i + 8]) << (8 * i); - } + pstrcpy(x86_cpu_def->vendor, sizeof(x86_cpu_def->vendor), val); x86_cpu_def->vendor_override = 1; } else if (!strcmp(featurestr, "model_id")) { pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id), @@ -1611,10 +1555,8 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) error_setg(&error, "Invalid cpu_model string format: %s", cpu_model); goto out; } - assert(def->vendor1); - env->cpuid_vendor1 = def->vendor1; - env->cpuid_vendor2 = def->vendor2; - env->cpuid_vendor3 = def->vendor3; + assert(def->vendor[0]); + object_property_set_str(OBJECT(cpu), def->vendor, "vendor", &error); env->cpuid_vendor_override = def->vendor_override; object_property_set_int(OBJECT(cpu), def->level, "level", &error); object_property_set_int(OBJECT(cpu), def->family, "family", &error); diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 4e091cd..554bd4a 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -537,14 +537,14 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */ #define CPUID_VENDOR_INTEL_2 0x49656e69 /* "ineI" */ #define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */ +#define CPUID_VENDOR_INTEL "GenuineIntel" #define CPUID_VENDOR_AMD_1 0x68747541 /* "Auth" */ #define CPUID_VENDOR_AMD_2 0x69746e65 /* "enti" */ #define CPUID_VENDOR_AMD_3 0x444d4163 /* "cAMD" */ +#define CPUID_VENDOR_AMD "AuthenticAMD" -#define CPUID_VENDOR_VIA_1 0x746e6543 /* "Cent" */ -#define CPUID_VENDOR_VIA_2 0x48727561 /* "aurH" */ -#define CPUID_VENDOR_VIA_3 0x736c7561 /* "auls" */ +#define CPUID_VENDOR_VIA "CentaurHauls" #define CPUID_MWAIT_IBE (1 << 1) /* Interrupts can exit capability */ #define CPUID_MWAIT_EMX (1 << 0) /* enumeration supported */ -- 1.7.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] target-i386: replace uint32_t vendor fields by vendor string in x86_def_t 2013-01-17 15:16 ` [Qemu-devel] [PATCH 2/5] target-i386: replace uint32_t vendor fields by vendor string in x86_def_t Igor Mammedov @ 2013-01-17 15:29 ` Eduardo Habkost 2013-01-18 7:12 ` li guang 2013-01-21 8:18 ` Andreas Färber 2 siblings, 0 replies; 16+ messages in thread From: Eduardo Habkost @ 2013-01-17 15:29 UTC (permalink / raw) To: Igor Mammedov; +Cc: qemu-devel, afaerber On Thu, Jan 17, 2013 at 04:16:31PM +0100, Igor Mammedov wrote: > Vendor property setter takes string as vendor value but cpudefs > use uint32_t vendor[123] fields to define vendor value. It makes it > difficult to unify and use property setter for values from cpudefs. > > Simplify code by using vendor property setter, vendor[123] fields > are converted into vendor[13] array to keep its value. And vendor > property setter is used to access/set value on CPU. > > - Make for() cycle reusable for the next patch by adding > x86_cpu_vendor_words2str() > > Intel's CPUID spec[1] says: > " > 5.1.1 ... > These registers contain the ASCII string: GenuineIntel > ... > " > > List[2] of known vendor values shows that they all are 12 ASCII > characters long, padded where necessary with space > > Current supported values are all ASCII characters packed in > ebx, edx, ecx. So lets state that qemu supports 12 ASCII characters > packed in ebx, edx, ecx registers for cpuid(0) instruction. Nit: I guess you mean ASCII _printable_ characters. NUL is an ASCII character as well, but it won't be supported. > > *1 - http://www.intel.com/Assets/PDF/appnote/241618.pdf > *2 - http://en.wikipedia.org/wiki/CPUID#EAX.3D0:_Get_vendor_ID > > Signed-off-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> Minor comment below, feel free to ignore. > --- > v4: > - add to commit msg that supported vendor should be 12 ASCII > characters long string > - squash in "add x86_cpu_vendor_words2str()" patch > - use strncmp() instead of strcmp() > Suggested-By: Andreas Färber <afaerber@suse.de> > - style fix: align args on next line properly > v3: > - replace x86cpu_vendor_words2str() with x86_cpu_vendor_words2str() > due to renaming of the last in previous patch > - rebased with "target-i386: move out CPU features initialization > in separate func" patch dropped > v2: > - restore deleted host_cpuid() call in kvm_cpu_fill_host() > Spotted-By: Eduardo Habkost <ehabkost@redhat.com> > --- > target-i386/cpu.c | 148 ++++++++++++++++------------------------------------- > target-i386/cpu.h | 6 +- > 2 files changed, 48 insertions(+), 106 deletions(-) > > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > index ce914da..ab80dbe 100644 > --- a/target-i386/cpu.c > +++ b/target-i386/cpu.c [...] > @@ -975,9 +937,8 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) > x86_cpu_def->vendor_override = 0; > > /* Call Centaur's CPUID instruction. */ > - if (x86_cpu_def->vendor1 == CPUID_VENDOR_VIA_1 && > - x86_cpu_def->vendor2 == CPUID_VENDOR_VIA_2 && > - x86_cpu_def->vendor3 == CPUID_VENDOR_VIA_3) { > + if (!strncmp(x86_cpu_def->vendor, CPUID_VENDOR_VIA, > + sizeof(x86_cpu_def->vendor))) { We don't need strncmp() if we are sure the vendor field is always NUL-terminated. > host_cpuid(0xC0000000, 0, &eax, &ebx, &ecx, &edx); > eax = kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX); > if (eax >= 0xC0000001) { [...] -- Eduardo ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] target-i386: replace uint32_t vendor fields by vendor string in x86_def_t 2013-01-17 15:16 ` [Qemu-devel] [PATCH 2/5] target-i386: replace uint32_t vendor fields by vendor string in x86_def_t Igor Mammedov 2013-01-17 15:29 ` Eduardo Habkost @ 2013-01-18 7:12 ` li guang 2013-01-18 13:40 ` Igor Mammedov 2013-01-21 8:18 ` Andreas Färber 2 siblings, 1 reply; 16+ messages in thread From: li guang @ 2013-01-18 7:12 UTC (permalink / raw) To: Igor Mammedov; +Cc: qemu-devel, afaerber, ehabkost 在 2013-01-17四的 16:16 +0100,Igor Mammedov写道: > > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > index ce914da..ab80dbe 100644 > --- a/target-i386/cpu.c > +++ b/target-i386/cpu.c > @@ -45,6 +45,18 @@ > #include "hw/apic_internal.h" > #endif > > +static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, > + uint32_t vendor2, uint32_t vendor3) sorry, but I should say "_vendor_words2str" seems not so suitable, it's mostly not a convertor, but a compactor, so I suggest to use "_vendor_str" directly. > +{ > + int i; > + for (i = 0; i < 4; i++) { > + dst[i] = vendor1 >> (8 * i); > + dst[i + 4] = vendor2 >> (8 * i); > + dst[i + 8] = vendor3 >> (8 * i); > + } > + dst[CPUID_VENDOR_SZ] = '\0'; > +} > + > --- a/target-i386/cpu.h > +++ b/target-i386/cpu.h > @@ -537,14 +537,14 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; > #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */ > #define CPUID_VENDOR_INTEL_2 0x49656e69 /* "ineI" */ > #define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */ > +#define CPUID_VENDOR_INTEL "GenuineIntel" > you said the reason you did not remove _VENDOR_INTEL_{1,2,3} is they're used somewhere, did you mean "target-i386/translate.c" for sysenter instruction? if it is, why can't we also remove them there? > #define CPUID_VENDOR_AMD_1 0x68747541 /* "Auth" */ > #define CPUID_VENDOR_AMD_2 0x69746e65 /* "enti" */ > #define CPUID_VENDOR_AMD_3 0x444d4163 /* "cAMD" */ > +#define CPUID_VENDOR_AMD "AuthenticAMD" > > -#define CPUID_VENDOR_VIA_1 0x746e6543 /* "Cent" */ > -#define CPUID_VENDOR_VIA_2 0x48727561 /* "aurH" */ > -#define CPUID_VENDOR_VIA_3 0x736c7561 /* "auls" */ > +#define CPUID_VENDOR_VIA "CentaurHauls" > > #define CPUID_MWAIT_IBE (1 << 1) /* Interrupts can exit capability */ > #define CPUID_MWAIT_EMX (1 << 0) /* enumeration supported */ -- regards! li guang ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] target-i386: replace uint32_t vendor fields by vendor string in x86_def_t 2013-01-18 7:12 ` li guang @ 2013-01-18 13:40 ` Igor Mammedov 2013-01-21 3:16 ` li guang 0 siblings, 1 reply; 16+ messages in thread From: Igor Mammedov @ 2013-01-18 13:40 UTC (permalink / raw) To: li guang; +Cc: qemu-devel, afaerber, ehabkost On Fri, 18 Jan 2013 15:12:36 +0800 li guang <lig.fnst@cn.fujitsu.com> wrote: > 在 2013-01-17四的 16:16 +0100,Igor Mammedov写道: > > > > > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > > index ce914da..ab80dbe 100644 > > --- a/target-i386/cpu.c > > +++ b/target-i386/cpu.c > > @@ -45,6 +45,18 @@ > > #include "hw/apic_internal.h" > > #endif > > > > +static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, > > + uint32_t vendor2, uint32_t vendor3) > > sorry, but I should say "_vendor_words2str" seems not so suitable, > it's mostly not a convertor, but a compactor, so I suggest to use > "_vendor_str" directly. I think that "_vendor_words2str" describes more clearly what function does, regardless whether it is conversion or compaction. "_vendor_str" seems more ambiguous though. But if you insist, I can change to it. BTW: it's not just copying, it copies from little endinan words to string. > > > +{ > > + int i; > > + for (i = 0; i < 4; i++) { > > + dst[i] = vendor1 >> (8 * i); > > + dst[i + 4] = vendor2 >> (8 * i); > > + dst[i + 8] = vendor3 >> (8 * i); > > + } > > + dst[CPUID_VENDOR_SZ] = '\0'; > > +} > > + > > > --- a/target-i386/cpu.h > > +++ b/target-i386/cpu.h > > @@ -537,14 +537,14 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; > > #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */ > > #define CPUID_VENDOR_INTEL_2 0x49656e69 /* "ineI" */ > > #define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */ > > +#define CPUID_VENDOR_INTEL "GenuineIntel" > > > > you said the reason you did not remove _VENDOR_INTEL_{1,2,3} > is they're used somewhere, did you mean "target-i386/translate.c" > for sysenter instruction? > if it is, why can't we also remove them there? That would imply conversion of CPUX86State to using string for cpuid_vendor instead of currents words which would mean to do conversion every time cpuid instruction is called in guest. I'd rather keep current cpuid_vendor{1,2,3} in CPUX86State. Purpose of this patch is to switch from direct field copying when initializing CPU to using property setter. If we ever decide to convert CPUX86State.cpuid_vendor{1,2,3} into string, it could be done by a separate patch. In addition, wouldn't strcmp() there be less effective performance wise, versus just number comparison if we would convert CPUX86State.cpuid_vendor{1,2,3} to string? > > > #define CPUID_VENDOR_AMD_1 0x68747541 /* "Auth" */ > > #define CPUID_VENDOR_AMD_2 0x69746e65 /* "enti" */ > > #define CPUID_VENDOR_AMD_3 0x444d4163 /* "cAMD" */ > > +#define CPUID_VENDOR_AMD "AuthenticAMD" > > > > -#define CPUID_VENDOR_VIA_1 0x746e6543 /* "Cent" */ > > -#define CPUID_VENDOR_VIA_2 0x48727561 /* "aurH" */ > > -#define CPUID_VENDOR_VIA_3 0x736c7561 /* "auls" */ > > +#define CPUID_VENDOR_VIA "CentaurHauls" > > > > #define CPUID_MWAIT_IBE (1 << 1) /* Interrupts can exit capability */ > > #define CPUID_MWAIT_EMX (1 << 0) /* enumeration supported */ > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] target-i386: replace uint32_t vendor fields by vendor string in x86_def_t 2013-01-18 13:40 ` Igor Mammedov @ 2013-01-21 3:16 ` li guang 0 siblings, 0 replies; 16+ messages in thread From: li guang @ 2013-01-21 3:16 UTC (permalink / raw) To: Igor Mammedov; +Cc: qemu-devel, afaerber, ehabkost 在 2013-01-18五的 14:40 +0100,Igor Mammedov写道: > On Fri, 18 Jan 2013 15:12:36 +0800 > li guang <lig.fnst@cn.fujitsu.com> wrote: > > > 在 2013-01-17四的 16:16 +0100,Igor Mammedov写道: > > > > > > > > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > > > index ce914da..ab80dbe 100644 > > > --- a/target-i386/cpu.c > > > +++ b/target-i386/cpu.c > > > @@ -45,6 +45,18 @@ > > > #include "hw/apic_internal.h" > > > #endif > > > > > > +static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, > > > + uint32_t vendor2, uint32_t vendor3) > > > > sorry, but I should say "_vendor_words2str" seems not so suitable, > > it's mostly not a convertor, but a compactor, so I suggest to use > > "_vendor_str" directly. > I think that "_vendor_words2str" describes more clearly what function does, > regardless whether it is conversion or compaction. "_vendor_str" seems more > ambiguous though. But if you insist, I can change to it. > No, "_vendor_words2str" is OK, though I still prefer "_vendor_str" stubbornly :) > BTW: it's not just copying, it copies from little endinan words to string. > > > > > > +{ > > > + int i; > > > + for (i = 0; i < 4; i++) { > > > + dst[i] = vendor1 >> (8 * i); > > > + dst[i + 4] = vendor2 >> (8 * i); > > > + dst[i + 8] = vendor3 >> (8 * i); > > > + } > > > + dst[CPUID_VENDOR_SZ] = '\0'; > > > +} > > > + > > > > > --- a/target-i386/cpu.h > > > +++ b/target-i386/cpu.h > > > @@ -537,14 +537,14 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; > > > #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */ > > > #define CPUID_VENDOR_INTEL_2 0x49656e69 /* "ineI" */ > > > #define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */ > > > +#define CPUID_VENDOR_INTEL "GenuineIntel" > > > > > > > you said the reason you did not remove _VENDOR_INTEL_{1,2,3} > > is they're used somewhere, did you mean "target-i386/translate.c" > > for sysenter instruction? > > if it is, why can't we also remove them there? > That would imply conversion of CPUX86State to using string for cpuid_vendor > instead of currents words which would mean to do conversion every time cpuid > instruction is called in guest. I'd rather keep current cpuid_vendor{1,2,3} > in CPUX86State. > > Purpose of this patch is to switch from direct field copying when initializing > CPU to using property setter. > If we ever decide to convert CPUX86State.cpuid_vendor{1,2,3} into string, it > could be done by a separate patch. > > In addition, wouldn't strcmp() there be less effective performance wise, > versus just number comparison if we would convert > CPUX86State.cpuid_vendor{1,2,3} to string? > that's true. Thanks! > > > > > #define CPUID_VENDOR_AMD_1 0x68747541 /* "Auth" */ > > > #define CPUID_VENDOR_AMD_2 0x69746e65 /* "enti" */ > > > #define CPUID_VENDOR_AMD_3 0x444d4163 /* "cAMD" */ > > > +#define CPUID_VENDOR_AMD "AuthenticAMD" > > > > > > -#define CPUID_VENDOR_VIA_1 0x746e6543 /* "Cent" */ > > > -#define CPUID_VENDOR_VIA_2 0x48727561 /* "aurH" */ > > > -#define CPUID_VENDOR_VIA_3 0x736c7561 /* "auls" */ > > > +#define CPUID_VENDOR_VIA "CentaurHauls" > > > > > > #define CPUID_MWAIT_IBE (1 << 1) /* Interrupts can exit capability */ > > > #define CPUID_MWAIT_EMX (1 << 0) /* enumeration supported */ > > > -- regards! li guang ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [PATCH 2/5] target-i386: replace uint32_t vendor fields by vendor string in x86_def_t 2013-01-17 15:16 ` [Qemu-devel] [PATCH 2/5] target-i386: replace uint32_t vendor fields by vendor string in x86_def_t Igor Mammedov 2013-01-17 15:29 ` Eduardo Habkost 2013-01-18 7:12 ` li guang @ 2013-01-21 8:18 ` Andreas Färber 2 siblings, 0 replies; 16+ messages in thread From: Andreas Färber @ 2013-01-21 8:18 UTC (permalink / raw) To: Igor Mammedov; +Cc: qemu-devel, ehabkost Am 17.01.2013 16:16, schrieb Igor Mammedov: > Vendor property setter takes string as vendor value but cpudefs > use uint32_t vendor[123] fields to define vendor value. It makes it > difficult to unify and use property setter for values from cpudefs. > > Simplify code by using vendor property setter, vendor[123] fields > are converted into vendor[13] array to keep its value. And vendor > property setter is used to access/set value on CPU. > > - Make for() cycle reusable for the next patch by adding > x86_cpu_vendor_words2str() > > Intel's CPUID spec[1] says: > " > 5.1.1 ... > These registers contain the ASCII string: GenuineIntel > ... > " > > List[2] of known vendor values shows that they all are 12 ASCII > characters long, padded where necessary with space > > Current supported values are all ASCII characters packed in > ebx, edx, ecx. So lets state that qemu supports 12 ASCII characters > packed in ebx, edx, ecx registers for cpuid(0) instruction. > > *1 - http://www.intel.com/Assets/PDF/appnote/241618.pdf > *2 - http://en.wikipedia.org/wiki/CPUID#EAX.3D0:_Get_vendor_ID > > Signed-off-by: Igor Mammedov <imammedo@redhat.com> So, hearing that my suggestion of a union to give us the best of both worlds did not work out well due to endianness conversions, I would still like to drop the vendor[0] assertion. And I spot no documentation for char vendor[...] in this patch, only in the commit message; we could spare that if we change char vendor[...] array to char *vendor, what do you think? Erroring out (or padding) could be done when setting it via "vendor" property onto X86CPU (maybe I'll try to cook up something for demonstration). Regards, Andreas -- SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg ^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 3/5] target-i386: remove vendor_override field from CPUX86State 2013-01-17 15:16 [Qemu-devel] [PATCH qom-cpu 0/5] x86 CPU cleanup, part 4 Igor Mammedov 2013-01-17 15:16 ` [Qemu-devel] [PATCH 1/5] target-i386: print deprecated warning if xlevel < 0x80000000 Igor Mammedov 2013-01-17 15:16 ` [Qemu-devel] [PATCH 2/5] target-i386: replace uint32_t vendor fields by vendor string in x86_def_t Igor Mammedov @ 2013-01-17 15:16 ` Igor Mammedov 2013-01-17 15:30 ` Eduardo Habkost 2013-01-17 15:16 ` [Qemu-devel] [PATCH 4/5] target-i386: set custom features/properties without intermediate x86_def_t Igor Mammedov 2013-01-17 15:16 ` [Qemu-devel] [PATCH 5/5] target-i386: remove setting tsc-frequency from x86_def_t Igor Mammedov 4 siblings, 1 reply; 16+ messages in thread From: Igor Mammedov @ 2013-01-17 15:16 UTC (permalink / raw) To: qemu-devel; +Cc: ehabkost, afaerber commit 8935499831312 makes cpuid return to guest host's vendor value instead of built-in one by default if kvm_enabled() == true and allows to override this behavior if 'vendor' is specified on -cpu command line. But every time guest calls cpuid to get 'vendor' value, host's value is read again and again in default case. It complicates semantic of vendor property and makes it harder to use. Instead of reading 'vendor' value from host every time cpuid[vendor] is called, override 'vendor' value only once in cpu_x86_find_by_name(), when built-in CPU model is found and if(kvm_enabled() == true). It provides the same default semantic if (kvm_enabled() == true) vendor = host's vendor else vendor = built-in vendor and then later: if (custom vendor) vendor = custom vendor 'vendor' value is overridden when user provides it on -cpu command line, and there isn't need in vendor_override field anymore, remove it. Signed-off-by: Igor Mammedov <imammedo@redhat.com> --- v4: - rebased with "target-i386: move out CPU features initialization in separate func" dropped. So remove vendor_override in cpu_x86_register() instead. - replace x86cpu_vendor_words2str() with x86_cpu_vendor_words2str() due to renaming of the last in previous patch --- target-i386/cpu.c | 27 ++++++++++++--------------- target-i386/cpu.h | 1 - 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index ab80dbe..5cd7917 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -362,7 +362,6 @@ typedef struct x86_def_t { uint32_t kvm_features, svm_features; uint32_t xlevel; char model_id[48]; - int vendor_override; /* Store the results of Centaur's CPUID instructions */ uint32_t ext4_features; uint32_t xlevel2; @@ -934,7 +933,6 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX); cpu_x86_fill_model_id(x86_cpu_def->model_id); - x86_cpu_def->vendor_override = 0; /* Call Centaur's CPUID instruction. */ if (!strncmp(x86_cpu_def->vendor, CPUID_VENDOR_VIA, @@ -1202,7 +1200,6 @@ static void x86_cpuid_set_vendor(Object *obj, const char *value, env->cpuid_vendor2 |= ((uint8_t)value[i + 4]) << (8 * i); env->cpuid_vendor3 |= ((uint8_t)value[i + 8]) << (8 * i); } - env->cpuid_vendor_override = 1; } static char *x86_cpuid_get_model_id(Object *obj, Error **errp) @@ -1288,6 +1285,18 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name) return -1; } else { memcpy(x86_cpu_def, def, sizeof(*def)); + /* sysenter isn't supported on compatibility mode on AMD, syscall + * isn't supported in compatibility mode on Intel. + * Normally we advertise the actual cpu vendor, but you can override + * this using the 'vendor' property if you want to use KVM's + * sysenter/syscall emulation in compatibility mode and when doing + * cross vendor migration + */ + if (kvm_enabled()) { + uint32_t ebx = 0, ecx = 0, edx = 0; + host_cpuid(0, 0, NULL, &ebx, &ecx, &edx); + x86_cpu_vendor_words2str(x86_cpu_def->vendor, ebx, edx, ecx); + } } return 0; @@ -1361,7 +1370,6 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) x86_cpu_def->xlevel = numvalue; } else if (!strcmp(featurestr, "vendor")) { pstrcpy(x86_cpu_def->vendor, sizeof(x86_cpu_def->vendor), val); - x86_cpu_def->vendor_override = 1; } else if (!strcmp(featurestr, "model_id")) { pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id), val); @@ -1557,7 +1565,6 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) } assert(def->vendor[0]); object_property_set_str(OBJECT(cpu), def->vendor, "vendor", &error); - env->cpuid_vendor_override = def->vendor_override; object_property_set_int(OBJECT(cpu), def->level, "level", &error); object_property_set_int(OBJECT(cpu), def->family, "family", &error); object_property_set_int(OBJECT(cpu), def->model, "model", &error); @@ -1629,16 +1636,6 @@ static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, *ebx = env->cpuid_vendor1; *edx = env->cpuid_vendor2; *ecx = env->cpuid_vendor3; - - /* sysenter isn't supported on compatibility mode on AMD, syscall - * isn't supported in compatibility mode on Intel. - * Normally we advertise the actual cpu vendor, but you can override - * this if you want to use KVM's sysenter/syscall emulation - * in compatibility mode and when doing cross vendor migration - */ - if (kvm_enabled() && ! env->cpuid_vendor_override) { - host_cpuid(0, 0, NULL, ebx, ecx, edx); - } } void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 554bd4a..53e1ea0 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -835,7 +835,6 @@ typedef struct CPUX86State { uint32_t cpuid_ext2_features; uint32_t cpuid_ext3_features; uint32_t cpuid_apic_id; - int cpuid_vendor_override; /* Store the results of Centaur's CPUID instructions */ uint32_t cpuid_xlevel2; uint32_t cpuid_ext4_features; -- 1.7.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [PATCH 3/5] target-i386: remove vendor_override field from CPUX86State 2013-01-17 15:16 ` [Qemu-devel] [PATCH 3/5] target-i386: remove vendor_override field from CPUX86State Igor Mammedov @ 2013-01-17 15:30 ` Eduardo Habkost 0 siblings, 0 replies; 16+ messages in thread From: Eduardo Habkost @ 2013-01-17 15:30 UTC (permalink / raw) To: Igor Mammedov; +Cc: qemu-devel, afaerber On Thu, Jan 17, 2013 at 04:16:32PM +0100, Igor Mammedov wrote: > commit 8935499831312 makes cpuid return to guest host's vendor value > instead of built-in one by default if kvm_enabled() == true and allows > to override this behavior if 'vendor' is specified on -cpu command line. > > But every time guest calls cpuid to get 'vendor' value, host's value is > read again and again in default case. > > It complicates semantic of vendor property and makes it harder to use. > > Instead of reading 'vendor' value from host every time cpuid[vendor] is > called, override 'vendor' value only once in cpu_x86_find_by_name(), when > built-in CPU model is found and if(kvm_enabled() == true). > > It provides the same default semantic > if (kvm_enabled() == true) vendor = host's vendor > else vendor = built-in vendor > > and then later: > if (custom vendor) vendor = custom vendor > > 'vendor' value is overridden when user provides it on -cpu command line, > and there isn't need in vendor_override field anymore, remove it. > > Signed-off-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> > --- > v4: > - rebased with "target-i386: move out CPU features initialization > in separate func" dropped. So remove vendor_override in > cpu_x86_register() instead. > - replace x86cpu_vendor_words2str() with x86_cpu_vendor_words2str() > due to renaming of the last in previous patch > --- > target-i386/cpu.c | 27 ++++++++++++--------------- > target-i386/cpu.h | 1 - > 2 files changed, 12 insertions(+), 16 deletions(-) > > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > index ab80dbe..5cd7917 100644 > --- a/target-i386/cpu.c > +++ b/target-i386/cpu.c > @@ -362,7 +362,6 @@ typedef struct x86_def_t { > uint32_t kvm_features, svm_features; > uint32_t xlevel; > char model_id[48]; > - int vendor_override; > /* Store the results of Centaur's CPUID instructions */ > uint32_t ext4_features; > uint32_t xlevel2; > @@ -934,7 +933,6 @@ static void kvm_cpu_fill_host(x86_def_t *x86_cpu_def) > kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_ECX); > > cpu_x86_fill_model_id(x86_cpu_def->model_id); > - x86_cpu_def->vendor_override = 0; > > /* Call Centaur's CPUID instruction. */ > if (!strncmp(x86_cpu_def->vendor, CPUID_VENDOR_VIA, > @@ -1202,7 +1200,6 @@ static void x86_cpuid_set_vendor(Object *obj, const char *value, > env->cpuid_vendor2 |= ((uint8_t)value[i + 4]) << (8 * i); > env->cpuid_vendor3 |= ((uint8_t)value[i + 8]) << (8 * i); > } > - env->cpuid_vendor_override = 1; > } > > static char *x86_cpuid_get_model_id(Object *obj, Error **errp) > @@ -1288,6 +1285,18 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name) > return -1; > } else { > memcpy(x86_cpu_def, def, sizeof(*def)); > + /* sysenter isn't supported on compatibility mode on AMD, syscall > + * isn't supported in compatibility mode on Intel. > + * Normally we advertise the actual cpu vendor, but you can override > + * this using the 'vendor' property if you want to use KVM's > + * sysenter/syscall emulation in compatibility mode and when doing > + * cross vendor migration > + */ > + if (kvm_enabled()) { > + uint32_t ebx = 0, ecx = 0, edx = 0; > + host_cpuid(0, 0, NULL, &ebx, &ecx, &edx); > + x86_cpu_vendor_words2str(x86_cpu_def->vendor, ebx, edx, ecx); > + } > } > > return 0; > @@ -1361,7 +1370,6 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) > x86_cpu_def->xlevel = numvalue; > } else if (!strcmp(featurestr, "vendor")) { > pstrcpy(x86_cpu_def->vendor, sizeof(x86_cpu_def->vendor), val); > - x86_cpu_def->vendor_override = 1; > } else if (!strcmp(featurestr, "model_id")) { > pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id), > val); > @@ -1557,7 +1565,6 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) > } > assert(def->vendor[0]); > object_property_set_str(OBJECT(cpu), def->vendor, "vendor", &error); > - env->cpuid_vendor_override = def->vendor_override; > object_property_set_int(OBJECT(cpu), def->level, "level", &error); > object_property_set_int(OBJECT(cpu), def->family, "family", &error); > object_property_set_int(OBJECT(cpu), def->model, "model", &error); > @@ -1629,16 +1636,6 @@ static void get_cpuid_vendor(CPUX86State *env, uint32_t *ebx, > *ebx = env->cpuid_vendor1; > *edx = env->cpuid_vendor2; > *ecx = env->cpuid_vendor3; > - > - /* sysenter isn't supported on compatibility mode on AMD, syscall > - * isn't supported in compatibility mode on Intel. > - * Normally we advertise the actual cpu vendor, but you can override > - * this if you want to use KVM's sysenter/syscall emulation > - * in compatibility mode and when doing cross vendor migration > - */ > - if (kvm_enabled() && ! env->cpuid_vendor_override) { > - host_cpuid(0, 0, NULL, ebx, ecx, edx); > - } > } > > void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, > diff --git a/target-i386/cpu.h b/target-i386/cpu.h > index 554bd4a..53e1ea0 100644 > --- a/target-i386/cpu.h > +++ b/target-i386/cpu.h > @@ -835,7 +835,6 @@ typedef struct CPUX86State { > uint32_t cpuid_ext2_features; > uint32_t cpuid_ext3_features; > uint32_t cpuid_apic_id; > - int cpuid_vendor_override; > /* Store the results of Centaur's CPUID instructions */ > uint32_t cpuid_xlevel2; > uint32_t cpuid_ext4_features; > -- > 1.7.1 > -- Eduardo ^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 4/5] target-i386: set custom features/properties without intermediate x86_def_t 2013-01-17 15:16 [Qemu-devel] [PATCH qom-cpu 0/5] x86 CPU cleanup, part 4 Igor Mammedov ` (2 preceding siblings ...) 2013-01-17 15:16 ` [Qemu-devel] [PATCH 3/5] target-i386: remove vendor_override field from CPUX86State Igor Mammedov @ 2013-01-17 15:16 ` Igor Mammedov 2013-01-17 17:44 ` Eduardo Habkost 2013-01-17 15:16 ` [Qemu-devel] [PATCH 5/5] target-i386: remove setting tsc-frequency from x86_def_t Igor Mammedov 4 siblings, 1 reply; 16+ messages in thread From: Igor Mammedov @ 2013-01-17 15:16 UTC (permalink / raw) To: qemu-devel; +Cc: ehabkost, afaerber Move custom features parsing after built-in cpu_model defaults are set and set custom features directly on CPU instance. That allows to make clear distinction between built-in cpu model defaults that eventually should go into clas_init() and extra property setting which is done after defaults are set on CPU instance. Impl. details: - features that are already properties, are converted to normalized (name, values) list. And after featurestr has been parsed, properties from the list are applied directly to CPU instance. * For now it provides uniform handling of properties with single object_property_parse() property setter. * And after current features/properties are converted into static properties, it will take a trivial patch to switch to global properties. Which will allow to: * get CPU instance initialized with all parameters passed on -cpu ... cmd. line from object_new() call. * call cpu_model/featurestr parsing only once before CPUs are created * open a road for removing CPUxxxState.cpu_model_str field, when other CPUs are similarly converted to subclasses and static properties. - re-factor error handling, to use Error instead of fprintf()s, since it is anyway passed in for property setter. Signed-off-by: Igor Mammedov <imammedo@redhat.com> --- target-i386/cpu.c | 144 ++++++++++++++++++++++++++++------------------------- 1 files changed, 77 insertions(+), 67 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 5cd7917..50e10b1 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1302,9 +1302,24 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name) return 0; } +typedef struct NameValuePair { + char *name; + char *value; + QTAILQ_ENTRY(NameValuePair) next; +} NameValuePair; +typedef QTAILQ_HEAD(NVList, NameValuePair) NVList; + +static void x86_cpu_add_nv_pair(NVList *list, const char *name, + const char *value) { + NameValuePair *p = g_malloc0(sizeof(*p)); + p->name = g_strdup(name); + p->value = g_strdup(value); + QTAILQ_INSERT_TAIL(list, p, next); +} + /* Parse "+feature,-feature,feature=foo" CPU feature string */ -static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) +static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp) { char *featurestr; /* Single 'key=value" string being parsed */ /* Features to be added */ @@ -1312,6 +1327,9 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) /* Features to be removed */ FeatureWordArray minus_features = { 0 }; uint32_t numvalue; + CPUX86State *env = &cpu->env; + NVList props = QTAILQ_HEAD_INITIALIZER(props); + NameValuePair *p, *tmp; featurestr = features ? strtok(features, ",") : NULL; @@ -1324,77 +1342,57 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) } else if ((val = strchr(featurestr, '='))) { *val = 0; val++; if (!strcmp(featurestr, "family")) { - char *err; - numvalue = strtoul(val, &err, 0); - if (!*val || *err || numvalue > 0xff + 0xf) { - fprintf(stderr, "bad numerical value %s\n", val); - goto error; - } - x86_cpu_def->family = numvalue; + x86_cpu_add_nv_pair(&props, featurestr, val); } else if (!strcmp(featurestr, "model")) { - char *err; - numvalue = strtoul(val, &err, 0); - if (!*val || *err || numvalue > 0xff) { - fprintf(stderr, "bad numerical value %s\n", val); - goto error; - } - x86_cpu_def->model = numvalue; + x86_cpu_add_nv_pair(&props, featurestr, val); } else if (!strcmp(featurestr, "stepping")) { - char *err; - numvalue = strtoul(val, &err, 0); - if (!*val || *err || numvalue > 0xf) { - fprintf(stderr, "bad numerical value %s\n", val); - goto error; - } - x86_cpu_def->stepping = numvalue ; + x86_cpu_add_nv_pair(&props, featurestr, val); } else if (!strcmp(featurestr, "level")) { - char *err; - numvalue = strtoul(val, &err, 0); - if (!*val || *err) { - fprintf(stderr, "bad numerical value %s\n", val); - goto error; - } - x86_cpu_def->level = numvalue; + x86_cpu_add_nv_pair(&props, featurestr, val); } else if (!strcmp(featurestr, "xlevel")) { char *err; + char num[32]; + numvalue = strtoul(val, &err, 0); if (!*val || *err) { - fprintf(stderr, "bad numerical value %s\n", val); - goto error; + error_setg(errp, "bad numerical value %s\n", val); + goto out; } if (numvalue < 0x80000000) { fprintf(stderr, "xlevel value shall always be >= 0x80000000" ", fixup will be deprecated in future versions\n"); numvalue += 0x80000000; } - x86_cpu_def->xlevel = numvalue; + snprintf(num, sizeof(num), "%" PRIu32, numvalue); + x86_cpu_add_nv_pair(&props, featurestr, num); } else if (!strcmp(featurestr, "vendor")) { - pstrcpy(x86_cpu_def->vendor, sizeof(x86_cpu_def->vendor), val); + x86_cpu_add_nv_pair(&props, featurestr, val); } else if (!strcmp(featurestr, "model_id")) { - pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id), - val); + x86_cpu_add_nv_pair(&props, "model-id", val); } else if (!strcmp(featurestr, "tsc_freq")) { int64_t tsc_freq; char *err; + char num[32]; tsc_freq = strtosz_suffix_unit(val, &err, STRTOSZ_DEFSUFFIX_B, 1000); if (tsc_freq < 0 || *err) { - fprintf(stderr, "bad numerical value %s\n", val); - goto error; + error_setg(errp, "bad numerical value %s\n", val); + goto out; } - x86_cpu_def->tsc_khz = tsc_freq / 1000; + snprintf(num, sizeof(num), "%" PRId64, tsc_freq); + x86_cpu_add_nv_pair(&props, "tsc-frequency", num); } else if (!strcmp(featurestr, "hv_spinlocks")) { char *err; numvalue = strtoul(val, &err, 0); if (!*val || *err) { - fprintf(stderr, "bad numerical value %s\n", val); - goto error; + error_setg(errp, "bad numerical value %s\n", val); + goto out; } hyperv_set_spinlock_retries(numvalue); } else { - fprintf(stderr, "unrecognized feature %s\n", featurestr); - goto error; + error_setg(errp, "unrecognized feature %s\n", featurestr); + goto out; } } else if (!strcmp(featurestr, "check")) { check_cpuid = 1; @@ -1405,31 +1403,46 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) } else if (!strcmp(featurestr, "hv_vapic")) { hyperv_enable_vapic_recommended(true); } else { - fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr); - goto error; + error_setg(errp, "feature string `%s' not in format (+feature|" + "-feature|feature=xyz)\n", featurestr); + goto out; } featurestr = strtok(NULL, ","); } - x86_cpu_def->features |= plus_features[FEAT_1_EDX]; - x86_cpu_def->ext_features |= plus_features[FEAT_1_ECX]; - x86_cpu_def->ext2_features |= plus_features[FEAT_8000_0001_EDX]; - x86_cpu_def->ext3_features |= plus_features[FEAT_8000_0001_ECX]; - x86_cpu_def->ext4_features |= plus_features[FEAT_C000_0001_EDX]; - x86_cpu_def->kvm_features |= plus_features[FEAT_KVM]; - x86_cpu_def->svm_features |= plus_features[FEAT_SVM]; - x86_cpu_def->cpuid_7_0_ebx_features |= plus_features[FEAT_7_0_EBX]; - x86_cpu_def->features &= ~minus_features[FEAT_1_EDX]; - x86_cpu_def->ext_features &= ~minus_features[FEAT_1_ECX]; - x86_cpu_def->ext2_features &= ~minus_features[FEAT_8000_0001_EDX]; - x86_cpu_def->ext3_features &= ~minus_features[FEAT_8000_0001_ECX]; - x86_cpu_def->ext4_features &= ~minus_features[FEAT_C000_0001_EDX]; - x86_cpu_def->kvm_features &= ~minus_features[FEAT_KVM]; - x86_cpu_def->svm_features &= ~minus_features[FEAT_SVM]; - x86_cpu_def->cpuid_7_0_ebx_features &= ~minus_features[FEAT_7_0_EBX]; - return 0; + env->cpuid_features |= plus_features[FEAT_1_EDX]; + env->cpuid_ext_features |= plus_features[FEAT_1_ECX]; + env->cpuid_ext2_features |= plus_features[FEAT_8000_0001_EDX]; + env->cpuid_ext3_features |= plus_features[FEAT_8000_0001_ECX]; + env->cpuid_ext4_features |= plus_features[FEAT_C000_0001_EDX]; + env->cpuid_kvm_features |= plus_features[FEAT_KVM]; + env->cpuid_svm_features |= plus_features[FEAT_SVM]; + env->cpuid_7_0_ebx_features |= plus_features[FEAT_7_0_EBX]; + env->cpuid_features &= ~minus_features[FEAT_1_EDX]; + env->cpuid_ext_features &= ~minus_features[FEAT_1_ECX]; + env->cpuid_ext2_features &= ~minus_features[FEAT_8000_0001_EDX]; + env->cpuid_ext3_features &= ~minus_features[FEAT_8000_0001_ECX]; + env->cpuid_ext4_features &= ~minus_features[FEAT_C000_0001_EDX]; + env->cpuid_kvm_features &= ~minus_features[FEAT_KVM]; + env->cpuid_svm_features &= ~minus_features[FEAT_SVM]; + env->cpuid_7_0_ebx_features &= ~minus_features[FEAT_7_0_EBX]; + + /* Set features on X86CPU object based on a provided key,value list */ + QTAILQ_FOREACH_SAFE(p, &props, next, tmp) { + /* TODO: switch to using global properties after subclasses and + * static properties are done */ + object_property_parse(OBJECT(cpu), p->value, p->name, errp); + if (error_is_set(errp)) { + goto out; + } + } -error: - return -1; +out: + QTAILQ_FOREACH_SAFE(p, &props, next, tmp) { + QTAILQ_REMOVE(&props, p, next); + g_free(p->value); + g_free(p->name); + g_free(p); + } } /* generate a composite string into buf of all cpuid names in featureset @@ -1559,10 +1572,6 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) def->kvm_features |= kvm_default_features; def->ext_features |= CPUID_EXT_HYPERVISOR; - if (cpu_x86_parse_featurestr(def, features) < 0) { - error_setg(&error, "Invalid cpu_model string format: %s", cpu_model); - goto out; - } assert(def->vendor[0]); object_property_set_str(OBJECT(cpu), def->vendor, "vendor", &error); object_property_set_int(OBJECT(cpu), def->level, "level", &error); @@ -1584,6 +1593,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); + cpu_x86_parse_featurestr(cpu, features, &error); out: g_strfreev(model_pieces); if (error) { -- 1.7.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [PATCH 4/5] target-i386: set custom features/properties without intermediate x86_def_t 2013-01-17 15:16 ` [Qemu-devel] [PATCH 4/5] target-i386: set custom features/properties without intermediate x86_def_t Igor Mammedov @ 2013-01-17 17:44 ` Eduardo Habkost 2013-01-18 14:49 ` Igor Mammedov 0 siblings, 1 reply; 16+ messages in thread From: Eduardo Habkost @ 2013-01-17 17:44 UTC (permalink / raw) To: Igor Mammedov; +Cc: qemu-devel, afaerber On Thu, Jan 17, 2013 at 04:16:33PM +0100, Igor Mammedov wrote: > Move custom features parsing after built-in cpu_model defaults are set > and set custom features directly on CPU instance. That allows to make > clear distinction between built-in cpu model defaults that eventually > should go into clas_init() and extra property setting which is done > after defaults are set on CPU instance. > > Impl. details: > - features that are already properties, are converted to normalized > (name, values) list. And after featurestr has been parsed, > properties from the list are applied directly to CPU instance. > * For now it provides uniform handling of properties with single > object_property_parse() property setter. > * And after current features/properties are converted into static > properties, it will take a trivial patch to switch to global properties. > Which will allow to: > * get CPU instance initialized with all parameters passed on -cpu ... > cmd. line from object_new() call. > * call cpu_model/featurestr parsing only once before CPUs are created > * open a road for removing CPUxxxState.cpu_model_str field, when other > CPUs are similarly converted to subclasses and static properties. > - re-factor error handling, to use Error instead of fprintf()s, since > it is anyway passed in for property setter. > > Signed-off-by: Igor Mammedov <imammedo@redhat.com> > --- > target-i386/cpu.c | 144 ++++++++++++++++++++++++++++------------------------- > 1 files changed, 77 insertions(+), 67 deletions(-) > > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > index 5cd7917..50e10b1 100644 > --- a/target-i386/cpu.c > +++ b/target-i386/cpu.c > @@ -1302,9 +1302,24 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *name) > return 0; > } > > +typedef struct NameValuePair { > + char *name; > + char *value; > + QTAILQ_ENTRY(NameValuePair) next; > +} NameValuePair; > +typedef QTAILQ_HEAD(NVList, NameValuePair) NVList; > + > +static void x86_cpu_add_nv_pair(NVList *list, const char *name, > + const char *value) { > + NameValuePair *p = g_malloc0(sizeof(*p)); > + p->name = g_strdup(name); > + p->value = g_strdup(value); > + QTAILQ_INSERT_TAIL(list, p, next); > +} I am not sure I like this extra complexity. We don't need it if we simply set/register the properties directly. I have a different proposal: 1) By now, use: object_property_parse(OBJECT(cpu), P, V, errp) in the places you are using: x86_cpu_add_nv_pair(&props, P, V) below. 2) The day we move to global properties, we just need to mechanically replace the occurrences of: object_property_parse(OBJECT(cpu), P, V, errp) with: qdev_prop_register_global("X86CPU", P, V) What do you think? > + object_property_parse(OBJECT(cpu), p->value, p->name, errp); > + > /* Parse "+feature,-feature,feature=foo" CPU feature string > */ > -static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) > +static void cpu_x86_parse_featurestr(X86CPU *cpu, char *features, Error **errp) > { > char *featurestr; /* Single 'key=value" string being parsed */ > /* Features to be added */ > @@ -1312,6 +1327,9 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) > /* Features to be removed */ > FeatureWordArray minus_features = { 0 }; > uint32_t numvalue; > + CPUX86State *env = &cpu->env; > + NVList props = QTAILQ_HEAD_INITIALIZER(props); > + NameValuePair *p, *tmp; > > featurestr = features ? strtok(features, ",") : NULL; > > @@ -1324,77 +1342,57 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) > } else if ((val = strchr(featurestr, '='))) { > *val = 0; val++; > if (!strcmp(featurestr, "family")) { > - char *err; > - numvalue = strtoul(val, &err, 0); > - if (!*val || *err || numvalue > 0xff + 0xf) { > - fprintf(stderr, "bad numerical value %s\n", val); > - goto error; > - } > - x86_cpu_def->family = numvalue; > + x86_cpu_add_nv_pair(&props, featurestr, val); > } else if (!strcmp(featurestr, "model")) { > - char *err; > - numvalue = strtoul(val, &err, 0); > - if (!*val || *err || numvalue > 0xff) { > - fprintf(stderr, "bad numerical value %s\n", val); > - goto error; > - } > - x86_cpu_def->model = numvalue; > + x86_cpu_add_nv_pair(&props, featurestr, val); > } else if (!strcmp(featurestr, "stepping")) { > - char *err; > - numvalue = strtoul(val, &err, 0); > - if (!*val || *err || numvalue > 0xf) { > - fprintf(stderr, "bad numerical value %s\n", val); > - goto error; > - } > - x86_cpu_def->stepping = numvalue ; > + x86_cpu_add_nv_pair(&props, featurestr, val); > } else if (!strcmp(featurestr, "level")) { > - char *err; > - numvalue = strtoul(val, &err, 0); > - if (!*val || *err) { > - fprintf(stderr, "bad numerical value %s\n", val); > - goto error; > - } > - x86_cpu_def->level = numvalue; > + x86_cpu_add_nv_pair(&props, featurestr, val); > } else if (!strcmp(featurestr, "xlevel")) { > char *err; > + char num[32]; > + > numvalue = strtoul(val, &err, 0); > if (!*val || *err) { > - fprintf(stderr, "bad numerical value %s\n", val); > - goto error; > + error_setg(errp, "bad numerical value %s\n", val); > + goto out; > } > if (numvalue < 0x80000000) { > fprintf(stderr, "xlevel value shall always be >= 0x80000000" > ", fixup will be deprecated in future versions\n"); > numvalue += 0x80000000; > } > - x86_cpu_def->xlevel = numvalue; > + snprintf(num, sizeof(num), "%" PRIu32, numvalue); > + x86_cpu_add_nv_pair(&props, featurestr, num); > } else if (!strcmp(featurestr, "vendor")) { > - pstrcpy(x86_cpu_def->vendor, sizeof(x86_cpu_def->vendor), val); > + x86_cpu_add_nv_pair(&props, featurestr, val); > } else if (!strcmp(featurestr, "model_id")) { > - pstrcpy(x86_cpu_def->model_id, sizeof(x86_cpu_def->model_id), > - val); > + x86_cpu_add_nv_pair(&props, "model-id", val); > } else if (!strcmp(featurestr, "tsc_freq")) { > int64_t tsc_freq; > char *err; > + char num[32]; > > tsc_freq = strtosz_suffix_unit(val, &err, > STRTOSZ_DEFSUFFIX_B, 1000); > if (tsc_freq < 0 || *err) { > - fprintf(stderr, "bad numerical value %s\n", val); > - goto error; > + error_setg(errp, "bad numerical value %s\n", val); > + goto out; > } > - x86_cpu_def->tsc_khz = tsc_freq / 1000; > + snprintf(num, sizeof(num), "%" PRId64, tsc_freq); > + x86_cpu_add_nv_pair(&props, "tsc-frequency", num); > } else if (!strcmp(featurestr, "hv_spinlocks")) { > char *err; > numvalue = strtoul(val, &err, 0); > if (!*val || *err) { > - fprintf(stderr, "bad numerical value %s\n", val); > - goto error; > + error_setg(errp, "bad numerical value %s\n", val); > + goto out; > } > hyperv_set_spinlock_retries(numvalue); > } else { > - fprintf(stderr, "unrecognized feature %s\n", featurestr); > - goto error; > + error_setg(errp, "unrecognized feature %s\n", featurestr); > + goto out; > } > } else if (!strcmp(featurestr, "check")) { > check_cpuid = 1; > @@ -1405,31 +1403,46 @@ static int cpu_x86_parse_featurestr(x86_def_t *x86_cpu_def, char *features) > } else if (!strcmp(featurestr, "hv_vapic")) { > hyperv_enable_vapic_recommended(true); > } else { > - fprintf(stderr, "feature string `%s' not in format (+feature|-feature|feature=xyz)\n", featurestr); > - goto error; > + error_setg(errp, "feature string `%s' not in format (+feature|" > + "-feature|feature=xyz)\n", featurestr); > + goto out; > } > featurestr = strtok(NULL, ","); > } > - x86_cpu_def->features |= plus_features[FEAT_1_EDX]; > - x86_cpu_def->ext_features |= plus_features[FEAT_1_ECX]; > - x86_cpu_def->ext2_features |= plus_features[FEAT_8000_0001_EDX]; > - x86_cpu_def->ext3_features |= plus_features[FEAT_8000_0001_ECX]; > - x86_cpu_def->ext4_features |= plus_features[FEAT_C000_0001_EDX]; > - x86_cpu_def->kvm_features |= plus_features[FEAT_KVM]; > - x86_cpu_def->svm_features |= plus_features[FEAT_SVM]; > - x86_cpu_def->cpuid_7_0_ebx_features |= plus_features[FEAT_7_0_EBX]; > - x86_cpu_def->features &= ~minus_features[FEAT_1_EDX]; > - x86_cpu_def->ext_features &= ~minus_features[FEAT_1_ECX]; > - x86_cpu_def->ext2_features &= ~minus_features[FEAT_8000_0001_EDX]; > - x86_cpu_def->ext3_features &= ~minus_features[FEAT_8000_0001_ECX]; > - x86_cpu_def->ext4_features &= ~minus_features[FEAT_C000_0001_EDX]; > - x86_cpu_def->kvm_features &= ~minus_features[FEAT_KVM]; > - x86_cpu_def->svm_features &= ~minus_features[FEAT_SVM]; > - x86_cpu_def->cpuid_7_0_ebx_features &= ~minus_features[FEAT_7_0_EBX]; > - return 0; > + env->cpuid_features |= plus_features[FEAT_1_EDX]; > + env->cpuid_ext_features |= plus_features[FEAT_1_ECX]; > + env->cpuid_ext2_features |= plus_features[FEAT_8000_0001_EDX]; > + env->cpuid_ext3_features |= plus_features[FEAT_8000_0001_ECX]; > + env->cpuid_ext4_features |= plus_features[FEAT_C000_0001_EDX]; > + env->cpuid_kvm_features |= plus_features[FEAT_KVM]; > + env->cpuid_svm_features |= plus_features[FEAT_SVM]; > + env->cpuid_7_0_ebx_features |= plus_features[FEAT_7_0_EBX]; > + env->cpuid_features &= ~minus_features[FEAT_1_EDX]; > + env->cpuid_ext_features &= ~minus_features[FEAT_1_ECX]; > + env->cpuid_ext2_features &= ~minus_features[FEAT_8000_0001_EDX]; > + env->cpuid_ext3_features &= ~minus_features[FEAT_8000_0001_ECX]; > + env->cpuid_ext4_features &= ~minus_features[FEAT_C000_0001_EDX]; > + env->cpuid_kvm_features &= ~minus_features[FEAT_KVM]; > + env->cpuid_svm_features &= ~minus_features[FEAT_SVM]; > + env->cpuid_7_0_ebx_features &= ~minus_features[FEAT_7_0_EBX]; > + > + /* Set features on X86CPU object based on a provided key,value list */ > + QTAILQ_FOREACH_SAFE(p, &props, next, tmp) { > + /* TODO: switch to using global properties after subclasses and > + * static properties are done */ > + object_property_parse(OBJECT(cpu), p->value, p->name, errp); > + if (error_is_set(errp)) { > + goto out; > + } > + } > > -error: > - return -1; > +out: > + QTAILQ_FOREACH_SAFE(p, &props, next, tmp) { > + QTAILQ_REMOVE(&props, p, next); > + g_free(p->value); > + g_free(p->name); > + g_free(p); > + } > } > > /* generate a composite string into buf of all cpuid names in featureset > @@ -1559,10 +1572,6 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) > def->kvm_features |= kvm_default_features; > def->ext_features |= CPUID_EXT_HYPERVISOR; > > - if (cpu_x86_parse_featurestr(def, features) < 0) { > - error_setg(&error, "Invalid cpu_model string format: %s", cpu_model); > - goto out; > - } > assert(def->vendor[0]); > object_property_set_str(OBJECT(cpu), def->vendor, "vendor", &error); > object_property_set_int(OBJECT(cpu), def->level, "level", &error); > @@ -1584,6 +1593,7 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) > > object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); > > + cpu_x86_parse_featurestr(cpu, features, &error); > out: > g_strfreev(model_pieces); > if (error) { > -- > 1.7.1 > -- Eduardo ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Qemu-devel] [PATCH 4/5] target-i386: set custom features/properties without intermediate x86_def_t 2013-01-17 17:44 ` Eduardo Habkost @ 2013-01-18 14:49 ` Igor Mammedov 0 siblings, 0 replies; 16+ messages in thread From: Igor Mammedov @ 2013-01-18 14:49 UTC (permalink / raw) To: Eduardo Habkost; +Cc: qemu-devel, afaerber On Thu, 17 Jan 2013 15:44:45 -0200 Eduardo Habkost <ehabkost@redhat.com> wrote: > On Thu, Jan 17, 2013 at 04:16:33PM +0100, Igor Mammedov wrote: > > Move custom features parsing after built-in cpu_model defaults are set > > and set custom features directly on CPU instance. That allows to make > > clear distinction between built-in cpu model defaults that eventually > > should go into clas_init() and extra property setting which is done > > after defaults are set on CPU instance. > > > > Impl. details: > > - features that are already properties, are converted to normalized > > (name, values) list. And after featurestr has been parsed, > > properties from the list are applied directly to CPU instance. > > * For now it provides uniform handling of properties with single > > object_property_parse() property setter. > > * And after current features/properties are converted into static > > properties, it will take a trivial patch to switch to global > > properties. Which will allow to: > > * get CPU instance initialized with all parameters passed on -cpu ... > > cmd. line from object_new() call. > > * call cpu_model/featurestr parsing only once before CPUs are created > > * open a road for removing CPUxxxState.cpu_model_str field, when > > other CPUs are similarly converted to subclasses and static properties. > > - re-factor error handling, to use Error instead of fprintf()s, since > > it is anyway passed in for property setter. > > > > Signed-off-by: Igor Mammedov <imammedo@redhat.com> > > --- > > target-i386/cpu.c | 144 > > ++++++++++++++++++++++++++++------------------------- 1 files changed, 77 > > insertions(+), 67 deletions(-) > > > > diff --git a/target-i386/cpu.c b/target-i386/cpu.c > > index 5cd7917..50e10b1 100644 > > --- a/target-i386/cpu.c > > +++ b/target-i386/cpu.c > > @@ -1302,9 +1302,24 @@ static int cpu_x86_find_by_name(x86_def_t > > *x86_cpu_def, const char *name) return 0; > > } > > > > +typedef struct NameValuePair { > > + char *name; > > + char *value; > > + QTAILQ_ENTRY(NameValuePair) next; > > +} NameValuePair; > > +typedef QTAILQ_HEAD(NVList, NameValuePair) NVList; > > + > > +static void x86_cpu_add_nv_pair(NVList *list, const char *name, > > + const char *value) { > > + NameValuePair *p = g_malloc0(sizeof(*p)); > > + p->name = g_strdup(name); > > + p->value = g_strdup(value); > > + QTAILQ_INSERT_TAIL(list, p, next); > > +} > > I am not sure I like this extra complexity. We don't need it if we > simply set/register the properties directly. > > I have a different proposal: > > 1) By now, use: > object_property_parse(OBJECT(cpu), P, V, errp) > in the places you are using: > x86_cpu_add_nv_pair(&props, P, V) > below. > > 2) The day we move to global properties, we just need to mechanically > replace the occurrences of: > object_property_parse(OBJECT(cpu), P, V, errp) > with: > qdev_prop_register_global("X86CPU", P, V) > > What do you think? Agreed, changes, when switching to global properties, will be mechanical and not in many places, so it makes sense to drop list approach. I'll resubmit series. > > > > + object_property_parse(OBJECT(cpu), p->value, p->name, errp); > > + > > /* Parse "+feature,-feature,feature=foo" CPU feature string > > */ [...] ^ permalink raw reply [flat|nested] 16+ messages in thread
* [Qemu-devel] [PATCH 5/5] target-i386: remove setting tsc-frequency from x86_def_t 2013-01-17 15:16 [Qemu-devel] [PATCH qom-cpu 0/5] x86 CPU cleanup, part 4 Igor Mammedov ` (3 preceding siblings ...) 2013-01-17 15:16 ` [Qemu-devel] [PATCH 4/5] target-i386: set custom features/properties without intermediate x86_def_t Igor Mammedov @ 2013-01-17 15:16 ` Igor Mammedov 4 siblings, 0 replies; 16+ messages in thread From: Igor Mammedov @ 2013-01-17 15:16 UTC (permalink / raw) To: qemu-devel; +Cc: ehabkost, afaerber Setting tsc-frequency from x86_def_t is NOP because default tsc_khz in x86_def_t is 0 and CPUX86State.tsc_khz is also initialized to 0 by default. So there is not need to set ovewrite tsc_khz with default 0 because field was already initialized to 0. custom tsc-frequency setting is not affected due to it is being set without using x86_def_t (previous patch) Field tsc_khz in x86_def_t becomes unused with this patch, so drop it as well. Signed-off-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> --- v2: - rebased with "target-i386: move out CPU features initialization in separate func" patch dropped --- target-i386/cpu.c | 3 --- 1 files changed, 0 insertions(+), 3 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 50e10b1..cc20ada 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -357,7 +357,6 @@ typedef struct x86_def_t { int family; int model; int stepping; - int tsc_khz; uint32_t features, ext_features, ext2_features, ext3_features; uint32_t kvm_features, svm_features; uint32_t xlevel; @@ -1588,8 +1587,6 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) env->cpuid_ext4_features = def->ext4_features; env->cpuid_7_0_ebx_features = def->cpuid_7_0_ebx_features; env->cpuid_xlevel2 = def->xlevel2; - object_property_set_int(OBJECT(cpu), (int64_t)def->tsc_khz * 1000, - "tsc-frequency", &error); object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); -- 1.7.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
end of thread, other threads:[~2013-01-21 12:14 UTC | newest] Thread overview: 16+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-01-17 15:16 [Qemu-devel] [PATCH qom-cpu 0/5] x86 CPU cleanup, part 4 Igor Mammedov 2013-01-17 15:16 ` [Qemu-devel] [PATCH 1/5] target-i386: print deprecated warning if xlevel < 0x80000000 Igor Mammedov 2013-01-21 8:39 ` Andreas Färber 2013-01-21 12:14 ` Igor Mammedov 2013-01-17 15:16 ` [Qemu-devel] [PATCH 2/5] target-i386: replace uint32_t vendor fields by vendor string in x86_def_t Igor Mammedov 2013-01-17 15:29 ` Eduardo Habkost 2013-01-18 7:12 ` li guang 2013-01-18 13:40 ` Igor Mammedov 2013-01-21 3:16 ` li guang 2013-01-21 8:18 ` Andreas Färber 2013-01-17 15:16 ` [Qemu-devel] [PATCH 3/5] target-i386: remove vendor_override field from CPUX86State Igor Mammedov 2013-01-17 15:30 ` Eduardo Habkost 2013-01-17 15:16 ` [Qemu-devel] [PATCH 4/5] target-i386: set custom features/properties without intermediate x86_def_t Igor Mammedov 2013-01-17 17:44 ` Eduardo Habkost 2013-01-18 14:49 ` Igor Mammedov 2013-01-17 15:16 ` [Qemu-devel] [PATCH 5/5] target-i386: remove setting tsc-frequency from x86_def_t Igor Mammedov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).