Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 26b7004d authored by Harshdeep Dhatt's avatar Harshdeep Dhatt
Browse files

msm: kgsl: Fix check for oversized HFI messages



The check for HFI message size is incorrect as it is done
after the higher bits of size are masked out while creating
the HFI header. Fix the check so that we do not let oversized
messages through.

Change-Id: Ic2350da328d21f085bd41656d36c74132c5007ac
Signed-off-by: default avatarSushmita Susheelendra <ssusheel@codeaurora.org>
Signed-off-by: default avatarHarshdeep Dhatt <hdhatt@codeaurora.org>
parent 27f4d2c0
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -842,7 +842,7 @@ static int a6xx_gmu_hfi_start_msg(struct adreno_device *adreno_dev)
	 * legacy firmware.
	 */
	if (!ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG)) {
		req.hdr = CMD_MSG_HDR(H2F_MSG_START, sizeof(req));
		CMD_MSG_HDR(req, H2F_MSG_START);

		return a6xx_hfi_send_generic_req(adreno_dev, &req);
	}
@@ -1713,7 +1713,7 @@ static int a6xx_gmu_notify_slumber(struct adreno_device *adreno_dev)
			.bw = bus_level,
		};

		req.hdr = CMD_MSG_HDR(H2F_MSG_PREPARE_SLUMBER, sizeof(req));
		CMD_MSG_HDR(req, H2F_MSG_PREPARE_SLUMBER);

		ret = a6xx_hfi_send_generic_req(adreno_dev, &req);
		goto out;
@@ -1803,7 +1803,7 @@ static int a6xx_gmu_dcvs_set(struct adreno_device *adreno_dev,
		return 0;
	}

	req.hdr = CMD_MSG_HDR(H2F_MSG_GX_BW_PERF_VOTE, sizeof(req));
	CMD_MSG_HDR(req, H2F_MSG_GX_BW_PERF_VOTE);

	if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
		ret = a6xx_gmu_dcvs_nohfi(device, req.freq, req.bw);
