xref: /linux/arch/sparc/kernel/sysfs.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
208f80073SAdam Buchbinder /* sysfs.c: Topology sysfs support code for sparc64.
3a88b5ba8SSam Ravnborg  *
4a88b5ba8SSam Ravnborg  * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
5a88b5ba8SSam Ravnborg  */
68abf9196SAlexey Dobriyan #include <linux/sched.h>
78a25a2fdSKay Sievers #include <linux/device.h>
8a88b5ba8SSam Ravnborg #include <linux/cpu.h>
9a88b5ba8SSam Ravnborg #include <linux/smp.h>
10a88b5ba8SSam Ravnborg #include <linux/percpu.h>
11a88b5ba8SSam Ravnborg #include <linux/init.h>
12a88b5ba8SSam Ravnborg 
136e6ab2e2SSam Ravnborg #include <asm/cpudata.h>
14a88b5ba8SSam Ravnborg #include <asm/hypervisor.h>
15a88b5ba8SSam Ravnborg #include <asm/spitfire.h>
16a88b5ba8SSam Ravnborg 
17a88b5ba8SSam Ravnborg static DEFINE_PER_CPU(struct hv_mmu_statistics, mmu_stats) __attribute__((aligned(64)));
18a88b5ba8SSam Ravnborg 
19a88b5ba8SSam Ravnborg #define SHOW_MMUSTAT_ULONG(NAME) \
208a25a2fdSKay Sievers static ssize_t show_##NAME(struct device *dev, \
218a25a2fdSKay Sievers 			struct device_attribute *attr, char *buf) \
22a88b5ba8SSam Ravnborg { \
23a88b5ba8SSam Ravnborg 	struct hv_mmu_statistics *p = &per_cpu(mmu_stats, dev->id); \
24a88b5ba8SSam Ravnborg 	return sprintf(buf, "%lu\n", p->NAME); \
25a88b5ba8SSam Ravnborg } \
268a25a2fdSKay Sievers static DEVICE_ATTR(NAME, 0444, show_##NAME, NULL)
27a88b5ba8SSam Ravnborg 
28a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_8k_tte);
29a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_8k_tte);
30a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_64k_tte);
31a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_64k_tte);
32a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_4mb_tte);
33a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_4mb_tte);
34a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_256mb_tte);
35a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_256mb_tte);
36a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_8k_tte);
37a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_8k_tte);
38a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_64k_tte);
39a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_64k_tte);
40a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_4mb_tte);
41a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_4mb_tte);
42a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_256mb_tte);
43a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_256mb_tte);
44a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_8k_tte);
45a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_8k_tte);
46a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_64k_tte);
47a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_64k_tte);
48a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_4mb_tte);
49a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_4mb_tte);
50a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_256mb_tte);
51a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_256mb_tte);
52a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_8k_tte);
53a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_8k_tte);
54a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_64k_tte);
55a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_64k_tte);
56a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_4mb_tte);
57a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_4mb_tte);
58a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_256mb_tte);
59a88b5ba8SSam Ravnborg SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_256mb_tte);
60a88b5ba8SSam Ravnborg 
61a88b5ba8SSam Ravnborg static struct attribute *mmu_stat_attrs[] = {
628a25a2fdSKay Sievers 	&dev_attr_immu_tsb_hits_ctx0_8k_tte.attr,
638a25a2fdSKay Sievers 	&dev_attr_immu_tsb_ticks_ctx0_8k_tte.attr,
648a25a2fdSKay Sievers 	&dev_attr_immu_tsb_hits_ctx0_64k_tte.attr,
658a25a2fdSKay Sievers 	&dev_attr_immu_tsb_ticks_ctx0_64k_tte.attr,
668a25a2fdSKay Sievers 	&dev_attr_immu_tsb_hits_ctx0_4mb_tte.attr,
678a25a2fdSKay Sievers 	&dev_attr_immu_tsb_ticks_ctx0_4mb_tte.attr,
688a25a2fdSKay Sievers 	&dev_attr_immu_tsb_hits_ctx0_256mb_tte.attr,
698a25a2fdSKay Sievers 	&dev_attr_immu_tsb_ticks_ctx0_256mb_tte.attr,
708a25a2fdSKay Sievers 	&dev_attr_immu_tsb_hits_ctxnon0_8k_tte.attr,
718a25a2fdSKay Sievers 	&dev_attr_immu_tsb_ticks_ctxnon0_8k_tte.attr,
728a25a2fdSKay Sievers 	&dev_attr_immu_tsb_hits_ctxnon0_64k_tte.attr,
738a25a2fdSKay Sievers 	&dev_attr_immu_tsb_ticks_ctxnon0_64k_tte.attr,
748a25a2fdSKay Sievers 	&dev_attr_immu_tsb_hits_ctxnon0_4mb_tte.attr,
758a25a2fdSKay Sievers 	&dev_attr_immu_tsb_ticks_ctxnon0_4mb_tte.attr,
768a25a2fdSKay Sievers 	&dev_attr_immu_tsb_hits_ctxnon0_256mb_tte.attr,
778a25a2fdSKay Sievers 	&dev_attr_immu_tsb_ticks_ctxnon0_256mb_tte.attr,
788a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_hits_ctx0_8k_tte.attr,
798a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_ticks_ctx0_8k_tte.attr,
808a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_hits_ctx0_64k_tte.attr,
818a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_ticks_ctx0_64k_tte.attr,
828a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_hits_ctx0_4mb_tte.attr,
838a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_ticks_ctx0_4mb_tte.attr,
848a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_hits_ctx0_256mb_tte.attr,
858a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_ticks_ctx0_256mb_tte.attr,
868a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_hits_ctxnon0_8k_tte.attr,
878a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_ticks_ctxnon0_8k_tte.attr,
888a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_hits_ctxnon0_64k_tte.attr,
898a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_ticks_ctxnon0_64k_tte.attr,
908a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_hits_ctxnon0_4mb_tte.attr,
918a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_ticks_ctxnon0_4mb_tte.attr,
928a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_hits_ctxnon0_256mb_tte.attr,
938a25a2fdSKay Sievers 	&dev_attr_dmmu_tsb_ticks_ctxnon0_256mb_tte.attr,
94a88b5ba8SSam Ravnborg 	NULL,
95a88b5ba8SSam Ravnborg };
96a88b5ba8SSam Ravnborg 
97a88b5ba8SSam Ravnborg static struct attribute_group mmu_stat_group = {
98a88b5ba8SSam Ravnborg 	.attrs = mmu_stat_attrs,
99a88b5ba8SSam Ravnborg 	.name = "mmu_stats",
100a88b5ba8SSam Ravnborg };
101a88b5ba8SSam Ravnborg 
read_mmustat_enable(void * data __maybe_unused)102ea875ec9SThomas Gleixner static long read_mmustat_enable(void *data __maybe_unused)
103a88b5ba8SSam Ravnborg {
104a88b5ba8SSam Ravnborg 	unsigned long ra = 0;
105a88b5ba8SSam Ravnborg 
106a88b5ba8SSam Ravnborg 	sun4v_mmustat_info(&ra);
107a88b5ba8SSam Ravnborg 
108a88b5ba8SSam Ravnborg 	return ra != 0;
109a88b5ba8SSam Ravnborg }
110a88b5ba8SSam Ravnborg 
write_mmustat_enable(void * data)111ea875ec9SThomas Gleixner static long write_mmustat_enable(void *data)
112a88b5ba8SSam Ravnborg {
113ea875ec9SThomas Gleixner 	unsigned long ra, orig_ra, *val = data;
114a88b5ba8SSam Ravnborg 
115ea875ec9SThomas Gleixner 	if (*val)
116a88b5ba8SSam Ravnborg 		ra = __pa(&per_cpu(mmu_stats, smp_processor_id()));
117a88b5ba8SSam Ravnborg 	else
118a88b5ba8SSam Ravnborg 		ra = 0UL;
119a88b5ba8SSam Ravnborg 
120a88b5ba8SSam Ravnborg 	return sun4v_mmustat_conf(ra, &orig_ra);
121a88b5ba8SSam Ravnborg }
122a88b5ba8SSam Ravnborg 
show_mmustat_enable(struct device * s,struct device_attribute * attr,char * buf)1238a25a2fdSKay Sievers static ssize_t show_mmustat_enable(struct device *s,
1248a25a2fdSKay Sievers 				struct device_attribute *attr, char *buf)
125a88b5ba8SSam Ravnborg {
126ea875ec9SThomas Gleixner 	long val = work_on_cpu(s->id, read_mmustat_enable, NULL);
127ea875ec9SThomas Gleixner 
128a88b5ba8SSam Ravnborg 	return sprintf(buf, "%lx\n", val);
129a88b5ba8SSam Ravnborg }
130a88b5ba8SSam Ravnborg 
store_mmustat_enable(struct device * s,struct device_attribute * attr,const char * buf,size_t count)1318a25a2fdSKay Sievers static ssize_t store_mmustat_enable(struct device *s,
1328a25a2fdSKay Sievers 			struct device_attribute *attr, const char *buf,
133a88b5ba8SSam Ravnborg 			size_t count)
134a88b5ba8SSam Ravnborg {
135ea875ec9SThomas Gleixner 	unsigned long val;
136ea875ec9SThomas Gleixner 	long err;
137ea875ec9SThomas Gleixner 	int ret;
138a88b5ba8SSam Ravnborg 
139ea875ec9SThomas Gleixner 	ret = sscanf(buf, "%lu", &val);
140a88b5ba8SSam Ravnborg 	if (ret != 1)
141a88b5ba8SSam Ravnborg 		return -EINVAL;
142a88b5ba8SSam Ravnborg 
143ea875ec9SThomas Gleixner 	err = work_on_cpu(s->id, write_mmustat_enable, &val);
144a88b5ba8SSam Ravnborg 	if (err)
145a88b5ba8SSam Ravnborg 		return -EIO;
146a88b5ba8SSam Ravnborg 
147a88b5ba8SSam Ravnborg 	return count;
148a88b5ba8SSam Ravnborg }
149a88b5ba8SSam Ravnborg 
1508a25a2fdSKay Sievers static DEVICE_ATTR(mmustat_enable, 0644, show_mmustat_enable, store_mmustat_enable);
151a88b5ba8SSam Ravnborg 
152a88b5ba8SSam Ravnborg static int mmu_stats_supported;
153a88b5ba8SSam Ravnborg 
register_mmu_stats(struct device * s)1548a25a2fdSKay Sievers static int register_mmu_stats(struct device *s)
155a88b5ba8SSam Ravnborg {
156a88b5ba8SSam Ravnborg 	if (!mmu_stats_supported)
157a88b5ba8SSam Ravnborg 		return 0;
1588a25a2fdSKay Sievers 	device_create_file(s, &dev_attr_mmustat_enable);
159a88b5ba8SSam Ravnborg 	return sysfs_create_group(&s->kobj, &mmu_stat_group);
160a88b5ba8SSam Ravnborg }
161a88b5ba8SSam Ravnborg 
162a88b5ba8SSam Ravnborg #ifdef CONFIG_HOTPLUG_CPU
unregister_mmu_stats(struct device * s)1638a25a2fdSKay Sievers static void unregister_mmu_stats(struct device *s)
164a88b5ba8SSam Ravnborg {
165a88b5ba8SSam Ravnborg 	if (!mmu_stats_supported)
166a88b5ba8SSam Ravnborg 		return;
167a88b5ba8SSam Ravnborg 	sysfs_remove_group(&s->kobj, &mmu_stat_group);
1688a25a2fdSKay Sievers 	device_remove_file(s, &dev_attr_mmustat_enable);
169a88b5ba8SSam Ravnborg }
170a88b5ba8SSam Ravnborg #endif
171a88b5ba8SSam Ravnborg 
172a88b5ba8SSam Ravnborg #define SHOW_CPUDATA_ULONG_NAME(NAME, MEMBER) \
1738a25a2fdSKay Sievers static ssize_t show_##NAME(struct device *dev, \
1748a25a2fdSKay Sievers 		struct device_attribute *attr, char *buf) \
175a88b5ba8SSam Ravnborg { \
176a88b5ba8SSam Ravnborg 	cpuinfo_sparc *c = &cpu_data(dev->id); \
177a88b5ba8SSam Ravnborg 	return sprintf(buf, "%lu\n", c->MEMBER); \
178a88b5ba8SSam Ravnborg }
179a88b5ba8SSam Ravnborg 
180a88b5ba8SSam Ravnborg #define SHOW_CPUDATA_UINT_NAME(NAME, MEMBER) \
1818a25a2fdSKay Sievers static ssize_t show_##NAME(struct device *dev, \
1828a25a2fdSKay Sievers 		struct device_attribute *attr, char *buf) \
183a88b5ba8SSam Ravnborg { \
184a88b5ba8SSam Ravnborg 	cpuinfo_sparc *c = &cpu_data(dev->id); \
185a88b5ba8SSam Ravnborg 	return sprintf(buf, "%u\n", c->MEMBER); \
186a88b5ba8SSam Ravnborg }
187a88b5ba8SSam Ravnborg 
188a88b5ba8SSam Ravnborg SHOW_CPUDATA_ULONG_NAME(clock_tick, clock_tick);
189a88b5ba8SSam Ravnborg SHOW_CPUDATA_UINT_NAME(l1_dcache_size, dcache_size);
190a88b5ba8SSam Ravnborg SHOW_CPUDATA_UINT_NAME(l1_dcache_line_size, dcache_line_size);
191a88b5ba8SSam Ravnborg SHOW_CPUDATA_UINT_NAME(l1_icache_size, icache_size);
192a88b5ba8SSam Ravnborg SHOW_CPUDATA_UINT_NAME(l1_icache_line_size, icache_line_size);
193a88b5ba8SSam Ravnborg SHOW_CPUDATA_UINT_NAME(l2_cache_size, ecache_size);
194a88b5ba8SSam Ravnborg SHOW_CPUDATA_UINT_NAME(l2_cache_line_size, ecache_line_size);
195a88b5ba8SSam Ravnborg 
1968a25a2fdSKay Sievers static struct device_attribute cpu_core_attrs[] = {
1978a25a2fdSKay Sievers 	__ATTR(clock_tick,          0444, show_clock_tick, NULL),
1988a25a2fdSKay Sievers 	__ATTR(l1_dcache_size,      0444, show_l1_dcache_size, NULL),
1998a25a2fdSKay Sievers 	__ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL),
2008a25a2fdSKay Sievers 	__ATTR(l1_icache_size,      0444, show_l1_icache_size, NULL),
2018a25a2fdSKay Sievers 	__ATTR(l1_icache_line_size, 0444, show_l1_icache_line_size, NULL),
2028a25a2fdSKay Sievers 	__ATTR(l2_cache_size,       0444, show_l2_cache_size, NULL),
2038a25a2fdSKay Sievers 	__ATTR(l2_cache_line_size,  0444, show_l2_cache_line_size, NULL),
204a88b5ba8SSam Ravnborg };
205a88b5ba8SSam Ravnborg 
206a88b5ba8SSam Ravnborg static DEFINE_PER_CPU(struct cpu, cpu_devices);
207a88b5ba8SSam Ravnborg 
register_cpu_online(unsigned int cpu)208e5355cd6SSebastian Andrzej Siewior static int register_cpu_online(unsigned int cpu)
209a88b5ba8SSam Ravnborg {
210a88b5ba8SSam Ravnborg 	struct cpu *c = &per_cpu(cpu_devices, cpu);
2118a25a2fdSKay Sievers 	struct device *s = &c->dev;
212a88b5ba8SSam Ravnborg 	int i;
213a88b5ba8SSam Ravnborg 
214a88b5ba8SSam Ravnborg 	for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
2158a25a2fdSKay Sievers 		device_create_file(s, &cpu_core_attrs[i]);
216a88b5ba8SSam Ravnborg 
217a88b5ba8SSam Ravnborg 	register_mmu_stats(s);
218e5355cd6SSebastian Andrzej Siewior 	return 0;
219a88b5ba8SSam Ravnborg }
220a88b5ba8SSam Ravnborg 
unregister_cpu_online(unsigned int cpu)221e5355cd6SSebastian Andrzej Siewior static int unregister_cpu_online(unsigned int cpu)
222a88b5ba8SSam Ravnborg {
223e5355cd6SSebastian Andrzej Siewior #ifdef CONFIG_HOTPLUG_CPU
224a88b5ba8SSam Ravnborg 	struct cpu *c = &per_cpu(cpu_devices, cpu);
2258a25a2fdSKay Sievers 	struct device *s = &c->dev;
226a88b5ba8SSam Ravnborg 	int i;
227a88b5ba8SSam Ravnborg 
228a88b5ba8SSam Ravnborg 	unregister_mmu_stats(s);
229a88b5ba8SSam Ravnborg 	for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++)
2308a25a2fdSKay Sievers 		device_remove_file(s, &cpu_core_attrs[i]);
231a88b5ba8SSam Ravnborg #endif
232e5355cd6SSebastian Andrzej Siewior 	return 0;
233a88b5ba8SSam Ravnborg }
234a88b5ba8SSam Ravnborg 
check_mmu_stats(void)235a88b5ba8SSam Ravnborg static void __init check_mmu_stats(void)
236a88b5ba8SSam Ravnborg {
237a88b5ba8SSam Ravnborg 	unsigned long dummy1, err;
238a88b5ba8SSam Ravnborg 
239a88b5ba8SSam Ravnborg 	if (tlb_type != hypervisor)
240a88b5ba8SSam Ravnborg 		return;
241a88b5ba8SSam Ravnborg 
242a88b5ba8SSam Ravnborg 	err = sun4v_mmustat_info(&dummy1);
243a88b5ba8SSam Ravnborg 	if (!err)
244a88b5ba8SSam Ravnborg 		mmu_stats_supported = 1;
245a88b5ba8SSam Ravnborg }
246a88b5ba8SSam Ravnborg 
topology_init(void)247a88b5ba8SSam Ravnborg static int __init topology_init(void)
248a88b5ba8SSam Ravnborg {
249e5355cd6SSebastian Andrzej Siewior 	int cpu, ret;
250a88b5ba8SSam Ravnborg 
251a88b5ba8SSam Ravnborg 	check_mmu_stats();
252a88b5ba8SSam Ravnborg 
253a88b5ba8SSam Ravnborg 	for_each_possible_cpu(cpu) {
254a88b5ba8SSam Ravnborg 		struct cpu *c = &per_cpu(cpu_devices, cpu);
255a88b5ba8SSam Ravnborg 
256a88b5ba8SSam Ravnborg 		register_cpu(c, cpu);
257a88b5ba8SSam Ravnborg 	}
258a88b5ba8SSam Ravnborg 
259e5355cd6SSebastian Andrzej Siewior 	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "sparc/topology:online",
260e5355cd6SSebastian Andrzej Siewior 				register_cpu_online, unregister_cpu_online);
261e5355cd6SSebastian Andrzej Siewior 	WARN_ON(ret < 0);
262a88b5ba8SSam Ravnborg 	return 0;
263a88b5ba8SSam Ravnborg }
264a88b5ba8SSam Ravnborg 
265a88b5ba8SSam Ravnborg subsys_initcall(topology_init);
266