Commit 470516c2 authored by David (Ming Qiang) Wu's avatar David (Ming Qiang) Wu Committed by Alex Deucher
Browse files

drm/amd/amdgpu: command submission parser for JPEG



Add JPEG IB command parser to ensure registers
in the command are within the JPEG IP block.

Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarDavid (Ming Qiang) Wu <David.Wu3@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
(cherry picked from commit a7f670d5)
Cc: stable@vger.kernel.org
parent 4246b107
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1057,6 +1057,9 @@ static int amdgpu_cs_patch_ibs(struct amdgpu_cs_parser *p,
			r = amdgpu_ring_parse_cs(ring, p, job, ib);
			if (r)
				return r;

			if (ib->sa_bo)
				ib->gpu_addr =  amdgpu_sa_bo_gpu_addr(ib->sa_bo);
		} else {
			ib->ptr = (uint32_t *)kptr;
			r = amdgpu_ring_patch_cs_in_place(ring, p, job, ib);
+60 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@

#include "amdgpu.h"
#include "amdgpu_jpeg.h"
#include "amdgpu_cs.h"
#include "soc15.h"
#include "soc15d.h"
#include "jpeg_v4_0_3.h"
@@ -782,6 +783,10 @@ void jpeg_v4_0_3_dec_ring_emit_ib(struct amdgpu_ring *ring,

	amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET,
		0, 0, PACKETJ_TYPE0));

	if (ring->funcs->parse_cs)
		amdgpu_ring_write(ring, 0);
	else
		amdgpu_ring_write(ring, (vmid | (vmid << 4) | (vmid << 8)));

	amdgpu_ring_write(ring, PACKETJ(regUVD_LMI_JPEG_VMID_INTERNAL_OFFSET,
@@ -1084,6 +1089,7 @@ static const struct amdgpu_ring_funcs jpeg_v4_0_3_dec_ring_vm_funcs = {
	.get_rptr = jpeg_v4_0_3_dec_ring_get_rptr,
	.get_wptr = jpeg_v4_0_3_dec_ring_get_wptr,
	.set_wptr = jpeg_v4_0_3_dec_ring_set_wptr,
	.parse_cs = jpeg_v4_0_3_dec_ring_parse_cs,
	.emit_frame_size =
		SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
@@ -1248,3 +1254,56 @@ static void jpeg_v4_0_3_set_ras_funcs(struct amdgpu_device *adev)
{
	adev->jpeg.ras = &jpeg_v4_0_3_ras;
}

/**
 * jpeg_v4_0_3_dec_ring_parse_cs - command submission parser
 *
 * @parser: Command submission parser context
 * @job: the job to parse
 * @ib: the IB to parse
 *
 * Parse the command stream, return -EINVAL for invalid packet,
 * 0 otherwise
 */
int jpeg_v4_0_3_dec_ring_parse_cs(struct amdgpu_cs_parser *parser,
			     struct amdgpu_job *job,
			     struct amdgpu_ib *ib)
{
	uint32_t i, reg, res, cond, type;
	struct amdgpu_device *adev = parser->adev;

	for (i = 0; i < ib->length_dw ; i += 2) {
		reg  = CP_PACKETJ_GET_REG(ib->ptr[i]);
		res  = CP_PACKETJ_GET_RES(ib->ptr[i]);
		cond = CP_PACKETJ_GET_COND(ib->ptr[i]);
		type = CP_PACKETJ_GET_TYPE(ib->ptr[i]);

		if (res) /* only support 0 at the moment */
			return -EINVAL;

		switch (type) {
		case PACKETJ_TYPE0:
			if (cond != PACKETJ_CONDITION_CHECK0 || reg < JPEG_REG_RANGE_START || reg > JPEG_REG_RANGE_END) {
				dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]);
				return -EINVAL;
			}
			break;
		case PACKETJ_TYPE3:
			if (cond != PACKETJ_CONDITION_CHECK3 || reg < JPEG_REG_RANGE_START || reg > JPEG_REG_RANGE_END) {
				dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]);
				return -EINVAL;
			}
			break;
		case PACKETJ_TYPE6:
			if (ib->ptr[i] == CP_PACKETJ_NOP)
				continue;
			dev_err(adev->dev, "Invalid packet [0x%08x]!\n", ib->ptr[i]);
			return -EINVAL;
		default:
			dev_err(adev->dev, "Unknown packet type %d !\n", type);
			return -EINVAL;
		}
	}

	return 0;
}
+6 −1
Original line number Diff line number Diff line
@@ -46,6 +46,9 @@

#define JRBC_DEC_EXTERNAL_REG_WRITE_ADDR				0x18000

#define JPEG_REG_RANGE_START						0x4000
#define JPEG_REG_RANGE_END						0x41c2

extern const struct amdgpu_ip_block_version jpeg_v4_0_3_ip_block;

void jpeg_v4_0_3_dec_ring_emit_ib(struct amdgpu_ring *ring,
@@ -62,5 +65,7 @@ void jpeg_v4_0_3_dec_ring_insert_end(struct amdgpu_ring *ring);
void jpeg_v4_0_3_dec_ring_emit_wreg(struct amdgpu_ring *ring, uint32_t reg, uint32_t val);
void jpeg_v4_0_3_dec_ring_emit_reg_wait(struct amdgpu_ring *ring, uint32_t reg,
					uint32_t val, uint32_t mask);

int jpeg_v4_0_3_dec_ring_parse_cs(struct amdgpu_cs_parser *parser,
				  struct amdgpu_job *job,
				  struct amdgpu_ib *ib);
#endif /* __JPEG_V4_0_3_H__ */
+1 −0
Original line number Diff line number Diff line
@@ -646,6 +646,7 @@ static const struct amdgpu_ring_funcs jpeg_v5_0_0_dec_ring_vm_funcs = {
	.get_rptr = jpeg_v5_0_0_dec_ring_get_rptr,
	.get_wptr = jpeg_v5_0_0_dec_ring_get_wptr,
	.set_wptr = jpeg_v5_0_0_dec_ring_set_wptr,
	.parse_cs = jpeg_v4_0_3_dec_ring_parse_cs,
	.emit_frame_size =
		SOC15_FLUSH_GPU_TLB_NUM_WREG * 6 +
		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 8 +
+6 −0
Original line number Diff line number Diff line
@@ -76,6 +76,12 @@
			 ((cond & 0xF) << 24) |				\
			 ((type & 0xF) << 28))

#define CP_PACKETJ_NOP		0x60000000
#define CP_PACKETJ_GET_REG(x)  ((x) & 0x3FFFF)
#define CP_PACKETJ_GET_RES(x)  (((x) >> 18) & 0x3F)
#define CP_PACKETJ_GET_COND(x) (((x) >> 24) & 0xF)
#define CP_PACKETJ_GET_TYPE(x) (((x) >> 28) & 0xF)

/* Packet 3 types */
#define	PACKET3_NOP					0x10
#define	PACKET3_SET_BASE				0x11