sysfs.c (7987B)
1// SPDX-License-Identifier: GPL-2.0 2/* sysfs.c: Topology sysfs support code for sparc64. 3 * 4 * Copyright (C) 2007 David S. Miller <davem@davemloft.net> 5 */ 6#include <linux/sched.h> 7#include <linux/device.h> 8#include <linux/cpu.h> 9#include <linux/smp.h> 10#include <linux/percpu.h> 11#include <linux/init.h> 12 13#include <asm/cpudata.h> 14#include <asm/hypervisor.h> 15#include <asm/spitfire.h> 16 17static DEFINE_PER_CPU(struct hv_mmu_statistics, mmu_stats) __attribute__((aligned(64))); 18 19#define SHOW_MMUSTAT_ULONG(NAME) \ 20static ssize_t show_##NAME(struct device *dev, \ 21 struct device_attribute *attr, char *buf) \ 22{ \ 23 struct hv_mmu_statistics *p = &per_cpu(mmu_stats, dev->id); \ 24 return sprintf(buf, "%lu\n", p->NAME); \ 25} \ 26static DEVICE_ATTR(NAME, 0444, show_##NAME, NULL) 27 28SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_8k_tte); 29SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_8k_tte); 30SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_64k_tte); 31SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_64k_tte); 32SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_4mb_tte); 33SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_4mb_tte); 34SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_256mb_tte); 35SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_256mb_tte); 36SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_8k_tte); 37SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_8k_tte); 38SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_64k_tte); 39SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_64k_tte); 40SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_4mb_tte); 41SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_4mb_tte); 42SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_256mb_tte); 43SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_256mb_tte); 44SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_8k_tte); 45SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_8k_tte); 46SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_64k_tte); 47SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_64k_tte); 48SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_4mb_tte); 49SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_4mb_tte); 50SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_256mb_tte); 51SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_256mb_tte); 52SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_8k_tte); 53SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_8k_tte); 54SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_64k_tte); 55SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_64k_tte); 56SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_4mb_tte); 57SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_4mb_tte); 58SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_256mb_tte); 59SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_256mb_tte); 60 61static struct attribute *mmu_stat_attrs[] = { 62 &dev_attr_immu_tsb_hits_ctx0_8k_tte.attr, 63 &dev_attr_immu_tsb_ticks_ctx0_8k_tte.attr, 64 &dev_attr_immu_tsb_hits_ctx0_64k_tte.attr, 65 &dev_attr_immu_tsb_ticks_ctx0_64k_tte.attr, 66 &dev_attr_immu_tsb_hits_ctx0_4mb_tte.attr, 67 &dev_attr_immu_tsb_ticks_ctx0_4mb_tte.attr, 68 &dev_attr_immu_tsb_hits_ctx0_256mb_tte.attr, 69 &dev_attr_immu_tsb_ticks_ctx0_256mb_tte.attr, 70 &dev_attr_immu_tsb_hits_ctxnon0_8k_tte.attr, 71 &dev_attr_immu_tsb_ticks_ctxnon0_8k_tte.attr, 72 &dev_attr_immu_tsb_hits_ctxnon0_64k_tte.attr, 73 &dev_attr_immu_tsb_ticks_ctxnon0_64k_tte.attr, 74 &dev_attr_immu_tsb_hits_ctxnon0_4mb_tte.attr, 75 &dev_attr_immu_tsb_ticks_ctxnon0_4mb_tte.attr, 76 &dev_attr_immu_tsb_hits_ctxnon0_256mb_tte.attr, 77 &dev_attr_immu_tsb_ticks_ctxnon0_256mb_tte.attr, 78 &dev_attr_dmmu_tsb_hits_ctx0_8k_tte.attr, 79 &dev_attr_dmmu_tsb_ticks_ctx0_8k_tte.attr, 80 &dev_attr_dmmu_tsb_hits_ctx0_64k_tte.attr, 81 &dev_attr_dmmu_tsb_ticks_ctx0_64k_tte.attr, 82 &dev_attr_dmmu_tsb_hits_ctx0_4mb_tte.attr, 83 &dev_attr_dmmu_tsb_ticks_ctx0_4mb_tte.attr, 84 &dev_attr_dmmu_tsb_hits_ctx0_256mb_tte.attr, 85 &dev_attr_dmmu_tsb_ticks_ctx0_256mb_tte.attr, 86 &dev_attr_dmmu_tsb_hits_ctxnon0_8k_tte.attr, 87 &dev_attr_dmmu_tsb_ticks_ctxnon0_8k_tte.attr, 88 &dev_attr_dmmu_tsb_hits_ctxnon0_64k_tte.attr, 89 &dev_attr_dmmu_tsb_ticks_ctxnon0_64k_tte.attr, 90 &dev_attr_dmmu_tsb_hits_ctxnon0_4mb_tte.attr, 91 &dev_attr_dmmu_tsb_ticks_ctxnon0_4mb_tte.attr, 92 &dev_attr_dmmu_tsb_hits_ctxnon0_256mb_tte.attr, 93 &dev_attr_dmmu_tsb_ticks_ctxnon0_256mb_tte.attr, 94 NULL, 95}; 96 97static struct attribute_group mmu_stat_group = { 98 .attrs = mmu_stat_attrs, 99 .name = "mmu_stats", 100}; 101 102static long read_mmustat_enable(void *data __maybe_unused) 103{ 104 unsigned long ra = 0; 105 106 sun4v_mmustat_info(&ra); 107 108 return ra != 0; 109} 110 111static long write_mmustat_enable(void *data) 112{ 113 unsigned long ra, orig_ra, *val = data; 114 115 if (*val) 116 ra = __pa(&per_cpu(mmu_stats, smp_processor_id())); 117 else 118 ra = 0UL; 119 120 return sun4v_mmustat_conf(ra, &orig_ra); 121} 122 123static ssize_t show_mmustat_enable(struct device *s, 124 struct device_attribute *attr, char *buf) 125{ 126 long val = work_on_cpu(s->id, read_mmustat_enable, NULL); 127 128 return sprintf(buf, "%lx\n", val); 129} 130 131static ssize_t store_mmustat_enable(struct device *s, 132 struct device_attribute *attr, const char *buf, 133 size_t count) 134{ 135 unsigned long val; 136 long err; 137 int ret; 138 139 ret = sscanf(buf, "%lu", &val); 140 if (ret != 1) 141 return -EINVAL; 142 143 err = work_on_cpu(s->id, write_mmustat_enable, &val); 144 if (err) 145 return -EIO; 146 147 return count; 148} 149 150static DEVICE_ATTR(mmustat_enable, 0644, show_mmustat_enable, store_mmustat_enable); 151 152static int mmu_stats_supported; 153 154static int register_mmu_stats(struct device *s) 155{ 156 if (!mmu_stats_supported) 157 return 0; 158 device_create_file(s, &dev_attr_mmustat_enable); 159 return sysfs_create_group(&s->kobj, &mmu_stat_group); 160} 161 162#ifdef CONFIG_HOTPLUG_CPU 163static void unregister_mmu_stats(struct device *s) 164{ 165 if (!mmu_stats_supported) 166 return; 167 sysfs_remove_group(&s->kobj, &mmu_stat_group); 168 device_remove_file(s, &dev_attr_mmustat_enable); 169} 170#endif 171 172#define SHOW_CPUDATA_ULONG_NAME(NAME, MEMBER) \ 173static ssize_t show_##NAME(struct device *dev, \ 174 struct device_attribute *attr, char *buf) \ 175{ \ 176 cpuinfo_sparc *c = &cpu_data(dev->id); \ 177 return sprintf(buf, "%lu\n", c->MEMBER); \ 178} 179 180#define SHOW_CPUDATA_UINT_NAME(NAME, MEMBER) \ 181static ssize_t show_##NAME(struct device *dev, \ 182 struct device_attribute *attr, char *buf) \ 183{ \ 184 cpuinfo_sparc *c = &cpu_data(dev->id); \ 185 return sprintf(buf, "%u\n", c->MEMBER); \ 186} 187 188SHOW_CPUDATA_ULONG_NAME(clock_tick, clock_tick); 189SHOW_CPUDATA_UINT_NAME(l1_dcache_size, dcache_size); 190SHOW_CPUDATA_UINT_NAME(l1_dcache_line_size, dcache_line_size); 191SHOW_CPUDATA_UINT_NAME(l1_icache_size, icache_size); 192SHOW_CPUDATA_UINT_NAME(l1_icache_line_size, icache_line_size); 193SHOW_CPUDATA_UINT_NAME(l2_cache_size, ecache_size); 194SHOW_CPUDATA_UINT_NAME(l2_cache_line_size, ecache_line_size); 195 196static struct device_attribute cpu_core_attrs[] = { 197 __ATTR(clock_tick, 0444, show_clock_tick, NULL), 198 __ATTR(l1_dcache_size, 0444, show_l1_dcache_size, NULL), 199 __ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL), 200 __ATTR(l1_icache_size, 0444, show_l1_icache_size, NULL), 201 __ATTR(l1_icache_line_size, 0444, show_l1_icache_line_size, NULL), 202 __ATTR(l2_cache_size, 0444, show_l2_cache_size, NULL), 203 __ATTR(l2_cache_line_size, 0444, show_l2_cache_line_size, NULL), 204}; 205 206static DEFINE_PER_CPU(struct cpu, cpu_devices); 207 208static int register_cpu_online(unsigned int cpu) 209{ 210 struct cpu *c = &per_cpu(cpu_devices, cpu); 211 struct device *s = &c->dev; 212 int i; 213 214 for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++) 215 device_create_file(s, &cpu_core_attrs[i]); 216 217 register_mmu_stats(s); 218 return 0; 219} 220 221static int unregister_cpu_online(unsigned int cpu) 222{ 223#ifdef CONFIG_HOTPLUG_CPU 224 struct cpu *c = &per_cpu(cpu_devices, cpu); 225 struct device *s = &c->dev; 226 int i; 227 228 unregister_mmu_stats(s); 229 for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++) 230 device_remove_file(s, &cpu_core_attrs[i]); 231#endif 232 return 0; 233} 234 235static void __init check_mmu_stats(void) 236{ 237 unsigned long dummy1, err; 238 239 if (tlb_type != hypervisor) 240 return; 241 242 err = sun4v_mmustat_info(&dummy1); 243 if (!err) 244 mmu_stats_supported = 1; 245} 246 247static int __init topology_init(void) 248{ 249 int cpu, ret; 250 251 check_mmu_stats(); 252 253 for_each_possible_cpu(cpu) { 254 struct cpu *c = &per_cpu(cpu_devices, cpu); 255 256 register_cpu(c, cpu); 257 } 258 259 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "sparc/topology:online", 260 register_cpu_online, unregister_cpu_online); 261 WARN_ON(ret < 0); 262 return 0; 263} 264 265subsys_initcall(topology_init);