linux/arch/sparc/kernel/sysfs.c
<<
>>
Prefs
   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 void register_nodes(void)
 248{
 249#ifdef CONFIG_NUMA
 250        int i;
 251
 252        for (i = 0; i < MAX_NUMNODES; i++)
 253                register_one_node(i);
 254#endif
 255}
 256
 257static int __init topology_init(void)
 258{
 259        int cpu, ret;
 260
 261        register_nodes();
 262
 263        check_mmu_stats();
 264
 265        for_each_possible_cpu(cpu) {
 266                struct cpu *c = &per_cpu(cpu_devices, cpu);
 267
 268                register_cpu(c, cpu);
 269        }
 270
 271        ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "sparc/topology:online",
 272                                register_cpu_online, unregister_cpu_online);
 273        WARN_ON(ret < 0);
 274        return 0;
 275}
 276
 277subsys_initcall(topology_init);
 278