xref: /openbmc/linux/arch/x86/kernel/cpu/proc.c (revision f3eca381)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2f7627e25SThomas Gleixner #include <linux/smp.h>
3f7627e25SThomas Gleixner #include <linux/timex.h>
4f7627e25SThomas Gleixner #include <linux/string.h>
5f7627e25SThomas Gleixner #include <linux/seq_file.h>
6890da9cfSLinus Torvalds #include <linux/cpufreq.h>
7f7627e25SThomas Gleixner 
87d5905dcSRafael J. Wysocki #include "cpu.h"
97d5905dcSRafael J. Wysocki 
1014442a15SSean Christopherson #ifdef CONFIG_X86_VMX_FEATURE_NAMES
1114442a15SSean Christopherson extern const char * const x86_vmx_flags[NVMXINTS*32];
1214442a15SSean Christopherson #endif
1314442a15SSean Christopherson 
14f7627e25SThomas Gleixner /*
15f7627e25SThomas Gleixner  *	Get CPU information for use by the procfs.
16f7627e25SThomas Gleixner  */
17a967ceacSHiroshi Shimamoto static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c,
18a967ceacSHiroshi Shimamoto 			      unsigned int cpu)
19a967ceacSHiroshi Shimamoto {
20327f4387SJaswinder Singh Rajput #ifdef CONFIG_SMP
21a967ceacSHiroshi Shimamoto 	seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
227d79a7bdSBartosz Golaszewski 	seq_printf(m, "siblings\t: %d\n",
237d79a7bdSBartosz Golaszewski 		   cpumask_weight(topology_core_cpumask(cpu)));
24a967ceacSHiroshi Shimamoto 	seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
25a967ceacSHiroshi Shimamoto 	seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
2601aaea1aSYinghai Lu 	seq_printf(m, "apicid\t\t: %d\n", c->apicid);
2701aaea1aSYinghai Lu 	seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid);
28a967ceacSHiroshi Shimamoto #endif
29a967ceacSHiroshi Shimamoto }
30a967ceacSHiroshi Shimamoto 
31327f4387SJaswinder Singh Rajput #ifdef CONFIG_X86_32
32a967ceacSHiroshi Shimamoto static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
33a967ceacSHiroshi Shimamoto {
34a967ceacSHiroshi Shimamoto 	seq_printf(m,
35a967ceacSHiroshi Shimamoto 		   "fdiv_bug\t: %s\n"
36a967ceacSHiroshi Shimamoto 		   "f00f_bug\t: %s\n"
37a967ceacSHiroshi Shimamoto 		   "coma_bug\t: %s\n"
38a967ceacSHiroshi Shimamoto 		   "fpu\t\t: %s\n"
39a967ceacSHiroshi Shimamoto 		   "fpu_exception\t: %s\n"
40a967ceacSHiroshi Shimamoto 		   "cpuid level\t: %d\n"
416415813bSMathias Krause 		   "wp\t\t: yes\n",
4267e87d43SBorislav Petkov 		   boot_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no",
4367e87d43SBorislav Petkov 		   boot_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no",
4467e87d43SBorislav Petkov 		   boot_cpu_has_bug(X86_BUG_COMA) ? "yes" : "no",
4567e87d43SBorislav Petkov 		   boot_cpu_has(X86_FEATURE_FPU) ? "yes" : "no",
4667e87d43SBorislav Petkov 		   boot_cpu_has(X86_FEATURE_FPU) ? "yes" : "no",
476415813bSMathias Krause 		   c->cpuid_level);
48a967ceacSHiroshi Shimamoto }
492aef7720SHiroshi Shimamoto #else
502aef7720SHiroshi Shimamoto static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
512aef7720SHiroshi Shimamoto {
522aef7720SHiroshi Shimamoto 	seq_printf(m,
532aef7720SHiroshi Shimamoto 		   "fpu\t\t: yes\n"
542aef7720SHiroshi Shimamoto 		   "fpu_exception\t: yes\n"
552aef7720SHiroshi Shimamoto 		   "cpuid level\t: %d\n"
562aef7720SHiroshi Shimamoto 		   "wp\t\t: yes\n",
572aef7720SHiroshi Shimamoto 		   c->cpuid_level);
582aef7720SHiroshi Shimamoto }
592aef7720SHiroshi Shimamoto #endif
60a967ceacSHiroshi Shimamoto 
61f7627e25SThomas Gleixner static int show_cpuinfo(struct seq_file *m, void *v)
62f7627e25SThomas Gleixner {
63f7627e25SThomas Gleixner 	struct cpuinfo_x86 *c = v;
64141168c3SKevin Winchester 	unsigned int cpu;
65a967ceacSHiroshi Shimamoto 	int i;
66f7627e25SThomas Gleixner 
67a967ceacSHiroshi Shimamoto 	cpu = c->cpu_index;
68a967ceacSHiroshi Shimamoto 	seq_printf(m, "processor\t: %u\n"
69f7627e25SThomas Gleixner 		   "vendor_id\t: %s\n"
70f7627e25SThomas Gleixner 		   "cpu family\t: %d\n"
71a967ceacSHiroshi Shimamoto 		   "model\t\t: %u\n"
72f7627e25SThomas Gleixner 		   "model name\t: %s\n",
73a967ceacSHiroshi Shimamoto 		   cpu,
74f7627e25SThomas Gleixner 		   c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
75f7627e25SThomas Gleixner 		   c->x86,
76f7627e25SThomas Gleixner 		   c->x86_model,
77f7627e25SThomas Gleixner 		   c->x86_model_id[0] ? c->x86_model_id : "unknown");
78f7627e25SThomas Gleixner 
79b399151cSJia Zhang 	if (c->x86_stepping || c->cpuid_level >= 0)
80b399151cSJia Zhang 		seq_printf(m, "stepping\t: %d\n", c->x86_stepping);
81f7627e25SThomas Gleixner 	else
823736708fSRasmus Villemoes 		seq_puts(m, "stepping\t: unknown\n");
83506ed6b5SAndi Kleen 	if (c->microcode)
84881e23e5SBorislav Petkov 		seq_printf(m, "microcode\t: 0x%x\n", c->microcode);
85f7627e25SThomas Gleixner 
86890da9cfSLinus Torvalds 	if (cpu_has(c, X86_FEATURE_TSC)) {
87*f3eca381SThomas Gleixner 		unsigned int freq = arch_freq_get_on_cpu(cpu);
88890da9cfSLinus Torvalds 
89890da9cfSLinus Torvalds 		if (!freq)
907d5905dcSRafael J. Wysocki 			freq = cpufreq_quick_get(cpu);
917d5905dcSRafael J. Wysocki 		if (!freq)
92890da9cfSLinus Torvalds 			freq = cpu_khz;
93f7627e25SThomas Gleixner 		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
94890da9cfSLinus Torvalds 			   freq / 1000, (freq % 1000));
95890da9cfSLinus Torvalds 	}
96f7627e25SThomas Gleixner 
97f7627e25SThomas Gleixner 	/* Cache size */
9824dbc600SGustavo A. R. Silva 	if (c->x86_cache_size)
9924dbc600SGustavo A. R. Silva 		seq_printf(m, "cache size\t: %u KB\n", c->x86_cache_size);
100f7627e25SThomas Gleixner 
101a967ceacSHiroshi Shimamoto 	show_cpuinfo_core(m, c, cpu);
102a967ceacSHiroshi Shimamoto 	show_cpuinfo_misc(m, c);
103f7627e25SThomas Gleixner 
1043736708fSRasmus Villemoes 	seq_puts(m, "flags\t\t:");
105f7627e25SThomas Gleixner 	for (i = 0; i < 32*NCAPINTS; i++)
106a967ceacSHiroshi Shimamoto 		if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
107f7627e25SThomas Gleixner 			seq_printf(m, " %s", x86_cap_flags[i]);
108f7627e25SThomas Gleixner 
10914442a15SSean Christopherson #ifdef CONFIG_X86_VMX_FEATURE_NAMES
11014442a15SSean Christopherson 	if (cpu_has(c, X86_FEATURE_VMX) && c->vmx_capability[0]) {
11114442a15SSean Christopherson 		seq_puts(m, "\nvmx flags\t:");
11214442a15SSean Christopherson 		for (i = 0; i < 32*NVMXINTS; i++) {
11314442a15SSean Christopherson 			if (test_bit(i, (unsigned long *)c->vmx_capability) &&
11414442a15SSean Christopherson 			    x86_vmx_flags[i] != NULL)
11514442a15SSean Christopherson 				seq_printf(m, " %s", x86_vmx_flags[i]);
11614442a15SSean Christopherson 		}
11714442a15SSean Christopherson 	}
11814442a15SSean Christopherson #endif
11914442a15SSean Christopherson 
1203736708fSRasmus Villemoes 	seq_puts(m, "\nbugs\t\t:");
12180a208bdSBorislav Petkov 	for (i = 0; i < 32*NBUGINTS; i++) {
12280a208bdSBorislav Petkov 		unsigned int bug_bit = 32*NCAPINTS + i;
12380a208bdSBorislav Petkov 
12480a208bdSBorislav Petkov 		if (cpu_has_bug(c, bug_bit) && x86_bug_flags[i])
12580a208bdSBorislav Petkov 			seq_printf(m, " %s", x86_bug_flags[i]);
12680a208bdSBorislav Petkov 	}
12780a208bdSBorislav Petkov 
128f84c3a42SHiroshi Shimamoto 	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
129f84c3a42SHiroshi Shimamoto 		   c->loops_per_jiffy/(500000/HZ),
130f84c3a42SHiroshi Shimamoto 		   (c->loops_per_jiffy/(5000/HZ)) % 100);
1312aef7720SHiroshi Shimamoto 
1322aef7720SHiroshi Shimamoto #ifdef CONFIG_X86_64
1332aef7720SHiroshi Shimamoto 	if (c->x86_tlbsize > 0)
1342aef7720SHiroshi Shimamoto 		seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
1352aef7720SHiroshi Shimamoto #endif
136f84c3a42SHiroshi Shimamoto 	seq_printf(m, "clflush size\t: %u\n", c->x86_clflush_size);
1372aef7720SHiroshi Shimamoto 	seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment);
1382aef7720SHiroshi Shimamoto 	seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n",
1392aef7720SHiroshi Shimamoto 		   c->x86_phys_bits, c->x86_virt_bits);
140f84c3a42SHiroshi Shimamoto 
1413736708fSRasmus Villemoes 	seq_puts(m, "power management:");
142f84c3a42SHiroshi Shimamoto 	for (i = 0; i < 32; i++) {
143f7627e25SThomas Gleixner 		if (c->x86_power & (1 << i)) {
144f7627e25SThomas Gleixner 			if (i < ARRAY_SIZE(x86_power_flags) &&
145f7627e25SThomas Gleixner 			    x86_power_flags[i])
146f7627e25SThomas Gleixner 				seq_printf(m, "%s%s",
147f7627e25SThomas Gleixner 					   x86_power_flags[i][0] ? " " : "",
148f7627e25SThomas Gleixner 					   x86_power_flags[i]);
149f7627e25SThomas Gleixner 			else
150f7627e25SThomas Gleixner 				seq_printf(m, " [%d]", i);
151f7627e25SThomas Gleixner 		}
152f84c3a42SHiroshi Shimamoto 	}
153f7627e25SThomas Gleixner 
1543736708fSRasmus Villemoes 	seq_puts(m, "\n\n");
155f7627e25SThomas Gleixner 
156f7627e25SThomas Gleixner 	return 0;
157f7627e25SThomas Gleixner }
158f7627e25SThomas Gleixner 
159f7627e25SThomas Gleixner static void *c_start(struct seq_file *m, loff_t *pos)
160f7627e25SThomas Gleixner {
1614f062896SRusty Russell 	*pos = cpumask_next(*pos - 1, cpu_online_mask);
162bc8bcc79SLai Jiangshan 	if ((*pos) < nr_cpu_ids)
16392cb7612SMike Travis 		return &cpu_data(*pos);
16492cb7612SMike Travis 	return NULL;
165f7627e25SThomas Gleixner }
166a967ceacSHiroshi Shimamoto 
167f7627e25SThomas Gleixner static void *c_next(struct seq_file *m, void *v, loff_t *pos)
168f7627e25SThomas Gleixner {
169bc8bcc79SLai Jiangshan 	(*pos)++;
170f7627e25SThomas Gleixner 	return c_start(m, pos);
171f7627e25SThomas Gleixner }
172a967ceacSHiroshi Shimamoto 
173f7627e25SThomas Gleixner static void c_stop(struct seq_file *m, void *v)
174f7627e25SThomas Gleixner {
175f7627e25SThomas Gleixner }
176a967ceacSHiroshi Shimamoto 
1778a45eb31SJan Engelhardt const struct seq_operations cpuinfo_op = {
178f7627e25SThomas Gleixner 	.start	= c_start,
179f7627e25SThomas Gleixner 	.next	= c_next,
180f7627e25SThomas Gleixner 	.stop	= c_stop,
181f7627e25SThomas Gleixner 	.show	= show_cpuinfo,
182f7627e25SThomas Gleixner };
183