xref: /openbmc/linux/arch/sparc/kernel/sysfs.c (revision 4800cd83)
1 /* sysfs.c: Toplogy sysfs support code for sparc64.
2  *
3  * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
4  */
5 #include <linux/sched.h>
6 #include <linux/sysdev.h>
7 #include <linux/cpu.h>
8 #include <linux/smp.h>
9 #include <linux/percpu.h>
10 #include <linux/init.h>
11 
12 #include <asm/cpudata.h>
13 #include <asm/hypervisor.h>
14 #include <asm/spitfire.h>
15 
16 static DEFINE_PER_CPU(struct hv_mmu_statistics, mmu_stats) __attribute__((aligned(64)));
17 
18 #define SHOW_MMUSTAT_ULONG(NAME) \
19 static ssize_t show_##NAME(struct sys_device *dev, \
20 			struct sysdev_attribute *attr, char *buf) \
21 { \
22 	struct hv_mmu_statistics *p = &per_cpu(mmu_stats, dev->id); \
23 	return sprintf(buf, "%lu\n", p->NAME); \
24 } \
25 static SYSDEV_ATTR(NAME, 0444, show_##NAME, NULL)
26 
27 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_8k_tte);
28 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_8k_tte);
29 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_64k_tte);
30 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_64k_tte);
31 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_4mb_tte);
32 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_4mb_tte);
33 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_256mb_tte);
34 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_256mb_tte);
35 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_8k_tte);
36 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_8k_tte);
37 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_64k_tte);
38 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_64k_tte);
39 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_4mb_tte);
40 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_4mb_tte);
41 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_256mb_tte);
42 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_256mb_tte);
43 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_8k_tte);
44 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_8k_tte);
45 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_64k_tte);
46 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_64k_tte);
47 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_4mb_tte);
48 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_4mb_tte);
49 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_256mb_tte);
50 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_256mb_tte);
51 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_8k_tte);
52 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_8k_tte);
53 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_64k_tte);
54 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_64k_tte);
55 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_4mb_tte);
56 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_4mb_tte);
57 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_256mb_tte);
58 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_256mb_tte);
59 
60 static struct attribute *mmu_stat_attrs[] = {
61 	&attr_immu_tsb_hits_ctx0_8k_tte.attr,
62 	&attr_immu_tsb_ticks_ctx0_8k_tte.attr,
63 	&attr_immu_tsb_hits_ctx0_64k_tte.attr,
64 	&attr_immu_tsb_ticks_ctx0_64k_tte.attr,
65 	&attr_immu_tsb_hits_ctx0_4mb_tte.attr,
66 	&attr_immu_tsb_ticks_ctx0_4mb_tte.attr,
67 	&attr_immu_tsb_hits_ctx0_256mb_tte.attr,
68 	&attr_immu_tsb_ticks_ctx0_256mb_tte.attr,
69 	&attr_immu_tsb_hits_ctxnon0_8k_tte.attr,
70 	&attr_immu_tsb_ticks_ctxnon0_8k_tte.attr,
71 	&attr_immu_tsb_hits_ctxnon0_64k_tte.attr,
72 	&attr_immu_tsb_ticks_ctxnon0_64k_tte.attr,
73 	&attr_immu_tsb_hits_ctxnon0_4mb_tte.attr,
74 	&attr_immu_tsb_ticks_ctxnon0_4mb_tte.attr,
75 	&attr_immu_tsb_hits_ctxnon0_256mb_tte.attr,
76 	&attr_immu_tsb_ticks_ctxnon0_256mb_tte.attr,
77 	&attr_dmmu_tsb_hits_ctx0_8k_tte.attr,
78 	&attr_dmmu_tsb_ticks_ctx0_8k_tte.attr,
79 	&attr_dmmu_tsb_hits_ctx0_64k_tte.attr,
80 	&attr_dmmu_tsb_ticks_ctx0_64k_tte.attr,
81 	&attr_dmmu_tsb_hits_ctx0_4mb_tte.attr,
82 	&attr_dmmu_tsb_ticks_ctx0_4mb_tte.attr,
83 	&attr_dmmu_tsb_hits_ctx0_256mb_tte.attr,
84 	&attr_dmmu_tsb_ticks_ctx0_256mb_tte.attr,
85 	&attr_dmmu_tsb_hits_ctxnon0_8k_tte.attr,
86 	&attr_dmmu_tsb_ticks_ctxnon0_8k_tte.attr,
87 	&attr_dmmu_tsb_hits_ctxnon0_64k_tte.attr,
88 	&attr_dmmu_tsb_ticks_ctxnon0_64k_tte.attr,
89 	&attr_dmmu_tsb_hits_ctxnon0_4mb_tte.attr,
90 	&attr_dmmu_tsb_ticks_ctxnon0_4mb_tte.attr,
91 	&attr_dmmu_tsb_hits_ctxnon0_256mb_tte.attr,
92 	&attr_dmmu_tsb_ticks_ctxnon0_256mb_tte.attr,
93 	NULL,
94 };
95 
96 static struct attribute_group mmu_stat_group = {
97 	.attrs = mmu_stat_attrs,
98 	.name = "mmu_stats",
99 };
100 
101 /* XXX convert to rusty's on_one_cpu */
102 static unsigned long run_on_cpu(unsigned long cpu,
103 			        unsigned long (*func)(unsigned long),
104 				unsigned long arg)
105 {
106 	cpumask_t old_affinity = current->cpus_allowed;
107 	unsigned long ret;
108 
109 	/* should return -EINVAL to userspace */
110 	if (set_cpus_allowed_ptr(current, cpumask_of(cpu)))
111 		return 0;
112 
113 	ret = func(arg);
114 
115 	set_cpus_allowed_ptr(current, &old_affinity);
116 
117 	return ret;
118 }
119 
120 static unsigned long read_mmustat_enable(unsigned long junk)
121 {
122 	unsigned long ra = 0;
123 
124 	sun4v_mmustat_info(&ra);
125 
126 	return ra != 0;
127 }
128 
129 static unsigned long write_mmustat_enable(unsigned long val)
130 {
131 	unsigned long ra, orig_ra;
132 
133 	if (val)
134 		ra = __pa(&per_cpu(mmu_stats, smp_processor_id()));
135 	else
136 		ra = 0UL;
137 
138 	return sun4v_mmustat_conf(ra, &orig_ra);
139 }
140 
141 static ssize_t show_mmustat_enable(struct sys_device *s,
142 				struct sysdev_attribute *attr, char *buf)
143 {
144 	unsigned long val = run_on_cpu(s->id, read_mmustat_enable, 0);
145 	return sprintf(buf, "%lx\n", val);
146 }
147 
148 static ssize_t store_mmustat_enable(struct sys_device *s,
149 			struct sysdev_attribute *attr, const char *buf,
150 			size_t count)
151 {
152 	unsigned long val, err;
153 	int ret = sscanf(buf, "%ld", &val);
154 
155 	if (ret != 1)
156 		return -EINVAL;
157 
158 	err = run_on_cpu(s->id, write_mmustat_enable, val);
159 	if (err)
160 		return -EIO;
161 
162 	return count;
163 }
164 
165 static SYSDEV_ATTR(mmustat_enable, 0644, show_mmustat_enable, store_mmustat_enable);
166 
167 static int mmu_stats_supported;
168 
169 static int register_mmu_stats(struct sys_device *s)
170 {
171 	if (!mmu_stats_supported)
172 		return 0;
173 	sysdev_create_file(s, &attr_mmustat_enable);
174 	return sysfs_create_group(&s->kobj, &mmu_stat_group);
175 }
176 
177 #ifdef CONFIG_HOTPLUG_CPU
178 static void unregister_mmu_stats(struct sys_device *s)
179 {
180 	if (!mmu_stats_supported)
181 		return;
182 	sysfs_remove_group(&s->kobj, &mmu_stat_group);
183 	sysdev_remove_file(s, &attr_mmustat_enable);
184 }
185 #endif
186 
187 #define SHOW_CPUDATA_ULONG_NAME(NAME, MEMBER) \
188 static ssize_t show_##NAME(struct sys_device *dev, \
189 		struct sysdev_attribute *attr, char *buf) \
190 { \
191 	cpuinfo_sparc *c = &cpu_data(dev->id); \
192 	return sprintf(buf, "%lu\n", c->MEMBER); \
193 }
194 
195 #define SHOW_CPUDATA_UINT_NAME(NAME, MEMBER) \
196 static ssize_t show_##NAME(struct sys_device *dev, \
197 		struct sysdev_attribute *attr, char *buf) \
198 { \
199 	cpuinfo_sparc *c = &cpu_data(dev->id); \
200 	return sprintf(buf, "%u\n", c->MEMBER); \
201 }
202 
203 SHOW_CPUDATA_ULONG_NAME(clock_tick, clock_tick);
204 SHOW_CPUDATA_UINT_NAME(l1_dcache_size, dcache_size);
205 SHOW_CPUDATA_UINT_NAME(l1_dcache_line_size, dcache_line_size);
206 SHOW_CPUDATA_UINT_NAME(l1_icache_size, icache_size);
207 SHOW_CPUDATA_UINT_NAME(l1_icache_line_size, icache_line_size);
208 SHOW_CPUDATA_UINT_NAME(l2_cache_size, ecache_size);
209 SHOW_CPUDATA_UINT_NAME(l2_cache_line_size, ecache_line_size);
210 
211 static struct sysdev_attribute cpu_core_attrs[] = {
212 	_SYSDEV_ATTR(clock_tick,          0444, show_clock_tick, NULL),
213 	_SYSDEV_ATTR(l1_dcache_size,      0444, show_l1_dcache_size, NULL),
214 	_SYSDEV_ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL),
215 	_SYSDEV_ATTR(l1_icache_size,      0444, show_l1_icache_size, NULL),
216 	_SYSDEV_ATTR(l1_icache_line_size, 0444, show_l1_icache_line_size, NULL),
217 	_SYSDEV_ATTR(l2_cache_size,       0444, show_l2_cache_size, NULL),
218 	_SYSDEV_ATTR(l2_cache_line_size,  0444, show_l2_cache_line_size, NULL),
219 };
220 
221 static DEFINE_PER_CPU(struct cpu, cpu_devices);
222 
223 static void register_cpu_online(unsigned int cpu)
224 {
225 	struct cpu *c = &per_cpu(cpu_devices, cpu);
226 	struct sys_device *s = &c->sysdev;
227 	int i;
228 
229 	for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
230 		sysdev_create_file(s, &cpu_core_attrs[i]);
231 
232 	register_mmu_stats(s);
233 }
234 
235 #ifdef CONFIG_HOTPLUG_CPU
236 static void unregister_cpu_online(unsigned int cpu)
237 {
238 	struct cpu *c = &per_cpu(cpu_devices, cpu);
239 	struct sys_device *s = &c->sysdev;
240 	int i;
241 
242 	unregister_mmu_stats(s);
243 	for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
244 		sysdev_remove_file(s, &cpu_core_attrs[i]);
245 }
246 #endif
247 
248 static int __cpuinit sysfs_cpu_notify(struct notifier_block *self,
249 				      unsigned long action, void *hcpu)
250 {
251 	unsigned int cpu = (unsigned int)(long)hcpu;
252 
253 	switch (action) {
254 	case CPU_ONLINE:
255 	case CPU_ONLINE_FROZEN:
256 		register_cpu_online(cpu);
257 		break;
258 #ifdef CONFIG_HOTPLUG_CPU
259 	case CPU_DEAD:
260 	case CPU_DEAD_FROZEN:
261 		unregister_cpu_online(cpu);
262 		break;
263 #endif
264 	}
265 	return NOTIFY_OK;
266 }
267 
268 static struct notifier_block __cpuinitdata sysfs_cpu_nb = {
269 	.notifier_call	= sysfs_cpu_notify,
270 };
271 
272 static void __init check_mmu_stats(void)
273 {
274 	unsigned long dummy1, err;
275 
276 	if (tlb_type != hypervisor)
277 		return;
278 
279 	err = sun4v_mmustat_info(&dummy1);
280 	if (!err)
281 		mmu_stats_supported = 1;
282 }
283 
284 static void register_nodes(void)
285 {
286 #ifdef CONFIG_NUMA
287 	int i;
288 
289 	for (i = 0; i < MAX_NUMNODES; i++)
290 		register_one_node(i);
291 #endif
292 }
293 
294 static int __init topology_init(void)
295 {
296 	int cpu;
297 
298 	register_nodes();
299 
300 	check_mmu_stats();
301 
302 	register_cpu_notifier(&sysfs_cpu_nb);
303 
304 	for_each_possible_cpu(cpu) {
305 		struct cpu *c = &per_cpu(cpu_devices, cpu);
306 
307 		register_cpu(c, cpu);
308 		if (cpu_online(cpu))
309 			register_cpu_online(cpu);
310 	}
311 
312 	return 0;
313 }
314 
315 subsys_initcall(topology_init);
316