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 if (c->x86_max_cores * smp_num_siblings > 1) { 15a967ceacSHiroshi Shimamoto seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); 16a967ceacSHiroshi Shimamoto seq_printf(m, "siblings\t: %d\n", 1735d11680SAndreas Herrmann cpumask_weight(cpu_core_mask(cpu))); 18a967ceacSHiroshi Shimamoto seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); 19a967ceacSHiroshi Shimamoto seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); 2001aaea1aSYinghai Lu seq_printf(m, "apicid\t\t: %d\n", c->apicid); 2101aaea1aSYinghai Lu seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid); 22a967ceacSHiroshi Shimamoto } 23a967ceacSHiroshi Shimamoto #endif 24a967ceacSHiroshi Shimamoto } 25a967ceacSHiroshi Shimamoto 26327f4387SJaswinder Singh Rajput #ifdef CONFIG_X86_32 27a967ceacSHiroshi Shimamoto static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) 28a967ceacSHiroshi Shimamoto { 29a967ceacSHiroshi Shimamoto seq_printf(m, 30a967ceacSHiroshi Shimamoto "fdiv_bug\t: %s\n" 31a967ceacSHiroshi Shimamoto "f00f_bug\t: %s\n" 32a967ceacSHiroshi Shimamoto "coma_bug\t: %s\n" 33a967ceacSHiroshi Shimamoto "fpu\t\t: %s\n" 34a967ceacSHiroshi Shimamoto "fpu_exception\t: %s\n" 35a967ceacSHiroshi Shimamoto "cpuid level\t: %d\n" 36a967ceacSHiroshi Shimamoto "wp\t\t: %s\n", 3793a829e8SBorislav Petkov static_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no", 38e2604b49SBorislav Petkov static_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no", 39c5b41a67SBorislav Petkov static_cpu_has_bug(X86_BUG_COMA) ? "yes" : "no", 4060e019ebSH. Peter Anvin static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no", 4160e019ebSH. Peter Anvin static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no", 42a967ceacSHiroshi Shimamoto c->cpuid_level, 43a967ceacSHiroshi Shimamoto c->wp_works_ok ? "yes" : "no"); 44a967ceacSHiroshi Shimamoto } 452aef7720SHiroshi Shimamoto #else 462aef7720SHiroshi Shimamoto static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) 472aef7720SHiroshi Shimamoto { 482aef7720SHiroshi Shimamoto seq_printf(m, 492aef7720SHiroshi Shimamoto "fpu\t\t: yes\n" 502aef7720SHiroshi Shimamoto "fpu_exception\t: yes\n" 512aef7720SHiroshi Shimamoto "cpuid level\t: %d\n" 522aef7720SHiroshi Shimamoto "wp\t\t: yes\n", 532aef7720SHiroshi Shimamoto c->cpuid_level); 542aef7720SHiroshi Shimamoto } 552aef7720SHiroshi Shimamoto #endif 56a967ceacSHiroshi Shimamoto 57f7627e25SThomas Gleixner static int show_cpuinfo(struct seq_file *m, void *v) 58f7627e25SThomas Gleixner { 59f7627e25SThomas Gleixner struct cpuinfo_x86 *c = v; 60141168c3SKevin Winchester unsigned int cpu; 61a967ceacSHiroshi Shimamoto int i; 62f7627e25SThomas Gleixner 63a967ceacSHiroshi Shimamoto cpu = c->cpu_index; 64a967ceacSHiroshi Shimamoto seq_printf(m, "processor\t: %u\n" 65f7627e25SThomas Gleixner "vendor_id\t: %s\n" 66f7627e25SThomas Gleixner "cpu family\t: %d\n" 67a967ceacSHiroshi Shimamoto "model\t\t: %u\n" 68f7627e25SThomas Gleixner "model name\t: %s\n", 69a967ceacSHiroshi Shimamoto cpu, 70f7627e25SThomas Gleixner c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown", 71f7627e25SThomas Gleixner c->x86, 72f7627e25SThomas Gleixner c->x86_model, 73f7627e25SThomas Gleixner c->x86_model_id[0] ? c->x86_model_id : "unknown"); 74f7627e25SThomas Gleixner 75f7627e25SThomas Gleixner if (c->x86_mask || c->cpuid_level >= 0) 76f7627e25SThomas Gleixner seq_printf(m, "stepping\t: %d\n", c->x86_mask); 77f7627e25SThomas Gleixner else 78f7627e25SThomas Gleixner seq_printf(m, "stepping\t: unknown\n"); 79506ed6b5SAndi Kleen if (c->microcode) 80881e23e5SBorislav Petkov seq_printf(m, "microcode\t: 0x%x\n", c->microcode); 81f7627e25SThomas Gleixner 82f7627e25SThomas Gleixner if (cpu_has(c, X86_FEATURE_TSC)) { 83a967ceacSHiroshi Shimamoto unsigned int freq = cpufreq_quick_get(cpu); 84a967ceacSHiroshi Shimamoto 85f7627e25SThomas Gleixner if (!freq) 86f7627e25SThomas Gleixner freq = cpu_khz; 87f7627e25SThomas Gleixner seq_printf(m, "cpu MHz\t\t: %u.%03u\n", 88f7627e25SThomas Gleixner freq / 1000, (freq % 1000)); 89f7627e25SThomas Gleixner } 90f7627e25SThomas Gleixner 91f7627e25SThomas Gleixner /* Cache size */ 92f7627e25SThomas Gleixner if (c->x86_cache_size >= 0) 93f7627e25SThomas Gleixner seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); 94f7627e25SThomas Gleixner 95a967ceacSHiroshi Shimamoto show_cpuinfo_core(m, c, cpu); 96a967ceacSHiroshi Shimamoto show_cpuinfo_misc(m, c); 97f7627e25SThomas Gleixner 98a967ceacSHiroshi Shimamoto seq_printf(m, "flags\t\t:"); 99f7627e25SThomas Gleixner for (i = 0; i < 32*NCAPINTS; i++) 100a967ceacSHiroshi Shimamoto if (cpu_has(c, i) && x86_cap_flags[i] != NULL) 101f7627e25SThomas Gleixner seq_printf(m, " %s", x86_cap_flags[i]); 102f7627e25SThomas Gleixner 103f84c3a42SHiroshi Shimamoto seq_printf(m, "\nbogomips\t: %lu.%02lu\n", 104f84c3a42SHiroshi Shimamoto c->loops_per_jiffy/(500000/HZ), 105f84c3a42SHiroshi Shimamoto (c->loops_per_jiffy/(5000/HZ)) % 100); 1062aef7720SHiroshi Shimamoto 1072aef7720SHiroshi Shimamoto #ifdef CONFIG_X86_64 1082aef7720SHiroshi Shimamoto if (c->x86_tlbsize > 0) 1092aef7720SHiroshi Shimamoto seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize); 1102aef7720SHiroshi Shimamoto #endif 111f84c3a42SHiroshi Shimamoto seq_printf(m, "clflush size\t: %u\n", c->x86_clflush_size); 1122aef7720SHiroshi Shimamoto seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment); 1132aef7720SHiroshi Shimamoto seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n", 1142aef7720SHiroshi Shimamoto c->x86_phys_bits, c->x86_virt_bits); 115f84c3a42SHiroshi Shimamoto 116f84c3a42SHiroshi Shimamoto seq_printf(m, "power management:"); 117f84c3a42SHiroshi Shimamoto for (i = 0; i < 32; i++) { 118f7627e25SThomas Gleixner if (c->x86_power & (1 << i)) { 119f7627e25SThomas Gleixner if (i < ARRAY_SIZE(x86_power_flags) && 120f7627e25SThomas Gleixner x86_power_flags[i]) 121f7627e25SThomas Gleixner seq_printf(m, "%s%s", 122f7627e25SThomas Gleixner x86_power_flags[i][0] ? " " : "", 123f7627e25SThomas Gleixner x86_power_flags[i]); 124f7627e25SThomas Gleixner else 125f7627e25SThomas Gleixner seq_printf(m, " [%d]", i); 126f7627e25SThomas Gleixner } 127f84c3a42SHiroshi Shimamoto } 128f7627e25SThomas Gleixner 129f84c3a42SHiroshi Shimamoto seq_printf(m, "\n\n"); 130f7627e25SThomas Gleixner 131f7627e25SThomas Gleixner return 0; 132f7627e25SThomas Gleixner } 133f7627e25SThomas Gleixner 134f7627e25SThomas Gleixner static void *c_start(struct seq_file *m, loff_t *pos) 135f7627e25SThomas Gleixner { 1364f062896SRusty Russell *pos = cpumask_next(*pos - 1, cpu_online_mask); 137bc8bcc79SLai Jiangshan if ((*pos) < nr_cpu_ids) 13892cb7612SMike Travis return &cpu_data(*pos); 13992cb7612SMike Travis return NULL; 140f7627e25SThomas Gleixner } 141a967ceacSHiroshi Shimamoto 142f7627e25SThomas Gleixner static void *c_next(struct seq_file *m, void *v, loff_t *pos) 143f7627e25SThomas Gleixner { 144bc8bcc79SLai Jiangshan (*pos)++; 145f7627e25SThomas Gleixner return c_start(m, pos); 146f7627e25SThomas Gleixner } 147a967ceacSHiroshi Shimamoto 148f7627e25SThomas Gleixner static void c_stop(struct seq_file *m, void *v) 149f7627e25SThomas Gleixner { 150f7627e25SThomas Gleixner } 151a967ceacSHiroshi Shimamoto 1528a45eb31SJan Engelhardt const struct seq_operations cpuinfo_op = { 153f7627e25SThomas Gleixner .start = c_start, 154f7627e25SThomas Gleixner .next = c_next, 155f7627e25SThomas Gleixner .stop = c_stop, 156f7627e25SThomas Gleixner .show = show_cpuinfo, 157f7627e25SThomas Gleixner }; 158