1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/timex.h>
4 #include <linux/string.h>
5 #include <linux/seq_file.h>
6 #include <linux/cpufreq.h>
11 * Get CPU information for use by the procfs.
13 static void show_cpuinfo_core(struct seq_file
*m
, struct cpuinfo_x86
*c
,
17 seq_printf(m
, "physical id\t: %d\n", c
->phys_proc_id
);
18 seq_printf(m
, "siblings\t: %d\n",
19 cpumask_weight(topology_core_cpumask(cpu
)));
20 seq_printf(m
, "core id\t\t: %d\n", c
->cpu_core_id
);
21 seq_printf(m
, "cpu cores\t: %d\n", c
->booted_cores
);
22 seq_printf(m
, "apicid\t\t: %d\n", c
->apicid
);
23 seq_printf(m
, "initial apicid\t: %d\n", c
->initial_apicid
);
28 static void show_cpuinfo_misc(struct seq_file
*m
, struct cpuinfo_x86
*c
)
35 "fpu_exception\t: %s\n"
38 static_cpu_has_bug(X86_BUG_FDIV
) ? "yes" : "no",
39 static_cpu_has_bug(X86_BUG_F00F
) ? "yes" : "no",
40 static_cpu_has_bug(X86_BUG_COMA
) ? "yes" : "no",
41 static_cpu_has(X86_FEATURE_FPU
) ? "yes" : "no",
42 static_cpu_has(X86_FEATURE_FPU
) ? "yes" : "no",
46 static void show_cpuinfo_misc(struct seq_file
*m
, struct cpuinfo_x86
*c
)
50 "fpu_exception\t: yes\n"
57 static int show_cpuinfo(struct seq_file
*m
, void *v
)
59 struct cpuinfo_x86
*c
= v
;
64 seq_printf(m
, "processor\t: %u\n"
70 c
->x86_vendor_id
[0] ? c
->x86_vendor_id
: "unknown",
73 c
->x86_model_id
[0] ? c
->x86_model_id
: "unknown");
75 if (c
->x86_stepping
|| c
->cpuid_level
>= 0)
76 seq_printf(m
, "stepping\t: %d\n", c
->x86_stepping
);
78 seq_puts(m
, "stepping\t: unknown\n");
80 seq_printf(m
, "microcode\t: 0x%x\n", c
->microcode
);
82 if (cpu_has(c
, X86_FEATURE_TSC
)) {
83 unsigned int freq
= aperfmperf_get_khz(cpu
);
86 freq
= cpufreq_quick_get(cpu
);
89 seq_printf(m
, "cpu MHz\t\t: %u.%03u\n",
90 freq
/ 1000, (freq
% 1000));
94 if (c
->x86_cache_size
)
95 seq_printf(m
, "cache size\t: %u KB\n", c
->x86_cache_size
);
97 show_cpuinfo_core(m
, c
, cpu
);
98 show_cpuinfo_misc(m
, c
);
100 seq_puts(m
, "flags\t\t:");
101 for (i
= 0; i
< 32*NCAPINTS
; i
++)
102 if (cpu_has(c
, i
) && x86_cap_flags
[i
] != NULL
)
103 seq_printf(m
, " %s", x86_cap_flags
[i
]);
105 seq_puts(m
, "\nbugs\t\t:");
106 for (i
= 0; i
< 32*NBUGINTS
; i
++) {
107 unsigned int bug_bit
= 32*NCAPINTS
+ i
;
109 if (cpu_has_bug(c
, bug_bit
) && x86_bug_flags
[i
])
110 seq_printf(m
, " %s", x86_bug_flags
[i
]);
113 seq_printf(m
, "\nbogomips\t: %lu.%02lu\n",
114 c
->loops_per_jiffy
/(500000/HZ
),
115 (c
->loops_per_jiffy
/(5000/HZ
)) % 100);
118 if (c
->x86_tlbsize
> 0)
119 seq_printf(m
, "TLB size\t: %d 4K pages\n", c
->x86_tlbsize
);
121 seq_printf(m
, "clflush size\t: %u\n", c
->x86_clflush_size
);
122 seq_printf(m
, "cache_alignment\t: %d\n", c
->x86_cache_alignment
);
123 seq_printf(m
, "address sizes\t: %u bits physical, %u bits virtual\n",
124 c
->x86_phys_bits
, c
->x86_virt_bits
);
126 seq_puts(m
, "power management:");
127 for (i
= 0; i
< 32; i
++) {
128 if (c
->x86_power
& (1 << i
)) {
129 if (i
< ARRAY_SIZE(x86_power_flags
) &&
131 seq_printf(m
, "%s%s",
132 x86_power_flags
[i
][0] ? " " : "",
135 seq_printf(m
, " [%d]", i
);
144 static void *c_start(struct seq_file
*m
, loff_t
*pos
)
146 *pos
= cpumask_next(*pos
- 1, cpu_online_mask
);
147 if ((*pos
) < nr_cpu_ids
)
148 return &cpu_data(*pos
);
152 static void *c_next(struct seq_file
*m
, void *v
, loff_t
*pos
)
155 return c_start(m
, pos
);
158 static void c_stop(struct seq_file
*m
, void *v
)
162 const struct seq_operations cpuinfo_op
= {
166 .show
= show_cpuinfo
,