xref: /linux/arch/x86/kernel/cpu/proc.c (revision ed3174d93c342b8b2eeba6bbd124707d55304a7b)
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