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

a5xx_debugfs.c (3741B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
      3 */
      4
      5#include <linux/types.h>
      6#include <linux/debugfs.h>
      7
      8#include <drm/drm_debugfs.h>
      9#include <drm/drm_file.h>
     10#include <drm/drm_print.h>
     11
     12#include "a5xx_gpu.h"
     13
     14static void pfp_print(struct msm_gpu *gpu, struct drm_printer *p)
     15{
     16	int i;
     17
     18	drm_printf(p, "PFP state:\n");
     19
     20	for (i = 0; i < 36; i++) {
     21		gpu_write(gpu, REG_A5XX_CP_PFP_STAT_ADDR, i);
     22		drm_printf(p, "  %02x: %08x\n", i,
     23			gpu_read(gpu, REG_A5XX_CP_PFP_STAT_DATA));
     24	}
     25}
     26
     27static void me_print(struct msm_gpu *gpu, struct drm_printer *p)
     28{
     29	int i;
     30
     31	drm_printf(p, "ME state:\n");
     32
     33	for (i = 0; i < 29; i++) {
     34		gpu_write(gpu, REG_A5XX_CP_ME_STAT_ADDR, i);
     35		drm_printf(p, "  %02x: %08x\n", i,
     36			gpu_read(gpu, REG_A5XX_CP_ME_STAT_DATA));
     37	}
     38}
     39
     40static void meq_print(struct msm_gpu *gpu, struct drm_printer *p)
     41{
     42	int i;
     43
     44	drm_printf(p, "MEQ state:\n");
     45	gpu_write(gpu, REG_A5XX_CP_MEQ_DBG_ADDR, 0);
     46
     47	for (i = 0; i < 64; i++) {
     48		drm_printf(p, "  %02x: %08x\n", i,
     49			gpu_read(gpu, REG_A5XX_CP_MEQ_DBG_DATA));
     50	}
     51}
     52
     53static void roq_print(struct msm_gpu *gpu, struct drm_printer *p)
     54{
     55	int i;
     56
     57	drm_printf(p, "ROQ state:\n");
     58	gpu_write(gpu, REG_A5XX_CP_ROQ_DBG_ADDR, 0);
     59
     60	for (i = 0; i < 512 / 4; i++) {
     61		uint32_t val[4];
     62		int j;
     63		for (j = 0; j < 4; j++)
     64			val[j] = gpu_read(gpu, REG_A5XX_CP_ROQ_DBG_DATA);
     65		drm_printf(p, "  %02x: %08x %08x %08x %08x\n", i,
     66			val[0], val[1], val[2], val[3]);
     67	}
     68}
     69
     70static int show(struct seq_file *m, void *arg)
     71{
     72	struct drm_info_node *node = (struct drm_info_node *) m->private;
     73	struct drm_device *dev = node->minor->dev;
     74	struct msm_drm_private *priv = dev->dev_private;
     75	struct drm_printer p = drm_seq_file_printer(m);
     76	void (*show)(struct msm_gpu *gpu, struct drm_printer *p) =
     77		node->info_ent->data;
     78
     79	show(priv->gpu, &p);
     80	return 0;
     81}
     82
     83#define ENT(n) { .name = #n, .show = show, .data = n ##_print }
     84static struct drm_info_list a5xx_debugfs_list[] = {
     85	ENT(pfp),
     86	ENT(me),
     87	ENT(meq),
     88	ENT(roq),
     89};
     90
     91/* for debugfs files that can be written to, we can't use drm helper: */
     92static int
     93reset_set(void *data, u64 val)
     94{
     95	struct drm_device *dev = data;
     96	struct msm_drm_private *priv = dev->dev_private;
     97	struct msm_gpu *gpu = priv->gpu;
     98	struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
     99	struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
    100
    101	if (!capable(CAP_SYS_ADMIN))
    102		return -EINVAL;
    103
    104	/* TODO do we care about trying to make sure the GPU is idle?
    105	 * Since this is just a debug feature limited to CAP_SYS_ADMIN,
    106	 * maybe it is fine to let the user keep both pieces if they
    107	 * try to reset an active GPU.
    108	 */
    109
    110	mutex_lock(&gpu->lock);
    111
    112	release_firmware(adreno_gpu->fw[ADRENO_FW_PM4]);
    113	adreno_gpu->fw[ADRENO_FW_PM4] = NULL;
    114
    115	release_firmware(adreno_gpu->fw[ADRENO_FW_PFP]);
    116	adreno_gpu->fw[ADRENO_FW_PFP] = NULL;
    117
    118	if (a5xx_gpu->pm4_bo) {
    119		msm_gem_unpin_iova(a5xx_gpu->pm4_bo, gpu->aspace);
    120		drm_gem_object_put(a5xx_gpu->pm4_bo);
    121		a5xx_gpu->pm4_bo = NULL;
    122	}
    123
    124	if (a5xx_gpu->pfp_bo) {
    125		msm_gem_unpin_iova(a5xx_gpu->pfp_bo, gpu->aspace);
    126		drm_gem_object_put(a5xx_gpu->pfp_bo);
    127		a5xx_gpu->pfp_bo = NULL;
    128	}
    129
    130	gpu->needs_hw_init = true;
    131
    132	pm_runtime_get_sync(&gpu->pdev->dev);
    133	gpu->funcs->recover(gpu);
    134
    135	pm_runtime_put_sync(&gpu->pdev->dev);
    136	mutex_unlock(&gpu->lock);
    137
    138	return 0;
    139}
    140
    141DEFINE_DEBUGFS_ATTRIBUTE(reset_fops, NULL, reset_set, "%llx\n");
    142
    143
    144void a5xx_debugfs_init(struct msm_gpu *gpu, struct drm_minor *minor)
    145{
    146	struct drm_device *dev;
    147
    148	if (!minor)
    149		return;
    150
    151	dev = minor->dev;
    152
    153	drm_debugfs_create_files(a5xx_debugfs_list,
    154				 ARRAY_SIZE(a5xx_debugfs_list),
    155				 minor->debugfs_root, minor);
    156
    157	debugfs_create_file_unsafe("reset", S_IWUGO, minor->debugfs_root, dev,
    158				&reset_fops);
    159}