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

vpu_dbg.c (11911B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright 2020-2021 NXP
      4 */
      5
      6#include <linux/init.h>
      7#include <linux/device.h>
      8#include <linux/ioctl.h>
      9#include <linux/list.h>
     10#include <linux/module.h>
     11#include <linux/kernel.h>
     12#include <linux/types.h>
     13#include <linux/pm_runtime.h>
     14#include <media/v4l2-device.h>
     15#include <linux/debugfs.h>
     16#include "vpu.h"
     17#include "vpu_defs.h"
     18#include "vpu_helpers.h"
     19#include "vpu_cmds.h"
     20#include "vpu_rpc.h"
     21#include "vpu_v4l2.h"
     22
     23struct print_buf_desc {
     24	u32 start_h_phy;
     25	u32 start_h_vir;
     26	u32 start_m;
     27	u32 bytes;
     28	u32 read;
     29	u32 write;
     30	char buffer[0];
     31};
     32
     33static char *vb2_stat_name[] = {
     34	[VB2_BUF_STATE_DEQUEUED] = "dequeued",
     35	[VB2_BUF_STATE_IN_REQUEST] = "in_request",
     36	[VB2_BUF_STATE_PREPARING] = "preparing",
     37	[VB2_BUF_STATE_QUEUED] = "queued",
     38	[VB2_BUF_STATE_ACTIVE] = "active",
     39	[VB2_BUF_STATE_DONE] = "done",
     40	[VB2_BUF_STATE_ERROR] = "error",
     41};
     42
     43static char *vpu_stat_name[] = {
     44	[VPU_BUF_STATE_IDLE] = "idle",
     45	[VPU_BUF_STATE_INUSE] = "inuse",
     46	[VPU_BUF_STATE_DECODED] = "decoded",
     47	[VPU_BUF_STATE_READY] = "ready",
     48	[VPU_BUF_STATE_SKIP] = "skip",
     49	[VPU_BUF_STATE_ERROR] = "error",
     50};
     51
     52static int vpu_dbg_instance(struct seq_file *s, void *data)
     53{
     54	struct vpu_inst *inst = s->private;
     55	char str[128];
     56	int num;
     57	struct vb2_queue *vq;
     58	int i;
     59
     60	if (!inst->fh.m2m_ctx)
     61		return 0;
     62	num = scnprintf(str, sizeof(str), "[%s]\n", vpu_core_type_desc(inst->type));
     63	if (seq_write(s, str, num))
     64		return 0;
     65
     66	num = scnprintf(str, sizeof(str), "tgig = %d,pid = %d\n", inst->tgid, inst->pid);
     67	if (seq_write(s, str, num))
     68		return 0;
     69	num = scnprintf(str, sizeof(str), "state = %d\n", inst->state);
     70	if (seq_write(s, str, num))
     71		return 0;
     72	num = scnprintf(str, sizeof(str),
     73			"min_buffer_out = %d, min_buffer_cap = %d\n",
     74			inst->min_buffer_out, inst->min_buffer_cap);
     75	if (seq_write(s, str, num))
     76		return 0;
     77
     78	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
     79	num = scnprintf(str, sizeof(str),
     80			"output (%2d, %2d): fmt = %c%c%c%c %d x %d, %d;",
     81			vb2_is_streaming(vq),
     82			vq->num_buffers,
     83			inst->out_format.pixfmt,
     84			inst->out_format.pixfmt >> 8,
     85			inst->out_format.pixfmt >> 16,
     86			inst->out_format.pixfmt >> 24,
     87			inst->out_format.width,
     88			inst->out_format.height,
     89			vq->last_buffer_dequeued);
     90	if (seq_write(s, str, num))
     91		return 0;
     92	for (i = 0; i < inst->out_format.num_planes; i++) {
     93		num = scnprintf(str, sizeof(str), " %d(%d)",
     94				inst->out_format.sizeimage[i],
     95				inst->out_format.bytesperline[i]);
     96		if (seq_write(s, str, num))
     97			return 0;
     98	}
     99	if (seq_write(s, "\n", 1))
    100		return 0;
    101
    102	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
    103	num = scnprintf(str, sizeof(str),
    104			"capture(%2d, %2d): fmt = %c%c%c%c %d x %d, %d;",
    105			vb2_is_streaming(vq),
    106			vq->num_buffers,
    107			inst->cap_format.pixfmt,
    108			inst->cap_format.pixfmt >> 8,
    109			inst->cap_format.pixfmt >> 16,
    110			inst->cap_format.pixfmt >> 24,
    111			inst->cap_format.width,
    112			inst->cap_format.height,
    113			vq->last_buffer_dequeued);
    114	if (seq_write(s, str, num))
    115		return 0;
    116	for (i = 0; i < inst->cap_format.num_planes; i++) {
    117		num = scnprintf(str, sizeof(str), " %d(%d)",
    118				inst->cap_format.sizeimage[i],
    119				inst->cap_format.bytesperline[i]);
    120		if (seq_write(s, str, num))
    121			return 0;
    122	}
    123	if (seq_write(s, "\n", 1))
    124		return 0;
    125	num = scnprintf(str, sizeof(str), "crop: (%d, %d) %d x %d\n",
    126			inst->crop.left,
    127			inst->crop.top,
    128			inst->crop.width,
    129			inst->crop.height);
    130	if (seq_write(s, str, num))
    131		return 0;
    132
    133	vq = v4l2_m2m_get_src_vq(inst->fh.m2m_ctx);
    134	for (i = 0; i < vq->num_buffers; i++) {
    135		struct vb2_buffer *vb = vq->bufs[i];
    136		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
    137
    138		if (vb->state == VB2_BUF_STATE_DEQUEUED)
    139			continue;
    140		num = scnprintf(str, sizeof(str),
    141				"output [%2d] state = %10s, %8s\n",
    142				i, vb2_stat_name[vb->state],
    143				vpu_stat_name[vpu_get_buffer_state(vbuf)]);
    144		if (seq_write(s, str, num))
    145			return 0;
    146	}
    147
    148	vq = v4l2_m2m_get_dst_vq(inst->fh.m2m_ctx);
    149	for (i = 0; i < vq->num_buffers; i++) {
    150		struct vb2_buffer *vb = vq->bufs[i];
    151		struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
    152
    153		if (vb->state == VB2_BUF_STATE_DEQUEUED)
    154			continue;
    155		num = scnprintf(str, sizeof(str),
    156				"capture[%2d] state = %10s, %8s\n",
    157				i, vb2_stat_name[vb->state],
    158				vpu_stat_name[vpu_get_buffer_state(vbuf)]);
    159		if (seq_write(s, str, num))
    160			return 0;
    161	}
    162
    163	num = scnprintf(str, sizeof(str), "sequence = %d\n", inst->sequence);
    164	if (seq_write(s, str, num))
    165		return 0;
    166
    167	if (inst->use_stream_buffer) {
    168		num = scnprintf(str, sizeof(str), "stream_buffer = %d / %d, <%pad, 0x%x>\n",
    169				vpu_helper_get_used_space(inst),
    170				inst->stream_buffer.length,
    171				&inst->stream_buffer.phys,
    172				inst->stream_buffer.length);
    173		if (seq_write(s, str, num))
    174			return 0;
    175	}
    176	num = scnprintf(str, sizeof(str), "kfifo len = 0x%x\n", kfifo_len(&inst->msg_fifo));
    177	if (seq_write(s, str, num))
    178		return 0;
    179
    180	num = scnprintf(str, sizeof(str), "flow :\n");
    181	if (seq_write(s, str, num))
    182		return 0;
    183
    184	mutex_lock(&inst->core->cmd_lock);
    185	for (i = 0; i < ARRAY_SIZE(inst->flows); i++) {
    186		u32 idx = (inst->flow_idx + i) % (ARRAY_SIZE(inst->flows));
    187
    188		if (!inst->flows[idx])
    189			continue;
    190		num = scnprintf(str, sizeof(str), "\t[%s]0x%x\n",
    191				inst->flows[idx] >= VPU_MSG_ID_NOOP ? "M" : "C",
    192				inst->flows[idx]);
    193		if (seq_write(s, str, num)) {
    194			mutex_unlock(&inst->core->cmd_lock);
    195			return 0;
    196		}
    197	}
    198	mutex_unlock(&inst->core->cmd_lock);
    199
    200	i = 0;
    201	while (true) {
    202		num = call_vop(inst, get_debug_info, str, sizeof(str), i++);
    203		if (num <= 0)
    204			break;
    205		if (seq_write(s, str, num))
    206			return 0;
    207	}
    208
    209	return 0;
    210}
    211
    212static int vpu_dbg_core(struct seq_file *s, void *data)
    213{
    214	struct vpu_core *core = s->private;
    215	struct vpu_shared_addr *iface = core->iface;
    216	char str[128];
    217	int num;
    218
    219	num = scnprintf(str, sizeof(str), "[%s]\n", vpu_core_type_desc(core->type));
    220	if (seq_write(s, str, num))
    221		return 0;
    222
    223	num = scnprintf(str, sizeof(str), "boot_region  = <%pad, 0x%x>\n",
    224			&core->fw.phys, core->fw.length);
    225	if (seq_write(s, str, num))
    226		return 0;
    227	num = scnprintf(str, sizeof(str), "rpc_region   = <%pad, 0x%x> used = 0x%x\n",
    228			&core->rpc.phys, core->rpc.length, core->rpc.bytesused);
    229	if (seq_write(s, str, num))
    230		return 0;
    231	num = scnprintf(str, sizeof(str), "fwlog_region = <%pad, 0x%x>\n",
    232			&core->log.phys, core->log.length);
    233	if (seq_write(s, str, num))
    234		return 0;
    235
    236	num = scnprintf(str, sizeof(str), "state = %d\n", core->state);
    237	if (seq_write(s, str, num))
    238		return 0;
    239	if (core->state == VPU_CORE_DEINIT)
    240		return 0;
    241	num = scnprintf(str, sizeof(str), "fw version = %d.%d.%d\n",
    242			(core->fw_version >> 16) & 0xff,
    243			(core->fw_version >> 8) & 0xff,
    244			core->fw_version & 0xff);
    245	if (seq_write(s, str, num))
    246		return 0;
    247	num = scnprintf(str, sizeof(str), "instances = %d/%d (0x%02lx), %d\n",
    248			hweight32(core->instance_mask),
    249			core->supported_instance_count,
    250			core->instance_mask,
    251			core->request_count);
    252	if (seq_write(s, str, num))
    253		return 0;
    254	num = scnprintf(str, sizeof(str), "kfifo len = 0x%x\n", kfifo_len(&core->msg_fifo));
    255	if (seq_write(s, str, num))
    256		return 0;
    257	num = scnprintf(str, sizeof(str),
    258			"cmd_buf:[0x%x, 0x%x], wptr = 0x%x, rptr = 0x%x\n",
    259			iface->cmd_desc->start,
    260			iface->cmd_desc->end,
    261			iface->cmd_desc->wptr,
    262			iface->cmd_desc->rptr);
    263	if (seq_write(s, str, num))
    264		return 0;
    265	num = scnprintf(str, sizeof(str),
    266			"msg_buf:[0x%x, 0x%x], wptr = 0x%x, rptr = 0x%x\n",
    267			iface->msg_desc->start,
    268			iface->msg_desc->end,
    269			iface->msg_desc->wptr,
    270			iface->msg_desc->rptr);
    271	if (seq_write(s, str, num))
    272		return 0;
    273
    274	return 0;
    275}
    276
    277static int vpu_dbg_fwlog(struct seq_file *s, void *data)
    278{
    279	struct vpu_core *core = s->private;
    280	struct print_buf_desc *print_buf;
    281	int length;
    282	u32 rptr;
    283	u32 wptr;
    284	int ret = 0;
    285
    286	if (!core->log.virt || core->state == VPU_CORE_DEINIT)
    287		return 0;
    288
    289	print_buf = core->log.virt;
    290	rptr = print_buf->read;
    291	wptr = print_buf->write;
    292
    293	if (rptr == wptr)
    294		return 0;
    295	else if (rptr < wptr)
    296		length = wptr - rptr;
    297	else
    298		length = print_buf->bytes + wptr - rptr;
    299
    300	if (s->count + length >= s->size) {
    301		s->count = s->size;
    302		return 0;
    303	}
    304
    305	if (rptr + length >= print_buf->bytes) {
    306		int num = print_buf->bytes - rptr;
    307
    308		if (seq_write(s, print_buf->buffer + rptr, num))
    309			ret = -1;
    310		length -= num;
    311		rptr = 0;
    312	}
    313
    314	if (length) {
    315		if (seq_write(s, print_buf->buffer + rptr, length))
    316			ret = -1;
    317		rptr += length;
    318	}
    319	if (!ret)
    320		print_buf->read = rptr;
    321
    322	return 0;
    323}
    324
    325static int vpu_dbg_inst_open(struct inode *inode, struct file *filp)
    326{
    327	return single_open(filp, vpu_dbg_instance, inode->i_private);
    328}
    329
    330static ssize_t vpu_dbg_inst_write(struct file *file,
    331				  const char __user *user_buf, size_t size, loff_t *ppos)
    332{
    333	struct seq_file *s = file->private_data;
    334	struct vpu_inst *inst = s->private;
    335
    336	vpu_session_debug(inst);
    337
    338	return size;
    339}
    340
    341static ssize_t vpu_dbg_core_write(struct file *file,
    342				  const char __user *user_buf, size_t size, loff_t *ppos)
    343{
    344	struct seq_file *s = file->private_data;
    345	struct vpu_core *core = s->private;
    346
    347	pm_runtime_resume_and_get(core->dev);
    348	mutex_lock(&core->lock);
    349	if (core->state != VPU_CORE_DEINIT && !core->instance_mask) {
    350		dev_info(core->dev, "reset\n");
    351		if (!vpu_core_sw_reset(core)) {
    352			core->state = VPU_CORE_ACTIVE;
    353			core->hang_mask = 0;
    354		}
    355	}
    356	mutex_unlock(&core->lock);
    357	pm_runtime_put_sync(core->dev);
    358
    359	return size;
    360}
    361
    362static int vpu_dbg_core_open(struct inode *inode, struct file *filp)
    363{
    364	return single_open(filp, vpu_dbg_core, inode->i_private);
    365}
    366
    367static int vpu_dbg_fwlog_open(struct inode *inode, struct file *filp)
    368{
    369	return single_open(filp, vpu_dbg_fwlog, inode->i_private);
    370}
    371
    372static const struct file_operations vpu_dbg_inst_fops = {
    373	.owner = THIS_MODULE,
    374	.open = vpu_dbg_inst_open,
    375	.release = single_release,
    376	.read = seq_read,
    377	.write = vpu_dbg_inst_write,
    378};
    379
    380static const struct file_operations vpu_dbg_core_fops = {
    381	.owner = THIS_MODULE,
    382	.open = vpu_dbg_core_open,
    383	.release = single_release,
    384	.read = seq_read,
    385	.write = vpu_dbg_core_write,
    386};
    387
    388static const struct file_operations vpu_dbg_fwlog_fops = {
    389	.owner = THIS_MODULE,
    390	.open = vpu_dbg_fwlog_open,
    391	.release = single_release,
    392	.read = seq_read,
    393};
    394
    395int vpu_inst_create_dbgfs_file(struct vpu_inst *inst)
    396{
    397	struct vpu_dev *vpu;
    398	char name[64];
    399
    400	if (!inst || !inst->core || !inst->core->vpu)
    401		return -EINVAL;
    402
    403	vpu = inst->core->vpu;
    404	if (!vpu->debugfs)
    405		return -EINVAL;
    406
    407	if (inst->debugfs)
    408		return 0;
    409
    410	scnprintf(name, sizeof(name), "instance.%d.%d", inst->core->id, inst->id);
    411	inst->debugfs = debugfs_create_file((const char *)name,
    412					    VERIFY_OCTAL_PERMISSIONS(0644),
    413					    vpu->debugfs,
    414					    inst,
    415					    &vpu_dbg_inst_fops);
    416
    417	return 0;
    418}
    419
    420int vpu_inst_remove_dbgfs_file(struct vpu_inst *inst)
    421{
    422	if (!inst)
    423		return 0;
    424
    425	debugfs_remove(inst->debugfs);
    426	inst->debugfs = NULL;
    427
    428	return 0;
    429}
    430
    431int vpu_core_create_dbgfs_file(struct vpu_core *core)
    432{
    433	struct vpu_dev *vpu;
    434	char name[64];
    435
    436	if (!core || !core->vpu)
    437		return -EINVAL;
    438
    439	vpu = core->vpu;
    440	if (!vpu->debugfs)
    441		return -EINVAL;
    442
    443	if (!core->debugfs) {
    444		scnprintf(name, sizeof(name), "core.%d", core->id);
    445		core->debugfs = debugfs_create_file((const char *)name,
    446						    VERIFY_OCTAL_PERMISSIONS(0644),
    447						    vpu->debugfs,
    448						    core,
    449						    &vpu_dbg_core_fops);
    450	}
    451	if (!core->debugfs_fwlog) {
    452		scnprintf(name, sizeof(name), "fwlog.%d", core->id);
    453		core->debugfs_fwlog = debugfs_create_file((const char *)name,
    454							  VERIFY_OCTAL_PERMISSIONS(0444),
    455							  vpu->debugfs,
    456							  core,
    457							  &vpu_dbg_fwlog_fops);
    458	}
    459
    460	return 0;
    461}
    462
    463int vpu_core_remove_dbgfs_file(struct vpu_core *core)
    464{
    465	if (!core)
    466		return 0;
    467	debugfs_remove(core->debugfs);
    468	core->debugfs = NULL;
    469	debugfs_remove(core->debugfs_fwlog);
    470	core->debugfs_fwlog = NULL;
    471
    472	return 0;
    473}
    474
    475void vpu_inst_record_flow(struct vpu_inst *inst, u32 flow)
    476{
    477	if (!inst)
    478		return;
    479
    480	inst->flows[inst->flow_idx] = flow;
    481	inst->flow_idx = (inst->flow_idx + 1) % (ARRAY_SIZE(inst->flows));
    482}