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 17 static DEFINE_PER_CPU(struct hv_mmu_statistics, mmu_stats) __attribute__((aligned(64))); 18 19 #define SHOW_MMUSTAT_ULONG(NAME) \ 20 static 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 } \ 26 static DEVICE_ATTR(NAME, 0444, show_##NAME, NULL) 27 28 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_8k_tte); 29 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_8k_tte); 30 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_64k_tte); 31 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_64k_tte); 32 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_4mb_tte); 33 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_4mb_tte); 34 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctx0_256mb_tte); 35 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctx0_256mb_tte); 36 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_8k_tte); 37 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_8k_tte); 38 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_64k_tte); 39 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_64k_tte); 40 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_4mb_tte); 41 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_4mb_tte); 42 SHOW_MMUSTAT_ULONG(immu_tsb_hits_ctxnon0_256mb_tte); 43 SHOW_MMUSTAT_ULONG(immu_tsb_ticks_ctxnon0_256mb_tte); 44 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_8k_tte); 45 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_8k_tte); 46 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_64k_tte); 47 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_64k_tte); 48 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_4mb_tte); 49 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_4mb_tte); 50 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctx0_256mb_tte); 51 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctx0_256mb_tte); 52 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_8k_tte); 53 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_8k_tte); 54 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_64k_tte); 55 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_64k_tte); 56 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_4mb_tte); 57 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_4mb_tte); 58 SHOW_MMUSTAT_ULONG(dmmu_tsb_hits_ctxnon0_256mb_tte); 59 SHOW_MMUSTAT_ULONG(dmmu_tsb_ticks_ctxnon0_256mb_tte); 60 61 static 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 97 static struct attribute_group mmu_stat_group = { 98 .attrs = mmu_stat_attrs, 99 .name = "mmu_stats", 100 }; 101 102 static 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 111 static 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 123 static 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 131 static 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 150 static DEVICE_ATTR(mmustat_enable, 0644, show_mmustat_enable, store_mmustat_enable); 151 152 static int mmu_stats_supported; 153 154 static 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 163 static 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) \ 173 static 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) \ 181 static 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 188 SHOW_CPUDATA_ULONG_NAME(clock_tick, clock_tick); 189 SHOW_CPUDATA_UINT_NAME(l1_dcache_size, dcache_size); 190 SHOW_CPUDATA_UINT_NAME(l1_dcache_line_size, dcache_line_size); 191 SHOW_CPUDATA_UINT_NAME(l1_icache_size, icache_size); 192 SHOW_CPUDATA_UINT_NAME(l1_icache_line_size, icache_line_size); 193 SHOW_CPUDATA_UINT_NAME(l2_cache_size, ecache_size); 194 SHOW_CPUDATA_UINT_NAME(l2_cache_line_size, ecache_line_size); 195 196 static 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 206 static DEFINE_PER_CPU(struct cpu, cpu_devices); 207 208 static 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 221 static 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 235 static 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 247 static 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 265 subsys_initcall(topology_init); 266