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

msm_disp_snapshot_util.c (4637B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
      4 */
      5
      6#define pr_fmt(fmt)	"[drm:%s:%d] " fmt, __func__, __LINE__
      7
      8#include <generated/utsrelease.h>
      9
     10#include "msm_disp_snapshot.h"
     11
     12static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *base_addr)
     13{
     14	u32 len_padded;
     15	u32 num_rows;
     16	u32 x0, x4, x8, xc;
     17	void __iomem *addr;
     18	u32 *dump_addr = NULL;
     19	void __iomem *end_addr;
     20	int i;
     21
     22	len_padded = aligned_len * REG_DUMP_ALIGN;
     23	num_rows = aligned_len / REG_DUMP_ALIGN;
     24
     25	addr = base_addr;
     26	end_addr = base_addr + aligned_len;
     27
     28	if (!(*reg))
     29		*reg = kzalloc(len_padded, GFP_KERNEL);
     30
     31	if (*reg)
     32		dump_addr = *reg;
     33
     34	for (i = 0; i < num_rows; i++) {
     35		x0 = (addr < end_addr) ? readl_relaxed(addr + 0x0) : 0;
     36		x4 = (addr + 0x4 < end_addr) ? readl_relaxed(addr + 0x4) : 0;
     37		x8 = (addr + 0x8 < end_addr) ? readl_relaxed(addr + 0x8) : 0;
     38		xc = (addr + 0xc < end_addr) ? readl_relaxed(addr + 0xc) : 0;
     39
     40		if (dump_addr) {
     41			dump_addr[i * 4] = x0;
     42			dump_addr[i * 4 + 1] = x4;
     43			dump_addr[i * 4 + 2] = x8;
     44			dump_addr[i * 4 + 3] = xc;
     45		}
     46
     47		addr += REG_DUMP_ALIGN;
     48	}
     49}
     50
     51static void msm_disp_state_print_regs(u32 **reg, u32 len, void __iomem *base_addr,
     52		struct drm_printer *p)
     53{
     54	int i;
     55	u32 *dump_addr = NULL;
     56	void __iomem *addr;
     57	u32 num_rows;
     58
     59	addr = base_addr;
     60	num_rows = len / REG_DUMP_ALIGN;
     61
     62	if (*reg)
     63		dump_addr = *reg;
     64
     65	for (i = 0; i < num_rows; i++) {
     66		drm_printf(p, "0x%lx : %08x %08x %08x %08x\n",
     67				(unsigned long)(addr - base_addr),
     68				dump_addr[i * 4], dump_addr[i * 4 + 1],
     69				dump_addr[i * 4 + 2], dump_addr[i * 4 + 3]);
     70		addr += REG_DUMP_ALIGN;
     71	}
     72}
     73
     74void msm_disp_state_print(struct msm_disp_state *state, struct drm_printer *p)
     75{
     76	struct msm_disp_state_block *block, *tmp;
     77
     78	if (!p) {
     79		DRM_ERROR("invalid drm printer\n");
     80		return;
     81	}
     82
     83	drm_printf(p, "---\n");
     84	drm_printf(p, "kernel: " UTS_RELEASE "\n");
     85	drm_printf(p, "module: " KBUILD_MODNAME "\n");
     86	drm_printf(p, "dpu devcoredump\n");
     87	drm_printf(p, "time: %lld.%09ld\n",
     88		state->time.tv_sec, state->time.tv_nsec);
     89
     90	list_for_each_entry_safe(block, tmp, &state->blocks, node) {
     91		drm_printf(p, "====================%s================\n", block->name);
     92		msm_disp_state_print_regs(&block->state, block->size, block->base_addr, p);
     93	}
     94
     95	drm_printf(p, "===================dpu drm state================\n");
     96
     97	if (state->atomic_state)
     98		drm_atomic_print_new_state(state->atomic_state, p);
     99}
    100
    101static void msm_disp_capture_atomic_state(struct msm_disp_state *disp_state)
    102{
    103	struct drm_device *ddev;
    104	struct drm_modeset_acquire_ctx ctx;
    105
    106	ktime_get_real_ts64(&disp_state->time);
    107
    108	ddev = disp_state->drm_dev;
    109
    110	drm_modeset_acquire_init(&ctx, 0);
    111
    112	while (drm_modeset_lock_all_ctx(ddev, &ctx) != 0)
    113		drm_modeset_backoff(&ctx);
    114
    115	disp_state->atomic_state = drm_atomic_helper_duplicate_state(ddev,
    116			&ctx);
    117	drm_modeset_drop_locks(&ctx);
    118	drm_modeset_acquire_fini(&ctx);
    119}
    120
    121void msm_disp_snapshot_capture_state(struct msm_disp_state *disp_state)
    122{
    123	struct msm_drm_private *priv;
    124	struct drm_device *drm_dev;
    125	struct msm_kms *kms;
    126	int i;
    127
    128	drm_dev = disp_state->drm_dev;
    129	priv = drm_dev->dev_private;
    130	kms = priv->kms;
    131
    132	for (i = 0; i < ARRAY_SIZE(priv->dp); i++) {
    133		if (!priv->dp[i])
    134			continue;
    135
    136		msm_dp_snapshot(disp_state, priv->dp[i]);
    137	}
    138
    139	for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
    140		if (!priv->dsi[i])
    141			continue;
    142
    143		msm_dsi_snapshot(disp_state, priv->dsi[i]);
    144	}
    145
    146	if (kms->funcs->snapshot)
    147		kms->funcs->snapshot(disp_state, kms);
    148
    149	msm_disp_capture_atomic_state(disp_state);
    150}
    151
    152void msm_disp_state_free(void *data)
    153{
    154	struct msm_disp_state *disp_state = data;
    155	struct msm_disp_state_block *block, *tmp;
    156
    157	if (disp_state->atomic_state) {
    158		drm_atomic_state_put(disp_state->atomic_state);
    159		disp_state->atomic_state = NULL;
    160	}
    161
    162	list_for_each_entry_safe(block, tmp, &disp_state->blocks, node) {
    163		list_del(&block->node);
    164		kfree(block->state);
    165		kfree(block);
    166	}
    167
    168	kfree(disp_state);
    169}
    170
    171void msm_disp_snapshot_add_block(struct msm_disp_state *disp_state, u32 len,
    172		void __iomem *base_addr, const char *fmt, ...)
    173{
    174	struct msm_disp_state_block *new_blk;
    175	struct va_format vaf;
    176	va_list va;
    177
    178	new_blk = kzalloc(sizeof(struct msm_disp_state_block), GFP_KERNEL);
    179	if (!new_blk)
    180		return;
    181
    182	va_start(va, fmt);
    183
    184	vaf.fmt = fmt;
    185	vaf.va = &va;
    186	snprintf(new_blk->name, sizeof(new_blk->name), "%pV", &vaf);
    187
    188	va_end(va);
    189
    190	INIT_LIST_HEAD(&new_blk->node);
    191	new_blk->size = ALIGN(len, REG_DUMP_ALIGN);
    192	new_blk->base_addr = base_addr;
    193
    194	msm_disp_state_dump_regs(&new_blk->state, new_blk->size, base_addr);
    195	list_add(&new_blk->node, &disp_state->blocks);
    196}