x86/CPUID: CPUID parsing rework, p1
Subsystems (8)
Borislav Petkov
maintainercover x86/CPUID: CPUID parsing rework, p1
From: Borislav Petkov <[email protected]>
Hi all,
this is the beginning of a long conversion. The final goal is to have one global, read-only CPUID hierarchy representation in arch/x86/ to replace all the gazillion places where CPUID is read and thus slim a lot of code. And improve all that X86_FEATURE* diddling. We'll see...
Anyway, these are the first three patches slimming cpuinfo_x86 by 80 bytes per CPU, by making vendor ID and brand name global and __ro_after_init.
Comments, reviews, etc are welcome, as always.
Thx.
Borislav Petkov (3):
x86/cpuid: Make cpuinfo_x86.x86_vendor_id global x86/cpuid: Get vendor ID on the BSP x86/cpuid: Make cpuinfo_x86.x86_model_id global
arch/x86/include/asm/processor.h | 6 +-- arch/x86/kernel/asm-offsets_32.c | 1 - arch/x86/kernel/cpu/amd.c | 4 +- arch/x86/kernel/cpu/centaur.c | 2 +- arch/x86/kernel/cpu/common.c | 56 +++++++++++++++------------- arch/x86/kernel/cpu/cyrix.c | 7 ++-- arch/x86/kernel/cpu/intel.c | 2 +- arch/x86/kernel/cpu/proc.c | 4 +- arch/x86/kernel/head_32.S | 5 --- arch/x86/kernel/setup.c | 3 ++ drivers/cpufreq/powernow-k8.c | 2 +- drivers/cpufreq/speedstep-centrino.c | 6 +-- drivers/cpufreq/speedstep-lib.c | 2 +- drivers/edac/e752x_edac.c | 3 +- drivers/hwmon/coretemp.c | 2 +- drivers/hwmon/k10temp.c | 2 +- drivers/platform/x86/intel_ips.c | 6 +-- 17 files changed, 57 insertions(+), 56 deletions(-)
Signature · 1 line
2.19.1
Borislav Petkov
maintainerPATCH 1/3 x86/cpuid: Make cpuinfo_x86.x86_vendor_id global
From: Borislav Petkov <[email protected]>
Make x86_vendor_id __ro_after_init and global as it is not needed per-CPU. Thus, save 16 bytes of per-CPU memory. Remove the vendor ID readout early in head_32.S because it is not needed that early either.
--- arch/x86/include/asm/processor.h | 4 ++-- arch/x86/kernel/asm-offsets_32.c | 1 - arch/x86/kernel/cpu/common.c | 15 +++++++-------- arch/x86/kernel/cpu/cyrix.c | 2 +- arch/x86/kernel/cpu/proc.c | 2 +- arch/x86/kernel/head_32.S | 5 ----- arch/x86/kernel/setup.c | 1 + 7 files changed, 12 insertions(+), 18 deletions(-)
arch/x86/include/asm/processor.h +2 -2
@@ -69,12 +69,13 @@ extern u16 __read_mostly tlb_lld_2m[NR_INFO];extern u16 __read_mostly tlb_lld_4m[NR_INFO ];extern u16 __read_mostly tlb_lld_1g[NR_INFO ]; +extern char x86_vendor_id[16 ]; +/* * CPU type and hardware bug flags. Kept separately for each CPU. * Members of this structure are referenced in head_32.S, so think twice * before touching them. [mj] */ -struct cpuinfo_x86 {__u8 x86;/* CPU family */ __u8 x86_vendor;/* CPU vendor */
@@ -94,7 +95,6 @@ struct cpuinfo_x86 {/* Maximum supported CPUID level, -1=no CPUID: */ int cpuid_level;__u32 x86_capability[NCAPINTS +NBUGINTS ]; -char x86_vendor_id[16 ];char x86_model_id[64 ];/* in KB - valid for CPUS which support this call: */ unsigned int x86_cache_size;
arch/x86/kernel/asm-offsets_32.c +0 -1
@@ -21,7 +21,6 @@ void foo(void)OFFSET (CPUINFO_x86_stepping, cpuinfo_x86, x86_stepping);OFFSET (CPUINFO_cpuid_level, cpuinfo_x86, cpuid_level);OFFSET (CPUINFO_x86_capability, cpuinfo_x86, x86_capability); -OFFSET (CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);BLANK ();OFFSET (PT_EBX , pt_regs, bx);
arch/x86/kernel/cpu/common.c +7 -8
@@ -708,7 +708,7 @@ void detect_ht(struct cpuinfo_x86 *c)static void get_cpu_vendor (struct cpuinfo_x86 *c) { -char *v = c->x86_vendor_id; +char *v = x86_vendor_id;int i;for (i =0 ; i <X86_VENDOR_NUM ; i++) {
@@ -736,9 +736,9 @@ void cpu_detect(struct cpuinfo_x86 *c) {/* Get vendor name */ cpuid (0x00000000 , (unsigned int *)&c->cpuid_level, - (unsigned int *)&c->x86_vendor_id[0 ], - (unsigned int *)&c->x86_vendor_id[8 ], - (unsigned int *)&c->x86_vendor_id[4 ]); + (unsigned int *)&x86_vendor_id[0 ], + (unsigned int *)&x86_vendor_id[8 ], + (unsigned int *)&x86_vendor_id[4 ]); c->x86 =4 ;/* Intel-defined flags: level 0x00000001 */
@@ -938,9 +938,9 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)for (i =0 ; i <X86_VENDOR_NUM ; i++)if (cpu_devs[i] && cpu_devs[i]->c_identify) { - c->x86_vendor_id[0 ] =0 ; + x86_vendor_id[0 ] =0 ; cpu_devs[i]->c_identify (c); -if (c->x86_vendor_id[0 ]) { +if (x86_vendor_id[0 ]) {get_cpu_vendor (c);break ; }
@@ -1301,7 +1301,6 @@ static void identify_cpu(struct cpuinfo_x86 *c) c->x86_cache_size =0 ; c->x86_vendor =X86_VENDOR_UNKNOWN ; c->x86_model = c->x86_stepping =0 ;/* So far unknown... */ - c->x86_vendor_id[0 ] ='\0' ;/* Unset */ c->x86_model_id[0 ] ='\0' ;/* Unset */ c->x86_max_cores =1 ; c->x86_coreid_bits =0 ;
@@ -1480,7 +1479,7 @@ void print_cpu_info(struct cpuinfo_x86 *c) vendor = this_cpu->c_vendor; }else {if (c->cpuid_level >=0 ) - vendor = c->x86_vendor_id; + vendor = x86_vendor_id; }if (vendor && !strstr (c->x86_model_id, vendor))
arch/x86/kernel/cpu/cyrix.c +1 -1
@@ -415,7 +415,7 @@ static void cyrix_identify(struct cpuinfo_x86 *c)if (c->x86 ==4 &&test_cyrix_52div ()) {unsigned char dir0, dir1; -strcpy (c->x86_vendor_id,"CyrixInstead" ); +strcpy (x86_vendor_id,"CyrixInstead" ); c->x86_vendor =X86_VENDOR_CYRIX ;/* Actually enable cpuid on the older cyrix */
arch/x86/kernel/cpu/proc.c +1 -1
@@ -67,7 +67,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)"model\t\t: %u\n" "model name\t: %s\n" , cpu, - c->x86_vendor_id[0 ] ? c->x86_vendor_id :"unknown" , + x86_vendor_id[0 ] ? x86_vendor_id :"unknown" , c->x86, c->x86_model, c->x86_model_id[0] ? c->x86_model_id : "unknown");
arch/x86/kernel/head_32.S +0 -5
@@ -41,8 +41,6 @@ #define X86_HARD_MATH new_cpu_data+CPUINFO_hard_math #define X86_CPUID new_cpu_data+CPUINFO_cpuid_level #define X86_CAPABILITY new_cpu_data+CPUINFO_x86_capability -#define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id - #define SIZEOF_PTREGS 17*4
@@ -316,9 +314,6 @@ ENTRY(startup_32_smp) xorl %eax,%eax # call CPUID with 0 -> return vendor ID cpuid movl %eax,X86_CPUID # save CPUID level - movl %ebx,X86_VENDOR_ID # lo 4 chars - movl %edx,X86_VENDOR_ID+4 # next 4 chars - movl %ecx,X86_VENDOR_ID+8 # last 4 chars orl %eax,%eax # do we have processor info as well? je .Lis486
arch/x86/kernel/setup.c +1 -0
@@ -161,6 +161,7 @@ static struct resource bss_resource = { .flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM }; +char x86_vendor_id[16 ]__ro_after_init ;#ifdef CONFIG_X86_32 /* cpu data as detected by the assembly code in head_32.S */
Signature · 1 line
2.19.1
Borislav Petkov
maintainerPATCH 2/3 x86/cpuid: Get vendor ID on the BSP
In reply to Borislav PetkovFrom: Borislav Petkov <[email protected]>
No need to do it on each CPU. Read max base CPUID level on each CPU for now so that the check in cpu_detect() works.
--- arch/x86/kernel/cpu/common.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
arch/x86/kernel/cpu/common.c +10 -3
@@ -732,15 +732,21 @@ static void get_cpu_vendor(struct cpuinfo_x86 *c) this_cpu = &default_cpu; } -void cpu_detect (struct cpuinfo_x86 *c) +static void cpu_get_vendor_name (void ) { -/* Get vendor name */ -cpuid (0x00000000 , (unsigned int *)&c->cpuid_level, +u32 dummy; + +cpuid (0x00000000 , &dummy, (unsigned int *)&x86_vendor_id[0 ], (unsigned int *)&x86_vendor_id[8 ], (unsigned int *)&x86_vendor_id[4 ]); +} +void cpu_detect (struct cpuinfo_x86 *c) +{ + c->cpuid_level =cpuid_eax (0 ); c->x86 =4 ; +/* Intel-defined flags: level 0x00000001 */ if (c->cpuid_level >=0x00000001 ) {u32 junk, tfms, cap0, misc;
@@ -1082,6 +1088,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)/* cyrix could have cpuid enabled via c_identify()*/ if (have_cpuid_p ()) { +cpu_get_vendor_name ();cpu_detect (c);get_cpu_vendor (c);get_cpu_cap (c);
Signature · 1 line
2.19.1
Borislav Petkov
maintainerPATCH 3/3 x86/cpuid: Make cpuinfo_x86.x86_model_id global
In reply to Borislav PetkovFrom: Borislav Petkov <[email protected]>
... and __ro_after_init. Since the brand string is being read earlier now, in early_identify_cpu(), get_model_name() needs to read out the extended CPUID level for the brand string. This is temporary only, until the full CPUID read out has been added.
--- arch/x86/include/asm/processor.h | 2 +- arch/x86/kernel/cpu/amd.c | 4 ++-- arch/x86/kernel/cpu/centaur.c | 2 +- arch/x86/kernel/cpu/common.c | 28 ++++++++++++++-------------- arch/x86/kernel/cpu/cyrix.c | 5 ++--- arch/x86/kernel/cpu/intel.c | 2 +- arch/x86/kernel/cpu/proc.c | 2 +- arch/x86/kernel/setup.c | 2 ++ drivers/cpufreq/powernow-k8.c | 2 +- drivers/cpufreq/speedstep-centrino.c | 6 +++--- drivers/cpufreq/speedstep-lib.c | 2 +- drivers/edac/e752x_edac.c | 3 +-- drivers/hwmon/coretemp.c | 2 +- drivers/hwmon/k10temp.c | 2 +- drivers/platform/x86/intel_ips.c | 6 +++--- 15 files changed, 35 insertions(+), 35 deletions(-)
arch/x86/include/asm/processor.h +1 -1
@@ -70,6 +70,7 @@ extern u16 __read_mostly tlb_lld_4m[NR_INFO];extern u16 __read_mostly tlb_lld_1g[NR_INFO ];extern char x86_vendor_id[16 ]; +extern char x86_model_id[64 ];/* * CPU type and hardware bug flags. Kept separately for each CPU.
@@ -95,7 +96,6 @@ struct cpuinfo_x86 {/* Maximum supported CPUID level, -1=no CPUID: */ int cpuid_level;__u32 x86_capability[NCAPINTS +NBUGINTS ]; -char x86_model_id[64 ];/* in KB - valid for CPUS which support this call: */ unsigned int x86_cache_size;int x86_cache_alignment;/* In bytes */
arch/x86/kernel/cpu/amd.c +2 -2
@@ -737,8 +737,8 @@ static void init_amd_k8(struct cpuinfo_x86 *c) } } -if (!c->x86_model_id[0 ]) -strcpy (c->x86_model_id,"Hammer" ); +if (!x86_model_id[0 ]) +strcpy (x86_model_id,"Hammer" );#ifdef CONFIG_SMP /*
arch/x86/kernel/cpu/centaur.c +1 -1
@@ -239,7 +239,7 @@ static void init_centaur(struct cpuinfo_x86 *c)/* Add L1 data and code cache sizes. */ c->x86_cache_size = (cc>>24)+(dd>>24); } -sprintf (c->x86_model_id,"WinChip %s" , name); +sprintf (x86_model_id,"WinChip %s" , name);break ;#endif case 6 :
arch/x86/kernel/cpu/common.c +14 -14
@@ -95,9 +95,9 @@ static void default_init(struct cpuinfo_x86 *c)if (c->cpuid_level ==-1 ) {/* No cpuid. It must be an ancient CPU */ if (c->x86 ==4 ) -strcpy (c->x86_model_id,"486" ); +strcpy (x86_model_id,"486" );else if (c->x86 ==3 ) -strcpy (c->x86_model_id,"386" ); +strcpy (x86_model_id,"386" ); }#endif }
@@ -561,17 +561,18 @@ static void get_model_name(struct cpuinfo_x86 *c)unsigned int *v;char *p, *q, *s; + c->extended_cpuid_level =cpuid_eax (0x80000000 );if (c->extended_cpuid_level <0x80000004 )return ; - v = (unsigned int *)c->x86_model_id; + v = (unsigned int *)x86_model_id;cpuid (0x80000002 , &v[0 ], &v[1 ], &v[2 ], &v[3 ]);cpuid (0x80000003 , &v[4 ], &v[5 ], &v[6 ], &v[7 ]);cpuid (0x80000004 , &v[8 ], &v[9 ], &v[10 ], &v[11 ]); - c->x86_model_id[48 ] =0 ; + x86_model_id[48 ] =0 ;/* Trim whitespace */ - p = q = s = &c->x86_model_id[0 ]; + p = q = s = x86_model_id;while (*p ==' ' ) p++;
@@ -1089,6 +1090,7 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)/* cyrix could have cpuid enabled via c_identify()*/ if (have_cpuid_p ()) {cpu_get_vendor_name (); +get_model_name (c);cpu_detect (c);get_cpu_vendor (c);get_cpu_cap (c);
@@ -1232,8 +1234,6 @@ static void generic_identify(struct cpuinfo_x86 *c) c->phys_proc_id = c->initial_apicid; } -get_model_name (c);/* Default name */ -detect_null_seg_behavior (c);/*
@@ -1308,7 +1308,6 @@ static void identify_cpu(struct cpuinfo_x86 *c) c->x86_cache_size =0 ; c->x86_vendor =X86_VENDOR_UNKNOWN ; c->x86_model = c->x86_stepping =0 ;/* So far unknown... */ - c->x86_model_id[0 ] ='\0' ;/* Unset */ c->x86_max_cores =1 ; c->x86_coreid_bits =0 ; c->cu_id =0xff ;
@@ -1367,14 +1366,15 @@ static void identify_cpu(struct cpuinfo_x86 *c)filter_cpuid_features (c, true);/* If the model name is still unset, do table lookup. */ -if (!c->x86_model_id[0 ]) { +if (!x86_model_id[0 ]) {const char *p; + p =table_lookup_model (c);if (p) -strcpy (c->x86_model_id, p); +strcpy (x86_model_id, p);else /* Last resort... */ -sprintf (c->x86_model_id,"%02x/%02x" , +sprintf (x86_model_id,"%02x/%02x" , c->x86, c->x86_model); }
@@ -1489,11 +1489,11 @@ void print_cpu_info(struct cpuinfo_x86 *c) vendor = x86_vendor_id; } -if (vendor && !strstr (c->x86_model_id, vendor)) +if (vendor && !strstr (x86_model_id, vendor))pr_cont ("%s " , vendor); -if (c->x86_model_id[0 ]) -pr_cont ("%s" , c->x86_model_id); +if (x86_model_id[0 ]) +pr_cont ("%s" , x86_model_id);else pr_cont ("%d86" , c->x86);
arch/x86/kernel/cpu/cyrix.c +2 -3
@@ -191,7 +191,6 @@ static void early_init_cyrix(struct cpuinfo_x86 *c)static void init_cyrix (struct cpuinfo_x86 *c) {unsigned char dir0, dir0_msn, dir0_lsn, dir1 =0 ; -char *buf = c->x86_model_id;const char *p =NULL ;/*
@@ -351,9 +350,9 @@ static void init_cyrix(struct cpuinfo_x86 *c) dir0_msn =7 ;break ; } -strcpy (buf, Cx86_model[dir0_msn &7 ]); +strcpy (x86_model_id, Cx86_model[dir0_msn &7 ]);if (p) -strcat (buf, p); +strcat (x86_model_id, p);return ; }
arch/x86/kernel/cpu/intel.c +1 -1
@@ -745,7 +745,7 @@ static void init_intel(struct cpuinfo_x86 *c) }if (p) -strcpy (c->x86_model_id, p); +strcpy (x86_model_id, p); }if (c->x86 ==15 )
arch/x86/kernel/cpu/proc.c +1 -1
@@ -70,7 +70,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) x86_vendor_id[0 ] ? x86_vendor_id :"unknown" , c->x86, c->x86_model, - c->x86_model_id[0] ? c->x86_model_id : "unknown"); + x86_model_id[0] ? x86_model_id : "unknown");if (c->x86_stepping || c->cpuid_level >=0 )seq_printf (m,"stepping\t: %d\n" , c->x86_stepping);
arch/x86/kernel/setup.c +2 -0
@@ -162,6 +162,8 @@ static struct resource bss_resource = { };char x86_vendor_id[16 ]__ro_after_init ; +char x86_model_id[64 ]__ro_after_init ; +EXPORT_SYMBOL_GPL (x86_model_id);#ifdef CONFIG_X86_32 /* cpu data as detected by the assembly code in head_32.S */
drivers/cpufreq/powernow-k8.c +1 -1
@@ -1204,7 +1204,7 @@ static int powernowk8_init(void)return ret;pr_info ("Found %d %s (%d cpu cores) (" VERSION ")\n" , -num_online_nodes (), boot_cpu_data.x86_model_id, supported_cpus); +num_online_nodes (), x86_model_id, supported_cpus);return ret; }
drivers/cpufreq/speedstep-centrino.c +3 -3
@@ -238,21 +238,21 @@ static int centrino_cpu_init_table(struct cpufreq_policy *policy)for (model = models; model->cpu_id !=NULL ; model++)if (centrino_verify_cpu_id (cpu, model->cpu_id) && (model->model_name ==NULL || -strcmp (cpu->x86_model_id, model->model_name) ==0 )) +strcmp (x86_model_id, model->model_name) ==0 ))break ;if (model->cpu_id ==NULL ) {/* No match at all */ pr_debug ("no support for CPU model \"%s\": " "send /proc/cpuinfo to " MAINTAINER "\n" , - cpu->x86_model_id); + x86_model_id);return -ENOENT ; }if (model->op_points ==NULL ) {/* Matched a non-match */ pr_debug ("no table support for CPU model \"%s\"\n" , - cpu->x86_model_id); + x86_model_id);pr_debug ("try using the acpi-cpufreq driver\n" );return -ENOENT ; }
drivers/cpufreq/speedstep-lib.c +1 -1
@@ -312,7 +312,7 @@ enum speedstep_processor speedstep_detect_processor(void)* string */ if ((ebx ==0x0e ) || - (strstr (c->x86_model_id, + (strstr (x86_model_id,"Mobile Intel(R) Pentium(R) 4" ) !=NULL ))return SPEEDSTEP_CPU_P4M ;break ;
drivers/edac/e752x_edac.c +1 -2
@@ -1211,14 +1211,13 @@ static int e752x_get_devs(struct pci_dev *pdev, int dev_idx,*/ static void e752x_init_sysbus_parity_mask (struct e752x_pvt *pvt) { -char *cpu_id =cpu_data (0 ).x86_model_id;struct pci_dev *dev = pvt->dev_d0f1;int enable =1 ;/* Allow module parameter override, else see if CPU supports parity */ if (sysbus_parity !=-1 ) { enable = sysbus_parity; - }else if (cpu_id[0 ] && !strstr (cpu_id,"Xeon" )) { + }else if (x86_model_id[0 ] && !strstr (x86_model_id,"Xeon" )) {e752x_printk (KERN_INFO ,"System Bus Parity not " "supported by CPU, disabling\n" ); enable =0 ;
drivers/hwmon/coretemp.c +1 -1
@@ -262,7 +262,7 @@ static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) }for (i =0 ; i <ARRAY_SIZE (tjmax_table); i++) { -if (strstr (c->x86_model_id, tjmax_table[i].id)) +if (strstr (x86_model_id, tjmax_table[i].id))return tjmax_table[i].tjmax; }
drivers/hwmon/k10temp.c +1 -1
@@ -343,7 +343,7 @@ static int k10temp_probe(struct pci_dev *pdev,const struct tctl_offset *entry = &tctl_offset_table[i];if (boot_cpu_data.x86 == entry->model && -strstr (boot_cpu_data.x86_model_id, entry->id)) { +strstr (x86_model_id, entry->id)) { data->temp_offset = entry->offset;break ; }
drivers/platform/x86/intel_ips.c +3 -3
@@ -1367,11 +1367,11 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips)else ips->turbo_toggle_allowed = false; -if (strstr (boot_cpu_data.x86_model_id,"CPU M" )) +if (strstr (x86_model_id,"CPU M" )) limits = &ips_sv_limits; -else if (strstr (boot_cpu_data.x86_model_id,"CPU L" )) +else if (strstr (x86_model_id,"CPU L" )) limits = &ips_lv_limits; -else if (strstr (boot_cpu_data.x86_model_id,"CPU U" )) +else if (strstr (x86_model_id,"CPU U" )) limits = &ips_ulv_limits;else {dev_info (ips->dev,"No CPUID match found.\n" );
Re: [PATCH 3/3] x86/cpuid: Make cpuinfo_x86.x86_model_id global
Quoted 22 lines · Borislav Petkov
From: Borislav Petkov <[email protected]>
... and
__ro_after_init. Since the brand string is being read earlier now, inearly_identify_cpu(),get_model_name()needs to read out the extended CPUID level for the brand string. This is temporary only, until the full CPUID read out has been added.drivers/platform/x86/intel_ips.c | 6 +++--- 15 files changed, 35 insertions(+), 35 deletions(-)drivers/platform/x86/intel_ips.c +0
-1@@ -1367,11 +1367,11 @@ static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips)else ips->turbo_toggle_allowed = false; -if (strstr (boot_cpu_data.x86_model_id,"CPU M" ))
drivers/platform/x86/intel_ips.c static struct ips_mcp_limits *ips_detect_cpu(struct ips_driver *ips) · line 1377
Quoted 10 lines
drivers/platform/x86/intel_ips.c +3
-2+if (strstr (x86_model_id,"CPU M" )) limits = &ips_sv_limits; - else if (strstr(boot_cpu_data.x86_model_id, "CPU L")) +else if (strstr (x86_model_id,"CPU L" )) limits = &ips_lv_limits; - else if (strstr(boot_cpu_data.x86_model_id, "CPU U")) +else if (strstr (x86_model_id,"CPU U" )) limits = &ips_ulv_limits;else {dev_info (ips->dev,"No CPUID match found.\n" );
for PDx86 bits
---
With Best Regards,
Andy Shevchenko