x86/cpu: Improvements to get_cpu_vendor()

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>
This commit is contained in:
Andrew Cooper committed 2017-01-03 13:33:16 +00:00
1 parent 291dcb4dd0
commit e34bc403c3
4 files changed
+23 -31

No files matched your search

+13 -14
View 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 */
+7 -3
View 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);
+2 -13
View 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) )
{
+1 -1
View 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);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.