@@ -2443,7 +2443,8 @@ static void a6xx_gmu_acd_probe(struct kgsl_device *device,
	if (!ADRENO_FEATURE(adreno_dev, ADRENO_ACD))
		return;

	cmd->hdr = CMD_MSG_HDR(H2F_MSG_ACD_TBL, sizeof(*cmd));
	cmd->hdr = CREATE_MSG_HDR(H2F_MSG_ACD_TBL, sizeof(*cmd), HFI_MSG_CMD);

	cmd->version = 1;
	cmd->stride = 1;
	cmd->enable_by_level = 0;
+15 −16
Original line number Diff line number Diff line
@@ -103,13 +103,6 @@ int a6xx_hfi_queue_write(struct adreno_device *adreno_dev, uint32_t queue_idx,
	if (hdr->status == HFI_QUEUE_STATUS_DISABLED)
		return -EINVAL;

	if (size > HFI_MAX_MSG_SIZE) {
		dev_err(&gmu->pdev->dev,
			"Message too big to send: sz=%d, id=%d\n",
			size, id);
		return -EINVAL;
	}

	queue = HOST_QUEUE_START_ADDR(gmu->hfi.hfi_mem, queue_idx);

	trace_kgsl_hfi_send(id, size, MSG_HDR_GET_SEQNUM(*msg));
@@ -359,13 +352,14 @@ static int a6xx_hfi_send_gmu_init(struct adreno_device *adreno_dev)
{
	struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
	struct hfi_gmu_init_cmd cmd = {
		.hdr = CMD_MSG_HDR(H2F_MSG_INIT, sizeof(cmd)),
		.seg_id = 0,
		.dbg_buffer_addr = (unsigned int) gmu->dump_mem->gmuaddr,
		.dbg_buffer_size = (unsigned int) gmu->dump_mem->size,
		.boot_state = 0x1,
	};

	CMD_MSG_HDR(cmd, H2F_MSG_INIT);

	return a6xx_hfi_send_generic_req(adreno_dev, &cmd);
}

@@ -374,12 +368,13 @@ static int a6xx_hfi_get_fw_version(struct adreno_device *adreno_dev,
{
	struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
	struct hfi_fw_version_cmd cmd = {
		.hdr = CMD_MSG_HDR(H2F_MSG_FW_VER, sizeof(cmd)),
		.supported_ver = expected_ver,
	};
	int rc;
	struct pending_cmd ret_cmd;

	CMD_MSG_HDR(cmd, H2F_MSG_FW_VER);

	memset(&ret_cmd, 0, sizeof(ret_cmd));

	rc = a6xx_hfi_send_cmd_wait_inline(adreno_dev, &cmd, &ret_cmd);
@@ -399,10 +394,11 @@ static int a6xx_hfi_get_fw_version(struct adreno_device *adreno_dev,
int a6xx_hfi_send_core_fw_start(struct adreno_device *adreno_dev)
{
	struct hfi_core_fw_start_cmd cmd = {
		.hdr = CMD_MSG_HDR(H2F_MSG_CORE_FW_START, sizeof(cmd)),
		.handle = 0x0,
	};

	CMD_MSG_HDR(cmd, H2F_MSG_CORE_FW_START);

	return a6xx_hfi_send_generic_req(adreno_dev, &cmd);
}

@@ -425,13 +421,14 @@ int a6xx_hfi_send_feature_ctrl(struct adreno_device *adreno_dev,
{
	struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
	struct hfi_feature_ctrl_cmd cmd = {
		.hdr = CMD_MSG_HDR(H2F_MSG_FEATURE_CTRL, sizeof(cmd)),
		.feature = feature,
		.enable = enable,
		.data = data,
	};
	int ret;

	CMD_MSG_HDR(cmd, H2F_MSG_FEATURE_CTRL);

	ret = a6xx_hfi_send_generic_req(adreno_dev, &cmd);
	if (ret)
		dev_err(&gmu->pdev->dev,
@@ -447,12 +444,13 @@ static int a6xx_hfi_send_dcvstbl_v1(struct adreno_device *adreno_dev)
	struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
	struct hfi_dcvstable_cmd *table = &gmu->hfi.dcvs_table;
	struct hfi_dcvstable_v1_cmd cmd = {
		.hdr = CMD_MSG_HDR(H2F_MSG_PERF_TBL, sizeof(cmd)),
		.gpu_level_num = table->gpu_level_num,
		.gmu_level_num = table->gmu_level_num,
	};
	int i;

	CMD_MSG_HDR(cmd, H2F_MSG_PERF_TBL);

	for (i = 0; i < table->gpu_level_num; i++) {
		cmd.gx_votes[i].vote = table->gx_votes[i].vote;
		cmd.gx_votes[i].freq = table->gx_votes[i].freq;
@@ -468,9 +466,9 @@ static int a6xx_hfi_send_dcvstbl_v1(struct adreno_device *adreno_dev)

static int a6xx_hfi_send_test(struct adreno_device *adreno_dev)
{
	struct hfi_test_cmd cmd = {
		.hdr = CMD_MSG_HDR(H2F_MSG_TEST, sizeof(cmd)),
	};
	struct hfi_test_cmd cmd;

	CMD_MSG_HDR(cmd, H2F_MSG_TEST);

	return a6xx_hfi_send_generic_req(adreno_dev, &cmd);
}
@@ -623,7 +621,8 @@ int a6xx_hfi_send_lm_feature_ctrl(struct adreno_device *adreno_dev)

	nvmem_cell_read_u32(&device->pdev->dev, "isense_slope", &slope);

	req.hdr = CMD_MSG_HDR(H2F_MSG_SET_VALUE, sizeof(req));
	CMD_MSG_HDR(req, H2F_MSG_SET_VALUE);

	req.type = HFI_VALUE_LM_CS0;
	req.subtype = 0;
	req.data = slope;
+8 −2
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@
#define HFI_QUEUE_SIZE			SZ_4K /* bytes, must be base 4dw */
#define MAX_RCVD_PAYLOAD_SIZE		16		/* dwords */
#define MAX_RCVD_SIZE			(MAX_RCVD_PAYLOAD_SIZE + 3) /* dwords */
#define HFI_MAX_MSG_SIZE		(SZ_1K>>2)	/* dwords */
#define HFI_MAX_MSG_SIZE		(SZ_1K)

#define HFI_CMD_ID 0
#define HFI_MSG_ID 1
@@ -133,7 +133,6 @@ struct hfi_queue_header {
/* Size is converted from Bytes to DWords */
#define CREATE_MSG_HDR(id, size, type) \
	(((type) << 16) | ((((size) >> 2) & 0xFF) << 8) | ((id) & 0xFF))
#define CMD_MSG_HDR(id, size) CREATE_MSG_HDR(id, size, HFI_MSG_CMD)
#define ACK_MSG_HDR(id, size) CREATE_MSG_HDR(id, size, HFI_MSG_ACK)

#define HFI_QUEUE_DEFAULT_CNT 3
@@ -569,6 +568,13 @@ struct a6xx_hfi {
	struct hfi_dcvstable_cmd dcvs_table;
};

#define CMD_MSG_HDR(cmd, id) \
	do { \
		if (WARN_ON((sizeof(cmd)) > HFI_MAX_MSG_SIZE)) \
			return -EMSGSIZE; \
		cmd.hdr = CREATE_MSG_HDR((id), (sizeof(cmd)), HFI_MSG_CMD); \
	} while (0)

struct a6xx_gmu_device;

/* a6xx_hfi_irq_handler - IRQ handler for HFI interripts */
+4 −2
Original line number Diff line number Diff line
@@ -199,7 +199,8 @@ static int a6xx_hwsched_notify_slumber(struct adreno_device *adreno_dev)
	struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
	struct hfi_prep_slumber_cmd req;

	req.hdr = CMD_MSG_HDR(H2F_MSG_PREPARE_SLUMBER, sizeof(req));
	CMD_MSG_HDR(req, H2F_MSG_PREPARE_SLUMBER);

	req.freq = gmu->hfi.dcvs_table.gpu_level_num -
			pwr->default_pwrlevel - 1;
	req.bw = pwr->pwrlevels[pwr->default_pwrlevel].bus_freq;
@@ -600,7 +601,6 @@ static int a6xx_hwsched_dcvs_set(struct adreno_device *adreno_dev,
	struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev);
	struct hfi_dcvstable_cmd *table = &gmu->hfi.dcvs_table;
	struct hfi_gx_bw_perf_vote_cmd req = {
		.hdr = CMD_MSG_HDR(H2F_MSG_GX_BW_PERF_VOTE, sizeof(req)),
		.ack_type = DCVS_ACK_BLOCK,
		.freq = INVALID_DCVS_IDX,
		.bw = INVALID_DCVS_IDX,
@@ -628,6 +628,8 @@ static int a6xx_hwsched_dcvs_set(struct adreno_device *adreno_dev,
	if ((req.freq == INVALID_DCVS_IDX) && (req.bw == INVALID_DCVS_IDX))
		return 0;

	CMD_MSG_HDR(req, H2F_MSG_GX_BW_PERF_VOTE);

	ret = a6xx_hfi_send_cmd_async(adreno_dev, &req);

	if (ret)
+17 −8
Original line number Diff line number Diff line
@@ -583,7 +583,8 @@ static int send_start_msg(struct adreno_device *adreno_dev)
	u32 rcvd[MAX_RCVD_SIZE];
	struct pending_cmd pending_ack = {0};

	cmd.hdr = CMD_MSG_HDR(H2F_MSG_START, sizeof(cmd));
	CMD_MSG_HDR(cmd, H2F_MSG_START);

	cmd.hdr = MSG_HDR_SET_SEQNUM(cmd.hdr, seqnum);

	pending_ack.sent_hdr = cmd.hdr;
@@ -775,8 +776,9 @@ static int cp_init(struct adreno_device *adreno_dev)
{
	u32 cmds[A6XX_CP_INIT_DWORDS + 1];

	cmds[0] = CMD_MSG_HDR(H2F_MSG_ISSUE_CMD_RAW,
			(A6XX_CP_INIT_DWORDS + 1) << 2);
	cmds[0] = CREATE_MSG_HDR(H2F_MSG_ISSUE_CMD_RAW,
		(A6XX_CP_INIT_DWORDS + 1) << 2, HFI_MSG_CMD);

	memcpy(&cmds[1], adreno_dev->cp_init_cmds, A6XX_CP_INIT_DWORDS << 2);

	return submit_raw_cmds(adreno_dev, cmds,
@@ -787,7 +789,9 @@ static int send_switch_to_unsecure(struct adreno_device *adreno_dev)
{
	u32 cmds[3];

	cmds[0] = CMD_MSG_HDR(H2F_MSG_ISSUE_CMD_RAW, sizeof(cmds));
	cmds[0] = CREATE_MSG_HDR(H2F_MSG_ISSUE_CMD_RAW, sizeof(cmds),
			HFI_MSG_CMD);

	cmds[1] = cp_type7_packet(CP_SET_SECURE_MODE, 1);
	cmds[2] = 0;

@@ -980,7 +984,8 @@ static int send_context_register(struct adreno_device *adreno_dev,
	struct hfi_register_ctxt_cmd cmd;
	struct kgsl_pagetable *pt = context->proc_priv->pagetable;

	cmd.hdr = CMD_MSG_HDR(H2F_MSG_REGISTER_CONTEXT, sizeof(cmd));
	CMD_MSG_HDR(cmd, H2F_MSG_REGISTER_CONTEXT);

	cmd.ctxt_id = context->id;
	cmd.flags = CTXT_FLAG_NOTIFY | context->flags;
	cmd.pt_addr = kgsl_mmu_pagetable_get_ttbr0(pt);
@@ -996,7 +1001,7 @@ static int send_context_pointers(struct adreno_device *adreno_dev,
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct hfi_context_pointers_cmd cmd;

	cmd.hdr = CMD_MSG_HDR(H2F_MSG_CONTEXT_POINTERS, sizeof(cmd));
	CMD_MSG_HDR(cmd, H2F_MSG_CONTEXT_POINTERS);
	cmd.ctxt_id = context->id;
	cmd.sop_addr = MEMSTORE_ID_GPU_ADDR(device, context->id, soptimestamp);
	cmd.eop_addr = MEMSTORE_ID_GPU_ADDR(device, context->id, eoptimestamp);
@@ -1071,11 +1076,15 @@ int a6xx_hwsched_submit_cmdobj(struct adreno_device *adreno_dev,
	/* Add a *issue_ib struct for each IB */
	cmd_sizebytes = sizeof(*cmd) + (sizeof(*issue_ib) * numibs);

	if (WARN_ON(cmd_sizebytes > HFI_MAX_MSG_SIZE))
		return -EMSGSIZE;

	cmd = kvmalloc(cmd_sizebytes, GFP_KERNEL);
	if (cmd == NULL)
		return -ENOMEM;

	cmd->hdr = CMD_MSG_HDR(H2F_MSG_ISSUE_CMD, cmd_sizebytes);
	cmd->hdr = CREATE_MSG_HDR(H2F_MSG_ISSUE_CMD, cmd_sizebytes,
			HFI_MSG_CMD);
	cmd->hdr = MSG_HDR_SET_SEQNUM(cmd->hdr,
			atomic_inc_return(&hfi->seqnum));

@@ -1150,7 +1159,7 @@ static int send_context_unregister_hfi(struct adreno_device *adreno_dev,
	u32 seqnum;
	int rc;

	cmd.hdr = CMD_MSG_HDR(H2F_MSG_UNREGISTER_CONTEXT, sizeof(cmd));
	CMD_MSG_HDR(cmd, H2F_MSG_UNREGISTER_CONTEXT);
	cmd.ctxt_id = ctxt_id,
	cmd.ts = ts,

Loading