x86/cpu: Improvements to get_cpu_vendor()
authorAndrew Cooper <andrew.cooper3@citrix.com>
Fri, 16 Dec 2016 17:36:22 +0000 (17:36 +0000)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 3 Jan 2017 13:33:16 +0000 (13:33 +0000)
Comparing 3 integers is more efficient than using strcmp(), and is more useful
to the gcv_guest case than having to fabricate a suitable string to pass.  The
gcv_host cases have both options easily to hand, and experimentally, the
resulting code is more efficient.

Update the cpu_dev structure to be more efficient.  c_vendor[] only needs to
be 8 bytes long to cover all the CPU drivers Xen has, which avoids storing an
8-byte pointer to 8 bytes of data.  Drop c_ident[1] as we have no CPU drivers
with a second ident string, and turn it into an anonymous union to allow
access to the integer values directly.

This avoids all need for the vendor_id union in update_domain_cpuid_info().

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/cpu/common.c
xen/arch/x86/cpu/cpu.h
xen/arch/x86/domctl.c
xen/include/asm-x86/processor.h

index 537ad356ad3ddfe232d9331712297827d0918ffe..d17a2ee05be2f9e4a2e3318db4020fa23d0e2260 100644 (file)
@@ -156,16 +156,15 @@ void display_cacheinfo(struct cpuinfo_x86 *c)
                       l2size, ecx & 0xFF);
 }
 
-int get_cpu_vendor(const char v[], enum get_cpu_vendor mode)
+int get_cpu_vendor(uint32_t b, uint32_t c, uint32_t d, enum get_cpu_vendor mode)
 {
        int i;
        static int printed;
 
        for (i = 0; i < X86_VENDOR_NUM; i++) {
                if (cpu_devs[i]) {
-                       if (!strcmp(v,cpu_devs[i]->c_ident[0]) ||
-                           (cpu_devs[i]->c_ident[1] && 
-                            !strcmp(v,cpu_devs[i]->c_ident[1]))) {
+                       if (cpu_devs[i]->b == b && cpu_devs[i]->c == c &&
+                           cpu_devs[i]->d == d) {
                                if (mode == gcv_host)
                                        this_cpu = cpu_devs[i];
                                return i;
@@ -234,12 +233,12 @@ static void __init early_cpu_detect(void)
        c->x86_cache_alignment = 32;
 
        /* Get vendor name */
-       cpuid(0x00000000, &c->cpuid_level,
-             (int *)&c->x86_vendor_id[0],
-             (int *)&c->x86_vendor_id[8],
-             (int *)&c->x86_vendor_id[4]);
+       cpuid(0x00000000, &c->cpuid_level, &ebx, &ecx, &edx);
+       *(u32 *)&c->x86_vendor_id[0] = ebx;
+       *(u32 *)&c->x86_vendor_id[8] = ecx;
+       *(u32 *)&c->x86_vendor_id[4] = edx;
 
-       c->x86_vendor = get_cpu_vendor(c->x86_vendor_id, gcv_host);
+       c->x86_vendor = get_cpu_vendor(ebx, ecx, edx, gcv_host);
 
        cpuid(0x00000001, &eax, &ebx, &ecx, &edx);
        c->x86 = get_cpu_family(eax, &c->x86_model, &c->x86_mask);
@@ -277,12 +276,12 @@ static void generic_identify(struct cpuinfo_x86 *c)
        u32 eax, ebx, ecx, edx, tmp;
 
        /* Get vendor name */
-       cpuid(0x00000000, &c->cpuid_level,
-             (int *)&c->x86_vendor_id[0],
-             (int *)&c->x86_vendor_id[8],
-             (int *)&c->x86_vendor_id[4]);
+       cpuid(0x00000000, &c->cpuid_level, &ebx, &ecx, &edx);
+       *(u32 *)&c->x86_vendor_id[0] = ebx;
+       *(u32 *)&c->x86_vendor_id[8] = ecx;
+       *(u32 *)&c->x86_vendor_id[4] = edx;
 
-       c->x86_vendor = get_cpu_vendor(c->x86_vendor_id, gcv_host);
+       c->x86_vendor = get_cpu_vendor(ebx, ecx, edx, gcv_host);
        /* Initialize the standard set of capabilities */
        /* Note that the vendor-specific code below might override */
 
index 1877e7d0071405debbf83c968468c3c7dc1313d5..5a7905c31a9e8f43b4bcf7f8e44917207e70f9b2 100644 (file)
@@ -1,9 +1,13 @@
 /* attempt to consolidate cpu attributes */
 struct cpu_dev {
-       char    * c_vendor;
+       char    c_vendor[8];
 
-       /* some have two possibilities for cpuid string */
-       char    * c_ident[2];   
+       union {
+               char    c_ident[13];
+               struct {
+                       uint32_t b, d, c;
+               };
+       };
 
        void            (*c_early_init)(struct cpuinfo_x86 *c);
        void            (*c_init)(struct cpuinfo_x86 * c);
index ab9ad395386348adda51098e44211e10bf4445c8..eb71c9ebd919d99f933c560daef1e5c5899fa59a 100644 (file)
@@ -54,21 +54,10 @@ static void update_domain_cpuid_info(struct domain *d,
     switch ( ctl->input[0] )
     {
     case 0: {
-        union {
-            typeof(boot_cpu_data.x86_vendor_id) str;
-            struct {
-                uint32_t ebx, edx, ecx;
-            } reg;
-        } vendor_id = {
-            .reg = {
-                .ebx = ctl->ebx,
-                .edx = ctl->edx,
-                .ecx = ctl->ecx
-            }
-        };
         int old_vendor = d->arch.x86_vendor;
 
-        d->arch.x86_vendor = get_cpu_vendor(vendor_id.str, gcv_guest);
+        d->arch.x86_vendor = get_cpu_vendor(
+            ctl->ebx, ctl->ecx, ctl->edx, gcv_guest);
 
         if ( is_hvm_domain(d) && (d->arch.x86_vendor != old_vendor) )
         {
index be315861f899f006ae08fa89dac34234db0c0101..aff115b21f416da803deec58c9125b26a8c8569f 100644 (file)
@@ -624,7 +624,7 @@ enum get_cpu_vendor {
     gcv_guest,
 };
 
-int get_cpu_vendor(const char vendor_id[], enum get_cpu_vendor);
+int get_cpu_vendor(uint32_t b, uint32_t c, uint32_t d, enum get_cpu_vendor mode);
 uint8_t get_cpu_family(uint32_t raw, uint8_t *model, uint8_t *stepping);
 
 void pv_cpuid(struct cpu_user_regs *regs);