cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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);