1f7627e25SThomas Gleixner #include <linux/smp.h> 2f7627e25SThomas Gleixner #include <linux/timex.h> 3f7627e25SThomas Gleixner #include <linux/string.h> 4f7627e25SThomas Gleixner #include <linux/seq_file.h> 5f7627e25SThomas Gleixner #include <linux/cpufreq.h> 6f7627e25SThomas Gleixner 7f7627e25SThomas Gleixner /* 8f7627e25SThomas Gleixner * Get CPU information for use by the procfs. 9f7627e25SThomas Gleixner */ 10a967ceacSHiroshi Shimamoto static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c, 11a967ceacSHiroshi Shimamoto unsigned int cpu) 12a967ceacSHiroshi Shimamoto { 13327f4387SJaswinder Singh Rajput #ifdef CONFIG_SMP 14a967ceacSHiroshi Shimamoto seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); 15a477c859SHATAYAMA Daisuke seq_printf(m, "siblings\t: %d\n", cpumask_weight(cpu_core_mask(cpu))); 16a967ceacSHiroshi Shimamoto seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); 17a967ceacSHiroshi Shimamoto seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); 1801aaea1aSYinghai Lu seq_printf(m, "apicid\t\t: %d\n", c->apicid); 1901aaea1aSYinghai Lu seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid); 20a967ceacSHiroshi Shimamoto #endif 21a967ceacSHiroshi Shimamoto } 22a967ceacSHiroshi Shimamoto 23327f4387SJaswinder Singh Rajput #ifdef CONFIG_X86_32 24a967ceacSHiroshi Shimamoto static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) 25a967ceacSHiroshi Shimamoto { 26a967ceacSHiroshi Shimamoto seq_printf(m, 27a967ceacSHiroshi Shimamoto "fdiv_bug\t: %s\n" 28a967ceacSHiroshi Shimamoto "f00f_bug\t: %s\n" 29a967ceacSHiroshi Shimamoto "coma_bug\t: %s\n" 30a967ceacSHiroshi Shimamoto "fpu\t\t: %s\n" 31a967ceacSHiroshi Shimamoto "fpu_exception\t: %s\n" 32a967ceacSHiroshi Shimamoto "cpuid level\t: %d\n" 33a967ceacSHiroshi Shimamoto "wp\t\t: %s\n", 3493a829e8SBorislav Petkov static_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no", 35e2604b49SBorislav Petkov static_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no", 36c5b41a67SBorislav Petkov static_cpu_has_bug(X86_BUG_COMA) ? "yes" : "no", 3760e019ebSH. Peter Anvin static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no", 3860e019ebSH. Peter Anvin static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no", 39a967ceacSHiroshi Shimamoto c->cpuid_level, 40a967ceacSHiroshi Shimamoto c->wp_works_ok ? "yes" : "no"); 41a967ceacSHiroshi Shimamoto } 422aef7720SHiroshi Shimamoto #else 432aef7720SHiroshi Shimamoto static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) 442aef7720SHiroshi Shimamoto { 452aef7720SHiroshi Shimamoto seq_printf(m, 462aef7720SHiroshi Shimamoto "fpu\t\t: yes\n" 472aef7720SHiroshi Shimamoto "fpu_exception\t: yes\n" 482aef7720SHiroshi Shimamoto "cpuid level\t: %d\n" 492aef7720SHiroshi Shimamoto "wp\t\t: yes\n", 502aef7720SHiroshi Shimamoto c->cpuid_level); 512aef7720SHiroshi Shimamoto } 522aef7720SHiroshi Shimamoto #endif 53a967ceacSHiroshi Shimamoto 54f7627e25SThomas Gleixner static int show_cpuinfo(struct seq_file *m, void *v) 55f7627e25SThomas Gleixner { 56f7627e25SThomas Gleixner struct cpuinfo_x86 *c = v; 57141168c3SKevin Winchester unsigned int cpu; 58a967ceacSHiroshi Shimamoto int i; 59f7627e25SThomas Gleixner 60a967ceacSHiroshi Shimamoto cpu = c->cpu_index; 61a967ceacSHiroshi Shimamoto seq_printf(m, "processor\t: %u\n" 62f7627e25SThomas Gleixner "vendor_id\t: %s\n" 63f7627e25SThomas Gleixner "cpu family\t: %d\n" 64a967ceacSHiroshi Shimamoto "model\t\t: %u\n" 65f7627e25SThomas Gleixner "model name\t: %s\n", 66a967ceacSHiroshi Shimamoto cpu, 67f7627e25SThomas Gleixner c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown", 68f7627e25SThomas Gleixner c->x86, 69f7627e25SThomas Gleixner c->x86_model, 70f7627e25SThomas Gleixner c->x86_model_id[0] ? c->x86_model_id : "unknown"); 71f7627e25SThomas Gleixner 72f7627e25SThomas Gleixner if (c->x86_mask || c->cpuid_level >= 0) 73f7627e25SThomas Gleixner seq_printf(m, "stepping\t: %d\n", c->x86_mask); 74f7627e25SThomas Gleixner else 753736708fSRasmus Villemoes seq_puts(m, "stepping\t: unknown\n"); 76506ed6b5SAndi Kleen if (c->microcode) 77881e23e5SBorislav Petkov seq_printf(m, "microcode\t: 0x%x\n", c->microcode); 78f7627e25SThomas Gleixner 79f7627e25SThomas Gleixner if (cpu_has(c, X86_FEATURE_TSC)) { 80a967ceacSHiroshi Shimamoto unsigned int freq = cpufreq_quick_get(cpu); 81a967ceacSHiroshi Shimamoto 82f7627e25SThomas Gleixner if (!freq) 83f7627e25SThomas Gleixner freq = cpu_khz; 84f7627e25SThomas Gleixner seq_printf(m, "cpu MHz\t\t: %u.%03u\n", 85f7627e25SThomas Gleixner freq / 1000, (freq % 1000)); 86f7627e25SThomas Gleixner } 87f7627e25SThomas Gleixner 88f7627e25SThomas Gleixner /* Cache size */ 89f7627e25SThomas Gleixner if (c->x86_cache_size >= 0) 90f7627e25SThomas Gleixner seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); 91f7627e25SThomas Gleixner 92a967ceacSHiroshi Shimamoto show_cpuinfo_core(m, c, cpu); 93a967ceacSHiroshi Shimamoto show_cpuinfo_misc(m, c); 94f7627e25SThomas Gleixner 953736708fSRasmus Villemoes seq_puts(m, "flags\t\t:"); 96f7627e25SThomas Gleixner for (i = 0; i < 32*NCAPINTS; i++) 97a967ceacSHiroshi Shimamoto if (cpu_has(c, i) && x86_cap_flags[i] != NULL) 98f7627e25SThomas Gleixner seq_printf(m, " %s", x86_cap_flags[i]); 99f7627e25SThomas Gleixner 1003736708fSRasmus Villemoes seq_puts(m, "\nbugs\t\t:"); 10180a208bdSBorislav Petkov for (i = 0; i < 32*NBUGINTS; i++) { 10280a208bdSBorislav Petkov unsigned int bug_bit = 32*NCAPINTS + i; 10380a208bdSBorislav Petkov 10480a208bdSBorislav Petkov if (cpu_has_bug(c, bug_bit) && x86_bug_flags[i]) 10580a208bdSBorislav Petkov seq_printf(m, " %s", x86_bug_flags[i]); 10680a208bdSBorislav Petkov } 10780a208bdSBorislav Petkov 108f84c3a42SHiroshi Shimamoto seq_printf(m, "\nbogomips\t: %lu.%02lu\n", 109f84c3a42SHiroshi Shimamoto c->loops_per_jiffy/(500000/HZ), 110f84c3a42SHiroshi Shimamoto (c->loops_per_jiffy/(5000/HZ)) % 100); 1112aef7720SHiroshi Shimamoto 1122aef7720SHiroshi Shimamoto #ifdef CONFIG_X86_64 1132aef7720SHiroshi Shimamoto if (c->x86_tlbsize > 0) 1142aef7720SHiroshi Shimamoto seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize); 1152aef7720SHiroshi Shimamoto #endif 116f84c3a42SHiroshi Shimamoto seq_printf(m, "clflush size\t: %u\n", c->x86_clflush_size); 1172aef7720SHiroshi Shimamoto seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment); 1182aef7720SHiroshi Shimamoto seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n", 1192aef7720SHiroshi Shimamoto c->x86_phys_bits, c->x86_virt_bits); 120f84c3a42SHiroshi Shimamoto 1213736708fSRasmus Villemoes seq_puts(m, "power management:"); 122f84c3a42SHiroshi Shimamoto for (i = 0; i < 32; i++) { 123f7627e25SThomas Gleixner if (c->x86_power & (1 << i)) { 124f7627e25SThomas Gleixner if (i < ARRAY_SIZE(x86_power_flags) && 125f7627e25SThomas Gleixner x86_power_flags[i]) 126f7627e25SThomas Gleixner seq_printf(m, "%s%s", 127f7627e25SThomas Gleixner x86_power_flags[i][0] ? " " : "", 128f7627e25SThomas Gleixner x86_power_flags[i]); 129f7627e25SThomas Gleixner else 130f7627e25SThomas Gleixner seq_printf(m, " [%d]", i); 131f7627e25SThomas Gleixner } 132f84c3a42SHiroshi Shimamoto } 133f7627e25SThomas Gleixner 1343736708fSRasmus Villemoes seq_puts(m, "\n\n"); 135f7627e25SThomas Gleixner 136f7627e25SThomas Gleixner return 0; 137f7627e25SThomas Gleixner } 138f7627e25SThomas Gleixner 139f7627e25SThomas Gleixner static void *c_start(struct seq_file *m, loff_t *pos) 140f7627e25SThomas Gleixner { 1414f062896SRusty Russell *pos = cpumask_next(*pos - 1, cpu_online_mask); 142bc8bcc79SLai Jiangshan if ((*pos) < nr_cpu_ids) 14392cb7612SMike Travis return &cpu_data(*pos); 14492cb7612SMike Travis return NULL; 145f7627e25SThomas Gleixner } 146a967ceacSHiroshi Shimamoto 147f7627e25SThomas Gleixner static void *c_next(struct seq_file *m, void *v, loff_t *pos) 148f7627e25SThomas Gleixner { 149bc8bcc79SLai Jiangshan (*pos)++; 150f7627e25SThomas Gleixner return c_start(m, pos); 151f7627e25SThomas Gleixner } 152a967ceacSHiroshi Shimamoto 153f7627e25SThomas Gleixner static void c_stop(struct seq_file *m, void *v) 154f7627e25SThomas Gleixner { 155f7627e25SThomas Gleixner } 156a967ceacSHiroshi Shimamoto 1578a45eb31SJan Engelhardt const struct seq_operations cpuinfo_op = { 158f7627e25SThomas Gleixner .start = c_start, 159f7627e25SThomas Gleixner .next = c_next, 160f7627e25SThomas Gleixner .stop = c_stop, 161f7627e25SThomas Gleixner .show = show_cpuinfo, 162f7627e25SThomas Gleixner }; 163