1 /* sysfs.c: Topology 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/device.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 device *dev, \ 20 struct device_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 DEVICE_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 &dev_attr_immu_tsb_hits_ctx0_8k_tte.attr, 62 &dev_attr_immu_tsb_ticks_ctx0_8k_tte.attr, 63 &dev_attr_immu_tsb_hits_ctx0_64k_tte.attr, 64 &dev_attr_immu_tsb_ticks_ctx0_64k_tte.attr, 65 &dev_attr_immu_tsb_hits_ctx0_4mb_tte.attr, 66 &dev_attr_immu_tsb_ticks_ctx0_4mb_tte.attr, 67 &dev_attr_immu_tsb_hits_ctx0_256mb_tte.attr, 68 &dev_attr_immu_tsb_ticks_ctx0_256mb_tte.attr, 69 &dev_attr_immu_tsb_hits_ctxnon0_8k_tte.attr, 70 &dev_attr_immu_tsb_ticks_ctxnon0_8k_tte.attr, 71 &dev_attr_immu_tsb_hits_ctxnon0_64k_tte.attr, 72 &dev_attr_immu_tsb_ticks_ctxnon0_64k_tte.attr, 73 &dev_attr_immu_tsb_hits_ctxnon0_4mb_tte.attr, 74 &dev_attr_immu_tsb_ticks_ctxnon0_4mb_tte.attr, 75 &dev_attr_immu_tsb_hits_ctxnon0_256mb_tte.attr, 76 &dev_attr_immu_tsb_ticks_ctxnon0_256mb_tte.attr, 77 &dev_attr_dmmu_tsb_hits_ctx0_8k_tte.attr, 78 &dev_attr_dmmu_tsb_ticks_ctx0_8k_tte.attr, 79 &dev_attr_dmmu_tsb_hits_ctx0_64k_tte.attr, 80 &dev_attr_dmmu_tsb_ticks_ctx0_64k_tte.attr, 81 &dev_attr_dmmu_tsb_hits_ctx0_4mb_tte.attr, 82 &dev_attr_dmmu_tsb_ticks_ctx0_4mb_tte.attr, 83 &dev_attr_dmmu_tsb_hits_ctx0_256mb_tte.attr, 84 &dev_attr_dmmu_tsb_ticks_ctx0_256mb_tte.attr, 85 &dev_attr_dmmu_tsb_hits_ctxnon0_8k_tte.attr, 86 &dev_attr_dmmu_tsb_ticks_ctxnon0_8k_tte.attr, 87 &dev_attr_dmmu_tsb_hits_ctxnon0_64k_tte.attr, 88 &dev_attr_dmmu_tsb_ticks_ctxnon0_64k_tte.attr, 89 &dev_attr_dmmu_tsb_hits_ctxnon0_4mb_tte.attr, 90 &dev_attr_dmmu_tsb_ticks_ctxnon0_4mb_tte.attr, 91 &dev_attr_dmmu_tsb_hits_ctxnon0_256mb_tte.attr, 92 &dev_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 static long read_mmustat_enable(void *data __maybe_unused) 102 { 103 unsigned long ra = 0; 104 105 sun4v_mmustat_info(&ra); 106 107 return ra != 0; 108 } 109 110 static long write_mmustat_enable(void *data) 111 { 112 unsigned long ra, orig_ra, *val = data; 113 114 if (*val) 115 ra = __pa(&per_cpu(mmu_stats, smp_processor_id())); 116 else 117 ra = 0UL; 118 119 return sun4v_mmustat_conf(ra, &orig_ra); 120 } 121 122 static ssize_t show_mmustat_enable(struct device *s, 123 struct device_attribute *attr, char *buf) 124 { 125 long val = work_on_cpu(s->id, read_mmustat_enable, NULL); 126 127 return sprintf(buf, "%lx\n", val); 128 } 129 130 static ssize_t store_mmustat_enable(struct device *s, 131 struct device_attribute *attr, const char *buf, 132 size_t count) 133 { 134 unsigned long val; 135 long err; 136 int ret; 137 138 ret = sscanf(buf, "%lu", &val); 139 if (ret != 1) 140 return -EINVAL; 141 142 err = work_on_cpu(s->id, write_mmustat_enable, &val); 143 if (err) 144 return -EIO; 145 146 return count; 147 } 148 149 static DEVICE_ATTR(mmustat_enable, 0644, show_mmustat_enable, store_mmustat_enable); 150 151 static int mmu_stats_supported; 152 153 static int register_mmu_stats(struct device *s) 154 { 155 if (!mmu_stats_supported) 156 return 0; 157 device_create_file(s, &dev_attr_mmustat_enable); 158 return sysfs_create_group(&s->kobj, &mmu_stat_group); 159 } 160 161 #ifdef CONFIG_HOTPLUG_CPU 162 static void unregister_mmu_stats(struct device *s) 163 { 164 if (!mmu_stats_supported) 165 return; 166 sysfs_remove_group(&s->kobj, &mmu_stat_group); 167 device_remove_file(s, &dev_attr_mmustat_enable); 168 } 169 #endif 170 171 #define SHOW_CPUDATA_ULONG_NAME(NAME, MEMBER) \ 172 static ssize_t show_##NAME(struct device *dev, \ 173 struct device_attribute *attr, char *buf) \ 174 { \ 175 cpuinfo_sparc *c = &cpu_data(dev->id); \ 176 return sprintf(buf, "%lu\n", c->MEMBER); \ 177 } 178 179 #define SHOW_CPUDATA_UINT_NAME(NAME, MEMBER) \ 180 static ssize_t show_##NAME(struct device *dev, \ 181 struct device_attribute *attr, char *buf) \ 182 { \ 183 cpuinfo_sparc *c = &cpu_data(dev->id); \ 184 return sprintf(buf, "%u\n", c->MEMBER); \ 185 } 186 187 SHOW_CPUDATA_ULONG_NAME(clock_tick, clock_tick); 188 SHOW_CPUDATA_UINT_NAME(l1_dcache_size, dcache_size); 189 SHOW_CPUDATA_UINT_NAME(l1_dcache_line_size, dcache_line_size); 190 SHOW_CPUDATA_UINT_NAME(l1_icache_size, icache_size); 191 SHOW_CPUDATA_UINT_NAME(l1_icache_line_size, icache_line_size); 192 SHOW_CPUDATA_UINT_NAME(l2_cache_size, ecache_size); 193 SHOW_CPUDATA_UINT_NAME(l2_cache_line_size, ecache_line_size); 194 195 static struct device_attribute cpu_core_attrs[] = { 196 __ATTR(clock_tick, 0444, show_clock_tick, NULL), 197 __ATTR(l1_dcache_size, 0444, show_l1_dcache_size, NULL), 198 __ATTR(l1_dcache_line_size, 0444, show_l1_dcache_line_size, NULL), 199 __ATTR(l1_icache_size, 0444, show_l1_icache_size, NULL), 200 __ATTR(l1_icache_line_size, 0444, show_l1_icache_line_size, NULL), 201 __ATTR(l2_cache_size, 0444, show_l2_cache_size, NULL), 202 __ATTR(l2_cache_line_size, 0444, show_l2_cache_line_size, NULL), 203 }; 204 205 static DEFINE_PER_CPU(struct cpu, cpu_devices); 206 207 static int register_cpu_online(unsigned int cpu) 208 { 209 struct cpu *c = &per_cpu(cpu_devices, cpu); 210 struct device *s = &c->dev; 211 int i; 212 213 for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++) 214 device_create_file(s, &cpu_core_attrs[i]); 215 216 register_mmu_stats(s); 217 return 0; 218 } 219 220 static int unregister_cpu_online(unsigned int cpu) 221 { 222 #ifdef CONFIG_HOTPLUG_CPU 223 struct cpu *c = &per_cpu(cpu_devices, cpu); 224 struct device *s = &c->dev; 225 int i; 226 227 unregister_mmu_stats(s); 228 for (i = 0; i < ARRAY_SIZE(cpu_core_attrs); i++) 229 device_remove_file(s, &cpu_core_attrs[i]); 230 #endif 231 return 0; 232 } 233 234 static void __init check_mmu_stats(void) 235 { 236 unsigned long dummy1, err; 237 238 if (tlb_type != hypervisor) 239 return; 240 241 err = sun4v_mmustat_info(&dummy1); 242 if (!err) 243 mmu_stats_supported = 1; 244 } 245 246 static void register_nodes(void) 247 { 248 #ifdef CONFIG_NUMA 249 int i; 250 251 for (i = 0; i < MAX_NUMNODES; i++) 252 register_one_node(i); 253 #endif 254 } 255 256 static int __init topology_init(void) 257 { 258 int cpu, ret; 259 260 register_nodes(); 261 262 check_mmu_stats(); 263 264 for_each_possible_cpu(cpu) { 265 struct cpu *c = &per_cpu(cpu_devices, cpu); 266 267 register_cpu(c, cpu); 268 } 269 270 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "sparc/topology:online", 271 register_cpu_online, unregister_cpu_online); 272 WARN_ON(ret < 0); 273 return 0; 274 } 275 276 subsys_initcall(topology_init); 277