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>
9 * Get CPU information for use by the procfs.
11 static int show_cpuinfo(struct seq_file
*m
, void *v
)
14 * These flag bits must match the definitions in <asm/cpufeature.h>.
15 * NULL means this bit is undefined or reserved; either way it doesn't
16 * have meaning as far as Linux is concerned. Note that it's important
17 * to realize there is a difference between this table and CPUID -- if
18 * applications want to get the raw CPUID data, they should access
19 * /dev/cpu/<cpu_nr>/cpuid instead.
21 static const char * const x86_cap_flags
[] = {
23 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
24 "cx8", "apic", NULL
, "sep", "mtrr", "pge", "mca", "cmov",
25 "pat", "pse36", "pn", "clflush", NULL
, "dts", "acpi", "mmx",
26 "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
29 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
30 NULL
, NULL
, NULL
, "syscall", NULL
, NULL
, NULL
, NULL
,
31 NULL
, NULL
, NULL
, "mp", "nx", NULL
, "mmxext", NULL
,
32 NULL
, "fxsr_opt", "pdpe1gb", "rdtscp", NULL
, "lm",
35 /* Transmeta-defined */
36 "recovery", "longrun", NULL
, "lrti", NULL
, NULL
, NULL
, NULL
,
37 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
38 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
39 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
41 /* Other (Linux-defined) */
42 "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
43 NULL
, NULL
, NULL
, NULL
,
44 "constant_tsc", "up", NULL
, "arch_perfmon",
45 "pebs", "bts", NULL
, "sync_rdtsc",
46 "rep_good", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
47 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
49 /* Intel-defined (#2) */
50 "pni", NULL
, NULL
, "monitor", "ds_cpl", "vmx", "smx", "est",
51 "tm2", "ssse3", "cid", NULL
, NULL
, "cx16", "xtpr", NULL
,
52 NULL
, NULL
, "dca", "sse4_1", "sse4_2", NULL
, NULL
, "popcnt",
53 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
55 /* VIA/Cyrix/Centaur-defined */
56 NULL
, NULL
, "rng", "rng_en", NULL
, NULL
, "ace", "ace_en",
57 "ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL
, NULL
,
58 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
59 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
61 /* AMD-defined (#2) */
62 "lahf_lm", "cmp_legacy", "svm", "extapic",
63 "cr8_legacy", "abm", "sse4a", "misalignsse",
64 "3dnowprefetch", "osvw", "ibs", "sse5",
65 "skinit", "wdt", NULL
, NULL
,
66 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
67 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
69 /* Auxiliary (Linux-defined) */
70 "ida", NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
71 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
72 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
73 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
75 static const char * const x86_power_flags
[] = {
76 "ts", /* temperature sensor */
77 "fid", /* frequency id control */
78 "vid", /* voltage id control */
79 "ttp", /* thermal trip */
84 "", /* constant_tsc - moved to flags */
87 struct cpuinfo_x86
*c
= v
;
94 seq_printf(m
, "processor\t: %d\n"
100 c
->x86_vendor_id
[0] ? c
->x86_vendor_id
: "unknown",
103 c
->x86_model_id
[0] ? c
->x86_model_id
: "unknown");
105 if (c
->x86_mask
|| c
->cpuid_level
>= 0)
106 seq_printf(m
, "stepping\t: %d\n", c
->x86_mask
);
108 seq_printf(m
, "stepping\t: unknown\n");
110 if ( cpu_has(c
, X86_FEATURE_TSC
) ) {
111 unsigned int freq
= cpufreq_quick_get(n
);
114 seq_printf(m
, "cpu MHz\t\t: %u.%03u\n",
115 freq
/ 1000, (freq
% 1000));
119 if (c
->x86_cache_size
>= 0)
120 seq_printf(m
, "cache size\t: %d KB\n", c
->x86_cache_size
);
122 if (c
->x86_max_cores
* smp_num_siblings
> 1) {
123 seq_printf(m
, "physical id\t: %d\n", c
->phys_proc_id
);
124 seq_printf(m
, "siblings\t: %d\n",
125 cpus_weight(per_cpu(cpu_core_map
, n
)));
126 seq_printf(m
, "core id\t\t: %d\n", c
->cpu_core_id
);
127 seq_printf(m
, "cpu cores\t: %d\n", c
->booted_cores
);
131 /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */
132 fpu_exception
= c
->hard_math
&& (ignore_fpu_irq
|| cpu_has_fpu
);
133 seq_printf(m
, "fdiv_bug\t: %s\n"
138 "fpu_exception\t: %s\n"
139 "cpuid level\t: %d\n"
142 c
->fdiv_bug
? "yes" : "no",
143 c
->hlt_works_ok
? "no" : "yes",
144 c
->f00f_bug
? "yes" : "no",
145 c
->coma_bug
? "yes" : "no",
146 c
->hard_math
? "yes" : "no",
147 fpu_exception
? "yes" : "no",
149 c
->wp_works_ok
? "yes" : "no");
151 for ( i
= 0 ; i
< 32*NCAPINTS
; i
++ )
152 if ( test_bit(i
, c
->x86_capability
) &&
153 x86_cap_flags
[i
] != NULL
)
154 seq_printf(m
, " %s", x86_cap_flags
[i
]);
156 for (i
= 0; i
< 32; i
++)
157 if (c
->x86_power
& (1 << i
)) {
158 if (i
< ARRAY_SIZE(x86_power_flags
) &&
160 seq_printf(m
, "%s%s",
161 x86_power_flags
[i
][0]?" ":"",
164 seq_printf(m
, " [%d]", i
);
167 seq_printf(m
, "\nbogomips\t: %lu.%02lu\n",
168 c
->loops_per_jiffy
/(500000/HZ
),
169 (c
->loops_per_jiffy
/(5000/HZ
)) % 100);
170 seq_printf(m
, "clflush size\t: %u\n\n", c
->x86_clflush_size
);
175 static void *c_start(struct seq_file
*m
, loff_t
*pos
)
177 if (*pos
== 0) /* just in case, cpu 0 is not the first */
178 *pos
= first_cpu(cpu_online_map
);
179 if ((*pos
) < NR_CPUS
&& cpu_online(*pos
))
180 return &cpu_data(*pos
);
183 static void *c_next(struct seq_file
*m
, void *v
, loff_t
*pos
)
185 *pos
= next_cpu(*pos
, cpu_online_map
);
186 return c_start(m
, pos
);
188 static void c_stop(struct seq_file
*m
, void *v
)
191 struct seq_operations cpuinfo_op
= {
195 .show
= show_cpuinfo
,