1 | // SPDX-License-Identifier: GPL-2.0 |
2 | |
3 | #include <linux/debugfs.h> |
4 | |
5 | #include <asm/apic.h> |
6 | #include <asm/processor.h> |
7 | |
8 | #include "cpu.h" |
9 | |
10 | static int cpu_debug_show(struct seq_file *m, void *p) |
11 | { |
12 | unsigned long cpu = (unsigned long)m->private; |
13 | struct cpuinfo_x86 *c = per_cpu_ptr(&cpu_info, cpu); |
14 | |
15 | seq_printf(m, fmt: "online: %d\n" , cpu_online(cpu)); |
16 | if (!c->initialized) |
17 | return 0; |
18 | |
19 | seq_printf(m, fmt: "initial_apicid: %x\n" , c->topo.initial_apicid); |
20 | seq_printf(m, fmt: "apicid: %x\n" , c->topo.apicid); |
21 | seq_printf(m, fmt: "pkg_id: %u\n" , c->topo.pkg_id); |
22 | seq_printf(m, fmt: "die_id: %u\n" , c->topo.die_id); |
23 | seq_printf(m, fmt: "cu_id: %u\n" , c->topo.cu_id); |
24 | seq_printf(m, fmt: "core_id: %u\n" , c->topo.core_id); |
25 | seq_printf(m, fmt: "logical_pkg_id: %u\n" , c->topo.logical_pkg_id); |
26 | seq_printf(m, fmt: "logical_die_id: %u\n" , c->topo.logical_die_id); |
27 | seq_printf(m, fmt: "llc_id: %u\n" , c->topo.llc_id); |
28 | seq_printf(m, fmt: "l2c_id: %u\n" , c->topo.l2c_id); |
29 | seq_printf(m, fmt: "amd_node_id: %u\n" , c->topo.amd_node_id); |
30 | seq_printf(m, fmt: "amd_nodes_per_pkg: %u\n" , topology_amd_nodes_per_pkg()); |
31 | seq_printf(m, fmt: "num_threads: %u\n" , __num_threads_per_package); |
32 | seq_printf(m, fmt: "num_cores: %u\n" , __num_cores_per_package); |
33 | seq_printf(m, fmt: "max_dies_per_pkg: %u\n" , __max_dies_per_package); |
34 | seq_printf(m, fmt: "max_threads_per_core:%u\n" , __max_threads_per_core); |
35 | return 0; |
36 | } |
37 | |
38 | static int cpu_debug_open(struct inode *inode, struct file *file) |
39 | { |
40 | return single_open(file, cpu_debug_show, inode->i_private); |
41 | } |
42 | |
43 | static const struct file_operations dfs_cpu_ops = { |
44 | .open = cpu_debug_open, |
45 | .read = seq_read, |
46 | .llseek = seq_lseek, |
47 | .release = single_release, |
48 | }; |
49 | |
50 | static int dom_debug_show(struct seq_file *m, void *p) |
51 | { |
52 | static const char *domain_names[TOPO_MAX_DOMAIN] = { |
53 | [TOPO_SMT_DOMAIN] = "Thread" , |
54 | [TOPO_CORE_DOMAIN] = "Core" , |
55 | [TOPO_MODULE_DOMAIN] = "Module" , |
56 | [TOPO_TILE_DOMAIN] = "Tile" , |
57 | [TOPO_DIE_DOMAIN] = "Die" , |
58 | [TOPO_DIEGRP_DOMAIN] = "DieGrp" , |
59 | [TOPO_PKG_DOMAIN] = "Package" , |
60 | }; |
61 | unsigned int dom, nthreads = 1; |
62 | |
63 | for (dom = 0; dom < TOPO_MAX_DOMAIN; dom++) { |
64 | nthreads *= x86_topo_system.dom_size[dom]; |
65 | seq_printf(m, fmt: "domain: %-10s shift: %u dom_size: %5u max_threads: %5u\n" , |
66 | domain_names[dom], x86_topo_system.dom_shifts[dom], |
67 | x86_topo_system.dom_size[dom], nthreads); |
68 | } |
69 | return 0; |
70 | } |
71 | |
72 | static int dom_debug_open(struct inode *inode, struct file *file) |
73 | { |
74 | return single_open(file, dom_debug_show, inode->i_private); |
75 | } |
76 | |
77 | static const struct file_operations dfs_dom_ops = { |
78 | .open = dom_debug_open, |
79 | .read = seq_read, |
80 | .llseek = seq_lseek, |
81 | .release = single_release, |
82 | }; |
83 | |
84 | static __init int cpu_init_debugfs(void) |
85 | { |
86 | struct dentry *dir, *base = debugfs_create_dir(name: "topo" , parent: arch_debugfs_dir); |
87 | unsigned long id; |
88 | char name[24]; |
89 | |
90 | debugfs_create_file(name: "domains" , mode: 0444, parent: base, NULL, fops: &dfs_dom_ops); |
91 | |
92 | dir = debugfs_create_dir(name: "cpus" , parent: base); |
93 | for_each_possible_cpu(id) { |
94 | sprintf(buf: name, fmt: "%lu" , id); |
95 | debugfs_create_file(name, mode: 0444, parent: dir, data: (void *)id, fops: &dfs_cpu_ops); |
96 | } |
97 | return 0; |
98 | } |
99 | late_initcall(cpu_init_debugfs); |
100 | |