1 #include <linux/smp.h> 2 #include <linux/timex.h> 3 #include <linux/string.h> 4 #include <asm/semaphore.h> 5 #include <linux/seq_file.h> 6 #include <linux/cpufreq.h> 7 8 /* 9 * Get CPU information for use by the procfs. 10 */ 11 static int show_cpuinfo(struct seq_file *m, void *v) 12 { 13 struct cpuinfo_x86 *c = v; 14 int i, n = 0; 15 int fpu_exception; 16 17 #ifdef CONFIG_SMP 18 n = c->cpu_index; 19 #endif 20 seq_printf(m, "processor\t: %d\n" 21 "vendor_id\t: %s\n" 22 "cpu family\t: %d\n" 23 "model\t\t: %d\n" 24 "model name\t: %s\n", 25 n, 26 c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown", 27 c->x86, 28 c->x86_model, 29 c->x86_model_id[0] ? c->x86_model_id : "unknown"); 30 31 if (c->x86_mask || c->cpuid_level >= 0) 32 seq_printf(m, "stepping\t: %d\n", c->x86_mask); 33 else 34 seq_printf(m, "stepping\t: unknown\n"); 35 36 if ( cpu_has(c, X86_FEATURE_TSC) ) { 37 unsigned int freq = cpufreq_quick_get(n); 38 if (!freq) 39 freq = cpu_khz; 40 seq_printf(m, "cpu MHz\t\t: %u.%03u\n", 41 freq / 1000, (freq % 1000)); 42 } 43 44 /* Cache size */ 45 if (c->x86_cache_size >= 0) 46 seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); 47 #ifdef CONFIG_X86_HT 48 if (c->x86_max_cores * smp_num_siblings > 1) { 49 seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); 50 seq_printf(m, "siblings\t: %d\n", 51 cpus_weight(per_cpu(cpu_core_map, n))); 52 seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); 53 seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); 54 } 55 #endif 56 57 /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */ 58 fpu_exception = c->hard_math && (ignore_fpu_irq || cpu_has_fpu); 59 seq_printf(m, "fdiv_bug\t: %s\n" 60 "hlt_bug\t\t: %s\n" 61 "f00f_bug\t: %s\n" 62 "coma_bug\t: %s\n" 63 "fpu\t\t: %s\n" 64 "fpu_exception\t: %s\n" 65 "cpuid level\t: %d\n" 66 "wp\t\t: %s\n" 67 "flags\t\t:", 68 c->fdiv_bug ? "yes" : "no", 69 c->hlt_works_ok ? "no" : "yes", 70 c->f00f_bug ? "yes" : "no", 71 c->coma_bug ? "yes" : "no", 72 c->hard_math ? "yes" : "no", 73 fpu_exception ? "yes" : "no", 74 c->cpuid_level, 75 c->wp_works_ok ? "yes" : "no"); 76 77 for ( i = 0 ; i < 32*NCAPINTS ; i++ ) 78 if ( test_bit(i, c->x86_capability) && 79 x86_cap_flags[i] != NULL ) 80 seq_printf(m, " %s", x86_cap_flags[i]); 81 82 for (i = 0; i < 32; i++) 83 if (c->x86_power & (1 << i)) { 84 if (i < ARRAY_SIZE(x86_power_flags) && 85 x86_power_flags[i]) 86 seq_printf(m, "%s%s", 87 x86_power_flags[i][0]?" ":"", 88 x86_power_flags[i]); 89 else 90 seq_printf(m, " [%d]", i); 91 } 92 93 seq_printf(m, "\nbogomips\t: %lu.%02lu\n", 94 c->loops_per_jiffy/(500000/HZ), 95 (c->loops_per_jiffy/(5000/HZ)) % 100); 96 seq_printf(m, "clflush size\t: %u\n\n", c->x86_clflush_size); 97 98 return 0; 99 } 100 101 static void *c_start(struct seq_file *m, loff_t *pos) 102 { 103 if (*pos == 0) /* just in case, cpu 0 is not the first */ 104 *pos = first_cpu(cpu_online_map); 105 if ((*pos) < NR_CPUS && cpu_online(*pos)) 106 return &cpu_data(*pos); 107 return NULL; 108 } 109 static void *c_next(struct seq_file *m, void *v, loff_t *pos) 110 { 111 *pos = next_cpu(*pos, cpu_online_map); 112 return c_start(m, pos); 113 } 114 static void c_stop(struct seq_file *m, void *v) 115 { 116 } 117 const struct seq_operations cpuinfo_op = { 118 .start = c_start, 119 .next = c_next, 120 .stop = c_stop, 121 .show = show_cpuinfo, 122 }; 123