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

v3d_debugfs.c (7451B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/* Copyright (C) 2014-2018 Broadcom */
      3
      4#include <linux/circ_buf.h>
      5#include <linux/ctype.h>
      6#include <linux/debugfs.h>
      7#include <linux/pm_runtime.h>
      8#include <linux/seq_file.h>
      9#include <linux/string_helpers.h>
     10
     11#include <drm/drm_debugfs.h>
     12
     13#include "v3d_drv.h"
     14#include "v3d_regs.h"
     15
     16#define REGDEF(reg) { reg, #reg }
     17struct v3d_reg_def {
     18	u32 reg;
     19	const char *name;
     20};
     21
     22static const struct v3d_reg_def v3d_hub_reg_defs[] = {
     23	REGDEF(V3D_HUB_AXICFG),
     24	REGDEF(V3D_HUB_UIFCFG),
     25	REGDEF(V3D_HUB_IDENT0),
     26	REGDEF(V3D_HUB_IDENT1),
     27	REGDEF(V3D_HUB_IDENT2),
     28	REGDEF(V3D_HUB_IDENT3),
     29	REGDEF(V3D_HUB_INT_STS),
     30	REGDEF(V3D_HUB_INT_MSK_STS),
     31
     32	REGDEF(V3D_MMU_CTL),
     33	REGDEF(V3D_MMU_VIO_ADDR),
     34	REGDEF(V3D_MMU_VIO_ID),
     35	REGDEF(V3D_MMU_DEBUG_INFO),
     36};
     37
     38static const struct v3d_reg_def v3d_gca_reg_defs[] = {
     39	REGDEF(V3D_GCA_SAFE_SHUTDOWN),
     40	REGDEF(V3D_GCA_SAFE_SHUTDOWN_ACK),
     41};
     42
     43static const struct v3d_reg_def v3d_core_reg_defs[] = {
     44	REGDEF(V3D_CTL_IDENT0),
     45	REGDEF(V3D_CTL_IDENT1),
     46	REGDEF(V3D_CTL_IDENT2),
     47	REGDEF(V3D_CTL_MISCCFG),
     48	REGDEF(V3D_CTL_INT_STS),
     49	REGDEF(V3D_CTL_INT_MSK_STS),
     50	REGDEF(V3D_CLE_CT0CS),
     51	REGDEF(V3D_CLE_CT0CA),
     52	REGDEF(V3D_CLE_CT0EA),
     53	REGDEF(V3D_CLE_CT1CS),
     54	REGDEF(V3D_CLE_CT1CA),
     55	REGDEF(V3D_CLE_CT1EA),
     56
     57	REGDEF(V3D_PTB_BPCA),
     58	REGDEF(V3D_PTB_BPCS),
     59
     60	REGDEF(V3D_GMP_STATUS),
     61	REGDEF(V3D_GMP_CFG),
     62	REGDEF(V3D_GMP_VIO_ADDR),
     63
     64	REGDEF(V3D_ERR_FDBGO),
     65	REGDEF(V3D_ERR_FDBGB),
     66	REGDEF(V3D_ERR_FDBGS),
     67	REGDEF(V3D_ERR_STAT),
     68};
     69
     70static const struct v3d_reg_def v3d_csd_reg_defs[] = {
     71	REGDEF(V3D_CSD_STATUS),
     72	REGDEF(V3D_CSD_CURRENT_CFG0),
     73	REGDEF(V3D_CSD_CURRENT_CFG1),
     74	REGDEF(V3D_CSD_CURRENT_CFG2),
     75	REGDEF(V3D_CSD_CURRENT_CFG3),
     76	REGDEF(V3D_CSD_CURRENT_CFG4),
     77	REGDEF(V3D_CSD_CURRENT_CFG5),
     78	REGDEF(V3D_CSD_CURRENT_CFG6),
     79};
     80
     81static int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused)
     82{
     83	struct drm_info_node *node = (struct drm_info_node *)m->private;
     84	struct drm_device *dev = node->minor->dev;
     85	struct v3d_dev *v3d = to_v3d_dev(dev);
     86	int i, core;
     87
     88	for (i = 0; i < ARRAY_SIZE(v3d_hub_reg_defs); i++) {
     89		seq_printf(m, "%s (0x%04x): 0x%08x\n",
     90			   v3d_hub_reg_defs[i].name, v3d_hub_reg_defs[i].reg,
     91			   V3D_READ(v3d_hub_reg_defs[i].reg));
     92	}
     93
     94	if (v3d->ver < 41) {
     95		for (i = 0; i < ARRAY_SIZE(v3d_gca_reg_defs); i++) {
     96			seq_printf(m, "%s (0x%04x): 0x%08x\n",
     97				   v3d_gca_reg_defs[i].name,
     98				   v3d_gca_reg_defs[i].reg,
     99				   V3D_GCA_READ(v3d_gca_reg_defs[i].reg));
    100		}
    101	}
    102
    103	for (core = 0; core < v3d->cores; core++) {
    104		for (i = 0; i < ARRAY_SIZE(v3d_core_reg_defs); i++) {
    105			seq_printf(m, "core %d %s (0x%04x): 0x%08x\n",
    106				   core,
    107				   v3d_core_reg_defs[i].name,
    108				   v3d_core_reg_defs[i].reg,
    109				   V3D_CORE_READ(core,
    110						 v3d_core_reg_defs[i].reg));
    111		}
    112
    113		if (v3d_has_csd(v3d)) {
    114			for (i = 0; i < ARRAY_SIZE(v3d_csd_reg_defs); i++) {
    115				seq_printf(m, "core %d %s (0x%04x): 0x%08x\n",
    116					   core,
    117					   v3d_csd_reg_defs[i].name,
    118					   v3d_csd_reg_defs[i].reg,
    119					   V3D_CORE_READ(core,
    120							 v3d_csd_reg_defs[i].reg));
    121			}
    122		}
    123	}
    124
    125	return 0;
    126}
    127
    128static int v3d_v3d_debugfs_ident(struct seq_file *m, void *unused)
    129{
    130	struct drm_info_node *node = (struct drm_info_node *)m->private;
    131	struct drm_device *dev = node->minor->dev;
    132	struct v3d_dev *v3d = to_v3d_dev(dev);
    133	u32 ident0, ident1, ident2, ident3, cores;
    134	int ret, core;
    135
    136	ret = pm_runtime_get_sync(v3d->drm.dev);
    137	if (ret < 0)
    138		return ret;
    139
    140	ident0 = V3D_READ(V3D_HUB_IDENT0);
    141	ident1 = V3D_READ(V3D_HUB_IDENT1);
    142	ident2 = V3D_READ(V3D_HUB_IDENT2);
    143	ident3 = V3D_READ(V3D_HUB_IDENT3);
    144	cores = V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_NCORES);
    145
    146	seq_printf(m, "Revision:   %d.%d.%d.%d\n",
    147		   V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_TVER),
    148		   V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_REV),
    149		   V3D_GET_FIELD(ident3, V3D_HUB_IDENT3_IPREV),
    150		   V3D_GET_FIELD(ident3, V3D_HUB_IDENT3_IPIDX));
    151	seq_printf(m, "MMU:        %s\n",
    152		   str_yes_no(ident2 & V3D_HUB_IDENT2_WITH_MMU));
    153	seq_printf(m, "TFU:        %s\n",
    154		   str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_TFU));
    155	seq_printf(m, "TSY:        %s\n",
    156		   str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_TSY));
    157	seq_printf(m, "MSO:        %s\n",
    158		   str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_MSO));
    159	seq_printf(m, "L3C:        %s (%dkb)\n",
    160		   str_yes_no(ident1 & V3D_HUB_IDENT1_WITH_L3C),
    161		   V3D_GET_FIELD(ident2, V3D_HUB_IDENT2_L3C_NKB));
    162
    163	for (core = 0; core < cores; core++) {
    164		u32 misccfg;
    165		u32 nslc, ntmu, qups;
    166
    167		ident0 = V3D_CORE_READ(core, V3D_CTL_IDENT0);
    168		ident1 = V3D_CORE_READ(core, V3D_CTL_IDENT1);
    169		ident2 = V3D_CORE_READ(core, V3D_CTL_IDENT2);
    170		misccfg = V3D_CORE_READ(core, V3D_CTL_MISCCFG);
    171
    172		nslc = V3D_GET_FIELD(ident1, V3D_IDENT1_NSLC);
    173		ntmu = V3D_GET_FIELD(ident1, V3D_IDENT1_NTMU);
    174		qups = V3D_GET_FIELD(ident1, V3D_IDENT1_QUPS);
    175
    176		seq_printf(m, "Core %d:\n", core);
    177		seq_printf(m, "  Revision:     %d.%d\n",
    178			   V3D_GET_FIELD(ident0, V3D_IDENT0_VER),
    179			   V3D_GET_FIELD(ident1, V3D_IDENT1_REV));
    180		seq_printf(m, "  Slices:       %d\n", nslc);
    181		seq_printf(m, "  TMUs:         %d\n", nslc * ntmu);
    182		seq_printf(m, "  QPUs:         %d\n", nslc * qups);
    183		seq_printf(m, "  Semaphores:   %d\n",
    184			   V3D_GET_FIELD(ident1, V3D_IDENT1_NSEM));
    185		seq_printf(m, "  BCG int:      %d\n",
    186			   (ident2 & V3D_IDENT2_BCG_INT) != 0);
    187		seq_printf(m, "  Override TMU: %d\n",
    188			   (misccfg & V3D_MISCCFG_OVRTMUOUT) != 0);
    189	}
    190
    191	pm_runtime_mark_last_busy(v3d->drm.dev);
    192	pm_runtime_put_autosuspend(v3d->drm.dev);
    193
    194	return 0;
    195}
    196
    197static int v3d_debugfs_bo_stats(struct seq_file *m, void *unused)
    198{
    199	struct drm_info_node *node = (struct drm_info_node *)m->private;
    200	struct drm_device *dev = node->minor->dev;
    201	struct v3d_dev *v3d = to_v3d_dev(dev);
    202
    203	mutex_lock(&v3d->bo_lock);
    204	seq_printf(m, "allocated bos:          %d\n",
    205		   v3d->bo_stats.num_allocated);
    206	seq_printf(m, "allocated bo size (kb): %ld\n",
    207		   (long)v3d->bo_stats.pages_allocated << (PAGE_SHIFT - 10));
    208	mutex_unlock(&v3d->bo_lock);
    209
    210	return 0;
    211}
    212
    213static int v3d_measure_clock(struct seq_file *m, void *unused)
    214{
    215	struct drm_info_node *node = (struct drm_info_node *)m->private;
    216	struct drm_device *dev = node->minor->dev;
    217	struct v3d_dev *v3d = to_v3d_dev(dev);
    218	uint32_t cycles;
    219	int core = 0;
    220	int measure_ms = 1000;
    221	int ret;
    222
    223	ret = pm_runtime_get_sync(v3d->drm.dev);
    224	if (ret < 0)
    225		return ret;
    226
    227	if (v3d->ver >= 40) {
    228		V3D_CORE_WRITE(core, V3D_V4_PCTR_0_SRC_0_3,
    229			       V3D_SET_FIELD(V3D_PCTR_CYCLE_COUNT,
    230					     V3D_PCTR_S0));
    231		V3D_CORE_WRITE(core, V3D_V4_PCTR_0_CLR, 1);
    232		V3D_CORE_WRITE(core, V3D_V4_PCTR_0_EN, 1);
    233	} else {
    234		V3D_CORE_WRITE(core, V3D_V3_PCTR_0_PCTRS0,
    235			       V3D_PCTR_CYCLE_COUNT);
    236		V3D_CORE_WRITE(core, V3D_V3_PCTR_0_CLR, 1);
    237		V3D_CORE_WRITE(core, V3D_V3_PCTR_0_EN,
    238			       V3D_V3_PCTR_0_EN_ENABLE |
    239			       1);
    240	}
    241	msleep(measure_ms);
    242	cycles = V3D_CORE_READ(core, V3D_PCTR_0_PCTR0);
    243
    244	seq_printf(m, "cycles: %d (%d.%d Mhz)\n",
    245		   cycles,
    246		   cycles / (measure_ms * 1000),
    247		   (cycles / (measure_ms * 100)) % 10);
    248
    249	pm_runtime_mark_last_busy(v3d->drm.dev);
    250	pm_runtime_put_autosuspend(v3d->drm.dev);
    251
    252	return 0;
    253}
    254
    255static const struct drm_info_list v3d_debugfs_list[] = {
    256	{"v3d_ident", v3d_v3d_debugfs_ident, 0},
    257	{"v3d_regs", v3d_v3d_debugfs_regs, 0},
    258	{"measure_clock", v3d_measure_clock, 0},
    259	{"bo_stats", v3d_debugfs_bo_stats, 0},
    260};
    261
    262void
    263v3d_debugfs_init(struct drm_minor *minor)
    264{
    265	drm_debugfs_create_files(v3d_debugfs_list,
    266				 ARRAY_SIZE(v3d_debugfs_list),
    267				 minor->debugfs_root, minor);
    268}