1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2f7627e25SThomas Gleixner #include <linux/smp.h> 3f7627e25SThomas Gleixner #include <linux/timex.h> 4f7627e25SThomas Gleixner #include <linux/string.h> 5f7627e25SThomas Gleixner #include <linux/seq_file.h> 6890da9cfSLinus Torvalds #include <linux/cpufreq.h> 7f7627e25SThomas Gleixner 87d5905dcSRafael J. Wysocki #include "cpu.h" 97d5905dcSRafael J. Wysocki 1014442a15SSean Christopherson #ifdef CONFIG_X86_VMX_FEATURE_NAMES 1114442a15SSean Christopherson extern const char * const x86_vmx_flags[NVMXINTS*32]; 1214442a15SSean Christopherson #endif 1314442a15SSean Christopherson 14f7627e25SThomas Gleixner /* 15f7627e25SThomas Gleixner * Get CPU information for use by the procfs. 16f7627e25SThomas Gleixner */ 17a967ceacSHiroshi Shimamoto static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c, 18a967ceacSHiroshi Shimamoto unsigned int cpu) 19a967ceacSHiroshi Shimamoto { 20327f4387SJaswinder Singh Rajput #ifdef CONFIG_SMP 21a967ceacSHiroshi Shimamoto seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); 227d79a7bdSBartosz Golaszewski seq_printf(m, "siblings\t: %d\n", 237d79a7bdSBartosz Golaszewski cpumask_weight(topology_core_cpumask(cpu))); 24a967ceacSHiroshi Shimamoto seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); 25a967ceacSHiroshi Shimamoto seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); 2601aaea1aSYinghai Lu seq_printf(m, "apicid\t\t: %d\n", c->apicid); 2701aaea1aSYinghai Lu seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid); 28a967ceacSHiroshi Shimamoto #endif 29a967ceacSHiroshi Shimamoto } 30a967ceacSHiroshi Shimamoto 31327f4387SJaswinder Singh Rajput #ifdef CONFIG_X86_32 32a967ceacSHiroshi Shimamoto static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) 33a967ceacSHiroshi Shimamoto { 34a967ceacSHiroshi Shimamoto seq_printf(m, 35a967ceacSHiroshi Shimamoto "fdiv_bug\t: %s\n" 36a967ceacSHiroshi Shimamoto "f00f_bug\t: %s\n" 37a967ceacSHiroshi Shimamoto "coma_bug\t: %s\n" 38a967ceacSHiroshi Shimamoto "fpu\t\t: %s\n" 39a967ceacSHiroshi Shimamoto "fpu_exception\t: %s\n" 40a967ceacSHiroshi Shimamoto "cpuid level\t: %d\n" 416415813bSMathias Krause "wp\t\t: yes\n", 4267e87d43SBorislav Petkov boot_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no", 4367e87d43SBorislav Petkov boot_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no", 4467e87d43SBorislav Petkov boot_cpu_has_bug(X86_BUG_COMA) ? "yes" : "no", 4567e87d43SBorislav Petkov boot_cpu_has(X86_FEATURE_FPU) ? "yes" : "no", 4667e87d43SBorislav Petkov boot_cpu_has(X86_FEATURE_FPU) ? "yes" : "no", 476415813bSMathias Krause c->cpuid_level); 48a967ceacSHiroshi Shimamoto } 492aef7720SHiroshi Shimamoto #else 502aef7720SHiroshi Shimamoto static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) 512aef7720SHiroshi Shimamoto { 522aef7720SHiroshi Shimamoto seq_printf(m, 532aef7720SHiroshi Shimamoto "fpu\t\t: yes\n" 542aef7720SHiroshi Shimamoto "fpu_exception\t: yes\n" 552aef7720SHiroshi Shimamoto "cpuid level\t: %d\n" 562aef7720SHiroshi Shimamoto "wp\t\t: yes\n", 572aef7720SHiroshi Shimamoto c->cpuid_level); 582aef7720SHiroshi Shimamoto } 592aef7720SHiroshi Shimamoto #endif 60a967ceacSHiroshi Shimamoto 61f7627e25SThomas Gleixner static int show_cpuinfo(struct seq_file *m, void *v) 62f7627e25SThomas Gleixner { 63f7627e25SThomas Gleixner struct cpuinfo_x86 *c = v; 64141168c3SKevin Winchester unsigned int cpu; 65a967ceacSHiroshi Shimamoto int i; 66f7627e25SThomas Gleixner 67a967ceacSHiroshi Shimamoto cpu = c->cpu_index; 68a967ceacSHiroshi Shimamoto seq_printf(m, "processor\t: %u\n" 69f7627e25SThomas Gleixner "vendor_id\t: %s\n" 70f7627e25SThomas Gleixner "cpu family\t: %d\n" 71a967ceacSHiroshi Shimamoto "model\t\t: %u\n" 72f7627e25SThomas Gleixner "model name\t: %s\n", 73a967ceacSHiroshi Shimamoto cpu, 74f7627e25SThomas Gleixner c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown", 75f7627e25SThomas Gleixner c->x86, 76f7627e25SThomas Gleixner c->x86_model, 77f7627e25SThomas Gleixner c->x86_model_id[0] ? c->x86_model_id : "unknown"); 78f7627e25SThomas Gleixner 79b399151cSJia Zhang if (c->x86_stepping || c->cpuid_level >= 0) 80b399151cSJia Zhang seq_printf(m, "stepping\t: %d\n", c->x86_stepping); 81f7627e25SThomas Gleixner else 823736708fSRasmus Villemoes seq_puts(m, "stepping\t: unknown\n"); 83506ed6b5SAndi Kleen if (c->microcode) 84881e23e5SBorislav Petkov seq_printf(m, "microcode\t: 0x%x\n", c->microcode); 85f7627e25SThomas Gleixner 86890da9cfSLinus Torvalds if (cpu_has(c, X86_FEATURE_TSC)) { 87*f3eca381SThomas Gleixner unsigned int freq = arch_freq_get_on_cpu(cpu); 88890da9cfSLinus Torvalds 89890da9cfSLinus Torvalds if (!freq) 907d5905dcSRafael J. Wysocki freq = cpufreq_quick_get(cpu); 917d5905dcSRafael J. Wysocki if (!freq) 92890da9cfSLinus Torvalds freq = cpu_khz; 93f7627e25SThomas Gleixner seq_printf(m, "cpu MHz\t\t: %u.%03u\n", 94890da9cfSLinus Torvalds freq / 1000, (freq % 1000)); 95890da9cfSLinus Torvalds } 96f7627e25SThomas Gleixner 97f7627e25SThomas Gleixner /* Cache size */ 9824dbc600SGustavo A. R. Silva if (c->x86_cache_size) 9924dbc600SGustavo A. R. Silva seq_printf(m, "cache size\t: %u KB\n", c->x86_cache_size); 100f7627e25SThomas Gleixner 101a967ceacSHiroshi Shimamoto show_cpuinfo_core(m, c, cpu); 102a967ceacSHiroshi Shimamoto show_cpuinfo_misc(m, c); 103f7627e25SThomas Gleixner 1043736708fSRasmus Villemoes seq_puts(m, "flags\t\t:"); 105f7627e25SThomas Gleixner for (i = 0; i < 32*NCAPINTS; i++) 106a967ceacSHiroshi Shimamoto if (cpu_has(c, i) && x86_cap_flags[i] != NULL) 107f7627e25SThomas Gleixner seq_printf(m, " %s", x86_cap_flags[i]); 108f7627e25SThomas Gleixner 10914442a15SSean Christopherson #ifdef CONFIG_X86_VMX_FEATURE_NAMES 11014442a15SSean Christopherson if (cpu_has(c, X86_FEATURE_VMX) && c->vmx_capability[0]) { 11114442a15SSean Christopherson seq_puts(m, "\nvmx flags\t:"); 11214442a15SSean Christopherson for (i = 0; i < 32*NVMXINTS; i++) { 11314442a15SSean Christopherson if (test_bit(i, (unsigned long *)c->vmx_capability) && 11414442a15SSean Christopherson x86_vmx_flags[i] != NULL) 11514442a15SSean Christopherson seq_printf(m, " %s", x86_vmx_flags[i]); 11614442a15SSean Christopherson } 11714442a15SSean Christopherson } 11814442a15SSean Christopherson #endif 11914442a15SSean Christopherson 1203736708fSRasmus Villemoes seq_puts(m, "\nbugs\t\t:"); 12180a208bdSBorislav Petkov for (i = 0; i < 32*NBUGINTS; i++) { 12280a208bdSBorislav Petkov unsigned int bug_bit = 32*NCAPINTS + i; 12380a208bdSBorislav Petkov 12480a208bdSBorislav Petkov if (cpu_has_bug(c, bug_bit) && x86_bug_flags[i]) 12580a208bdSBorislav Petkov seq_printf(m, " %s", x86_bug_flags[i]); 12680a208bdSBorislav Petkov } 12780a208bdSBorislav Petkov 128f84c3a42SHiroshi Shimamoto seq_printf(m, "\nbogomips\t: %lu.%02lu\n", 129f84c3a42SHiroshi Shimamoto c->loops_per_jiffy/(500000/HZ), 130f84c3a42SHiroshi Shimamoto (c->loops_per_jiffy/(5000/HZ)) % 100); 1312aef7720SHiroshi Shimamoto 1322aef7720SHiroshi Shimamoto #ifdef CONFIG_X86_64 1332aef7720SHiroshi Shimamoto if (c->x86_tlbsize > 0) 1342aef7720SHiroshi Shimamoto seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize); 1352aef7720SHiroshi Shimamoto #endif 136f84c3a42SHiroshi Shimamoto seq_printf(m, "clflush size\t: %u\n", c->x86_clflush_size); 1372aef7720SHiroshi Shimamoto seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment); 1382aef7720SHiroshi Shimamoto seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n", 1392aef7720SHiroshi Shimamoto c->x86_phys_bits, c->x86_virt_bits); 140f84c3a42SHiroshi Shimamoto 1413736708fSRasmus Villemoes seq_puts(m, "power management:"); 142f84c3a42SHiroshi Shimamoto for (i = 0; i < 32; i++) { 143f7627e25SThomas Gleixner if (c->x86_power & (1 << i)) { 144f7627e25SThomas Gleixner if (i < ARRAY_SIZE(x86_power_flags) && 145f7627e25SThomas Gleixner x86_power_flags[i]) 146f7627e25SThomas Gleixner seq_printf(m, "%s%s", 147f7627e25SThomas Gleixner x86_power_flags[i][0] ? " " : "", 148f7627e25SThomas Gleixner x86_power_flags[i]); 149f7627e25SThomas Gleixner else 150f7627e25SThomas Gleixner seq_printf(m, " [%d]", i); 151f7627e25SThomas Gleixner } 152f84c3a42SHiroshi Shimamoto } 153f7627e25SThomas Gleixner 1543736708fSRasmus Villemoes seq_puts(m, "\n\n"); 155f7627e25SThomas Gleixner 156f7627e25SThomas Gleixner return 0; 157f7627e25SThomas Gleixner } 158f7627e25SThomas Gleixner 159f7627e25SThomas Gleixner static void *c_start(struct seq_file *m, loff_t *pos) 160f7627e25SThomas Gleixner { 1614f062896SRusty Russell *pos = cpumask_next(*pos - 1, cpu_online_mask); 162bc8bcc79SLai Jiangshan if ((*pos) < nr_cpu_ids) 16392cb7612SMike Travis return &cpu_data(*pos); 16492cb7612SMike Travis return NULL; 165f7627e25SThomas Gleixner } 166a967ceacSHiroshi Shimamoto 167f7627e25SThomas Gleixner static void *c_next(struct seq_file *m, void *v, loff_t *pos) 168f7627e25SThomas Gleixner { 169bc8bcc79SLai Jiangshan (*pos)++; 170f7627e25SThomas Gleixner return c_start(m, pos); 171f7627e25SThomas Gleixner } 172a967ceacSHiroshi Shimamoto 173f7627e25SThomas Gleixner static void c_stop(struct seq_file *m, void *v) 174f7627e25SThomas Gleixner { 175f7627e25SThomas Gleixner } 176a967ceacSHiroshi Shimamoto 1778a45eb31SJan Engelhardt const struct seq_operations cpuinfo_op = { 178f7627e25SThomas Gleixner .start = c_start, 179f7627e25SThomas Gleixner .next = c_next, 180f7627e25SThomas Gleixner .stop = c_stop, 181f7627e25SThomas Gleixner .show = show_cpuinfo, 182f7627e25SThomas Gleixner }; 183