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 /* 30a967ceacSHiroshi Shimamoto * We use exception 16 if we have hardware math and we've either seen 31a967ceacSHiroshi Shimamoto * it or the CPU claims it is internal 32a967ceacSHiroshi Shimamoto */ 33a967ceacSHiroshi Shimamoto int fpu_exception = c->hard_math && (ignore_fpu_irq || cpu_has_fpu); 34a967ceacSHiroshi Shimamoto seq_printf(m, 35a967ceacSHiroshi Shimamoto "fdiv_bug\t: %s\n" 36a967ceacSHiroshi Shimamoto "hlt_bug\t\t: %s\n" 37a967ceacSHiroshi Shimamoto "f00f_bug\t: %s\n" 38a967ceacSHiroshi Shimamoto "coma_bug\t: %s\n" 39a967ceacSHiroshi Shimamoto "fpu\t\t: %s\n" 40a967ceacSHiroshi Shimamoto "fpu_exception\t: %s\n" 41a967ceacSHiroshi Shimamoto "cpuid level\t: %d\n" 42a967ceacSHiroshi Shimamoto "wp\t\t: %s\n", 43a967ceacSHiroshi Shimamoto c->fdiv_bug ? "yes" : "no", 44a967ceacSHiroshi Shimamoto c->hlt_works_ok ? "no" : "yes", 45a967ceacSHiroshi Shimamoto c->f00f_bug ? "yes" : "no", 46a967ceacSHiroshi Shimamoto c->coma_bug ? "yes" : "no", 47a967ceacSHiroshi Shimamoto c->hard_math ? "yes" : "no", 48a967ceacSHiroshi Shimamoto fpu_exception ? "yes" : "no", 49a967ceacSHiroshi Shimamoto c->cpuid_level, 50a967ceacSHiroshi Shimamoto c->wp_works_ok ? "yes" : "no"); 51a967ceacSHiroshi Shimamoto } 522aef7720SHiroshi Shimamoto #else 532aef7720SHiroshi Shimamoto static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c) 542aef7720SHiroshi Shimamoto { 552aef7720SHiroshi Shimamoto seq_printf(m, 562aef7720SHiroshi Shimamoto "fpu\t\t: yes\n" 572aef7720SHiroshi Shimamoto "fpu_exception\t: yes\n" 582aef7720SHiroshi Shimamoto "cpuid level\t: %d\n" 592aef7720SHiroshi Shimamoto "wp\t\t: yes\n", 602aef7720SHiroshi Shimamoto c->cpuid_level); 612aef7720SHiroshi Shimamoto } 622aef7720SHiroshi Shimamoto #endif 63a967ceacSHiroshi Shimamoto 64f7627e25SThomas Gleixner static int show_cpuinfo(struct seq_file *m, void *v) 65f7627e25SThomas Gleixner { 66f7627e25SThomas Gleixner struct cpuinfo_x86 *c = v; 67a967ceacSHiroshi Shimamoto unsigned int cpu = 0; 68a967ceacSHiroshi Shimamoto int i; 69f7627e25SThomas Gleixner 70f7627e25SThomas Gleixner #ifdef CONFIG_SMP 71a967ceacSHiroshi Shimamoto cpu = c->cpu_index; 72f7627e25SThomas Gleixner #endif 73a967ceacSHiroshi Shimamoto seq_printf(m, "processor\t: %u\n" 74f7627e25SThomas Gleixner "vendor_id\t: %s\n" 75f7627e25SThomas Gleixner "cpu family\t: %d\n" 76a967ceacSHiroshi Shimamoto "model\t\t: %u\n" 77f7627e25SThomas Gleixner "model name\t: %s\n", 78a967ceacSHiroshi Shimamoto cpu, 79f7627e25SThomas Gleixner c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown", 80f7627e25SThomas Gleixner c->x86, 81f7627e25SThomas Gleixner c->x86_model, 82f7627e25SThomas Gleixner c->x86_model_id[0] ? c->x86_model_id : "unknown"); 83f7627e25SThomas Gleixner 84f7627e25SThomas Gleixner if (c->x86_mask || c->cpuid_level >= 0) 85f7627e25SThomas Gleixner seq_printf(m, "stepping\t: %d\n", c->x86_mask); 86f7627e25SThomas Gleixner else 87f7627e25SThomas Gleixner seq_printf(m, "stepping\t: unknown\n"); 88f7627e25SThomas Gleixner 89f7627e25SThomas Gleixner if (cpu_has(c, X86_FEATURE_TSC)) { 90a967ceacSHiroshi Shimamoto unsigned int freq = cpufreq_quick_get(cpu); 91a967ceacSHiroshi Shimamoto 92f7627e25SThomas Gleixner if (!freq) 93f7627e25SThomas Gleixner freq = cpu_khz; 94f7627e25SThomas Gleixner seq_printf(m, "cpu MHz\t\t: %u.%03u\n", 95f7627e25SThomas Gleixner freq / 1000, (freq % 1000)); 96f7627e25SThomas Gleixner } 97f7627e25SThomas Gleixner 98f7627e25SThomas Gleixner /* Cache size */ 99f7627e25SThomas Gleixner if (c->x86_cache_size >= 0) 100f7627e25SThomas Gleixner seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); 101f7627e25SThomas Gleixner 102a967ceacSHiroshi Shimamoto show_cpuinfo_core(m, c, cpu); 103a967ceacSHiroshi Shimamoto show_cpuinfo_misc(m, c); 104f7627e25SThomas Gleixner 105a967ceacSHiroshi Shimamoto seq_printf(m, "flags\t\t:"); 106f7627e25SThomas Gleixner for (i = 0; i < 32*NCAPINTS; i++) 107a967ceacSHiroshi Shimamoto if (cpu_has(c, i) && x86_cap_flags[i] != NULL) 108f7627e25SThomas Gleixner seq_printf(m, " %s", x86_cap_flags[i]); 109f7627e25SThomas Gleixner 110f84c3a42SHiroshi Shimamoto seq_printf(m, "\nbogomips\t: %lu.%02lu\n", 111f84c3a42SHiroshi Shimamoto c->loops_per_jiffy/(500000/HZ), 112f84c3a42SHiroshi Shimamoto (c->loops_per_jiffy/(5000/HZ)) % 100); 1132aef7720SHiroshi Shimamoto 1142aef7720SHiroshi Shimamoto #ifdef CONFIG_X86_64 1152aef7720SHiroshi Shimamoto if (c->x86_tlbsize > 0) 1162aef7720SHiroshi Shimamoto seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize); 1172aef7720SHiroshi Shimamoto #endif 118f84c3a42SHiroshi Shimamoto seq_printf(m, "clflush size\t: %u\n", c->x86_clflush_size); 1192aef7720SHiroshi Shimamoto #ifdef CONFIG_X86_64 1202aef7720SHiroshi Shimamoto seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment); 1212aef7720SHiroshi Shimamoto seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n", 1222aef7720SHiroshi Shimamoto c->x86_phys_bits, c->x86_virt_bits); 1232aef7720SHiroshi Shimamoto #endif 124f84c3a42SHiroshi Shimamoto 125f84c3a42SHiroshi Shimamoto seq_printf(m, "power management:"); 126f84c3a42SHiroshi Shimamoto for (i = 0; i < 32; i++) { 127f7627e25SThomas Gleixner if (c->x86_power & (1 << i)) { 128f7627e25SThomas Gleixner if (i < ARRAY_SIZE(x86_power_flags) && 129f7627e25SThomas Gleixner x86_power_flags[i]) 130f7627e25SThomas Gleixner seq_printf(m, "%s%s", 131f7627e25SThomas Gleixner x86_power_flags[i][0]?" ":"", 132f7627e25SThomas Gleixner x86_power_flags[i]); 133f7627e25SThomas Gleixner else 134f7627e25SThomas Gleixner seq_printf(m, " [%d]", i); 135f7627e25SThomas Gleixner } 136f84c3a42SHiroshi Shimamoto } 137f7627e25SThomas Gleixner 138f84c3a42SHiroshi Shimamoto seq_printf(m, "\n\n"); 139f7627e25SThomas Gleixner 140f7627e25SThomas Gleixner return 0; 141f7627e25SThomas Gleixner } 142f7627e25SThomas Gleixner 143f7627e25SThomas Gleixner static void *c_start(struct seq_file *m, loff_t *pos) 144f7627e25SThomas Gleixner { 14592cb7612SMike Travis if (*pos == 0) /* just in case, cpu 0 is not the first */ 1464f062896SRusty Russell *pos = cpumask_first(cpu_online_mask); 147bc8bcc79SLai Jiangshan else 1484f062896SRusty Russell *pos = cpumask_next(*pos - 1, cpu_online_mask); 149bc8bcc79SLai Jiangshan if ((*pos) < nr_cpu_ids) 15092cb7612SMike Travis return &cpu_data(*pos); 15192cb7612SMike Travis return NULL; 152f7627e25SThomas Gleixner } 153a967ceacSHiroshi Shimamoto 154f7627e25SThomas Gleixner static void *c_next(struct seq_file *m, void *v, loff_t *pos) 155f7627e25SThomas Gleixner { 156bc8bcc79SLai Jiangshan (*pos)++; 157f7627e25SThomas Gleixner return c_start(m, pos); 158f7627e25SThomas Gleixner } 159a967ceacSHiroshi Shimamoto 160f7627e25SThomas Gleixner static void c_stop(struct seq_file *m, void *v) 161f7627e25SThomas Gleixner { 162f7627e25SThomas Gleixner } 163a967ceacSHiroshi Shimamoto 1648a45eb31SJan Engelhardt const struct seq_operations cpuinfo_op = { 165f7627e25SThomas Gleixner .start = c_start, 166f7627e25SThomas Gleixner .next = c_next, 167f7627e25SThomas Gleixner .stop = c_stop, 168f7627e25SThomas Gleixner .show = show_cpuinfo, 169f7627e25SThomas Gleixner }; 170