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

Commit 7c527ce9 authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Protect CP_STATE_DEBUG_INDEX



Put CP_STATE_DEBUG_INDEX and CP_STATE_DEBUG_DATA under protection
to keep it from being written from an IB1. Doing so however opens
up a subtle "feature" in the microcode: memory read opcodes turn off
protected mode in the microcode to do the read and then turns it
back on regardless of the initial state. This is a problem if the
memory read happens while protected mode is turned off and then we
try to access a protected register which then complains and goes boom.

To account for this irregularity explicitly turn back off protected
mode in all the places where we know this will be a problem.

Change-Id: Ic0dedbad1397ca9b80132241ac006560a615e042
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent e3727e00
Loading
Loading
Loading
Loading
+13 −11
Original line number Original line Diff line number Diff line
@@ -1151,9 +1151,7 @@ static int adreno_iommu_setstate(struct kgsl_device *device,
					uint32_t flags)
					uint32_t flags)
{
{
	phys_addr_t pt_val;
	phys_addr_t pt_val;
	unsigned int link[230];
	unsigned int *link = NULL, *cmds;
	unsigned int *cmds = &link[0];
	int sizedwords = 0;
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	int num_iommu_units;
	int num_iommu_units;
	struct kgsl_context *context;
	struct kgsl_context *context;
@@ -1171,6 +1169,14 @@ static int adreno_iommu_setstate(struct kgsl_device *device,
	if (context)
	if (context)
		adreno_ctx = ADRENO_CONTEXT(context);
		adreno_ctx = ADRENO_CONTEXT(context);


	link = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (link == NULL) {
		result = -ENOMEM;
		goto done;
	}

	cmds = link;

	result = kgsl_mmu_enable_clk(&device->mmu, KGSL_IOMMU_CONTEXT_USER);
	result = kgsl_mmu_enable_clk(&device->mmu, KGSL_IOMMU_CONTEXT_USER);


	if (result)
	if (result)
@@ -1193,17 +1199,11 @@ static int adreno_iommu_setstate(struct kgsl_device *device,
		cmds += _adreno_iommu_setstate_v1(device, cmds, pt_val,
		cmds += _adreno_iommu_setstate_v1(device, cmds, pt_val,
						num_iommu_units, flags);
						num_iommu_units, flags);


	sizedwords += (cmds - &link[0]);
	if (sizedwords == 0) {
		KGSL_DRV_ERR(device, "no commands generated\n");
		BUG();
	}
	/* invalidate all base pointers */
	/* invalidate all base pointers */
	*cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
	*cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
	*cmds++ = 0x7fff;
	*cmds++ = 0x7fff;
	sizedwords += 2;


	if (sizedwords > (ARRAY_SIZE(link))) {
	if ((unsigned int) (cmds - link) > (PAGE_SIZE / sizeof(unsigned int))) {
		KGSL_DRV_ERR(device, "Temp command buffer overflow\n");
		KGSL_DRV_ERR(device, "Temp command buffer overflow\n");
		BUG();
		BUG();
	}
	}
@@ -1212,7 +1212,8 @@ static int adreno_iommu_setstate(struct kgsl_device *device,
	 * use the global timestamp for iommu clock disablement
	 * use the global timestamp for iommu clock disablement
	 */
	 */
	result = adreno_ringbuffer_issuecmds(device, adreno_ctx,
	result = adreno_ringbuffer_issuecmds(device, adreno_ctx,
			KGSL_CMD_FLAGS_PMODE, &link[0], sizedwords);
			KGSL_CMD_FLAGS_PMODE, link,
			(unsigned int)(cmds - link));


	/*
	/*
	 * On error disable the IOMMU clock right away otherwise turn it off
	 * On error disable the IOMMU clock right away otherwise turn it off
@@ -1226,6 +1227,7 @@ static int adreno_iommu_setstate(struct kgsl_device *device,
						KGSL_IOMMU_CONTEXT_USER);
						KGSL_IOMMU_CONTEXT_USER);


done:
done:
	kfree(link);
	kgsl_context_put(context);
	kgsl_context_put(context);
	return result;
	return result;
}
}
+10 −0
Original line number Original line Diff line number Diff line
@@ -813,6 +813,11 @@ static inline int adreno_add_read_cmds(struct kgsl_device *device,
	*cmds++ = val;
	*cmds++ = val;
	*cmds++ = 0xFFFFFFFF;
	*cmds++ = 0xFFFFFFFF;
	*cmds++ = 0xFFFFFFFF;
	*cmds++ = 0xFFFFFFFF;

	/* WAIT_REG_MEM turns back on protected mode - push it off */
	*cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
	*cmds++ = 0;

	cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
	cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
	return cmds - start;
	return cmds - start;
}
}
@@ -858,6 +863,11 @@ static inline int adreno_wait_reg_mem(unsigned int *cmds, unsigned int addr,
	*cmds++ = val; /* ref val */
	*cmds++ = val; /* ref val */
	*cmds++ = mask;
	*cmds++ = mask;
	*cmds++ = interval;
	*cmds++ = interval;

	/* WAIT_REG_MEM turns back on protected mode - push it off */
	*cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
	*cmds++ = 0;

	return cmds - start;
	return cmds - start;
}
}
/*
/*
+1 −0
Original line number Original line Diff line number Diff line
@@ -2047,6 +2047,7 @@ static void a3xx_protect_init(struct kgsl_device *device)


	/* CP registers */
	/* CP registers */
	adreno_set_protected_registers(device, &index, 0x1C0, 5);
	adreno_set_protected_registers(device, &index, 0x1C0, 5);
	adreno_set_protected_registers(device, &index, 0x1EC, 1);
	adreno_set_protected_registers(device, &index, 0x1F6, 1);
	adreno_set_protected_registers(device, &index, 0x1F6, 1);
	adreno_set_protected_registers(device, &index, 0x1F8, 2);
	adreno_set_protected_registers(device, &index, 0x1F8, 2);
	adreno_set_protected_registers(device, &index, 0x45E, 2);
	adreno_set_protected_registers(device, &index, 0x45E, 2);
+16 −0
Original line number Original line Diff line number Diff line
@@ -1036,6 +1036,10 @@ static unsigned int kgsl_iommu_sync_lock(struct kgsl_mmu *mmu,
	*cmds++ = 0x1;
	*cmds++ = 0x1;
	*cmds++ = 0x1;
	*cmds++ = 0x1;


	/* WAIT_REG_MEM turns back on protected mode - push it off */
	*cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
	*cmds++ = 0;

	*cmds++ = cp_type3_packet(CP_MEM_WRITE, 2);
	*cmds++ = cp_type3_packet(CP_MEM_WRITE, 2);
	*cmds++ = lock_vars->turn;
	*cmds++ = lock_vars->turn;
	*cmds++ = 0;
	*cmds++ = 0;
@@ -1050,11 +1054,19 @@ static unsigned int kgsl_iommu_sync_lock(struct kgsl_mmu *mmu,
	*cmds++ = 0x1;
	*cmds++ = 0x1;
	*cmds++ = 0x1;
	*cmds++ = 0x1;


	/* WAIT_REG_MEM turns back on protected mode - push it off */
	*cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
	*cmds++ = 0;

	*cmds++ = cp_type3_packet(CP_TEST_TWO_MEMS, 3);
	*cmds++ = cp_type3_packet(CP_TEST_TWO_MEMS, 3);
	*cmds++ = lock_vars->flag[PROC_APPS];
	*cmds++ = lock_vars->flag[PROC_APPS];
	*cmds++ = lock_vars->turn;
	*cmds++ = lock_vars->turn;
	*cmds++ = 0;
	*cmds++ = 0;


	/* TEST_TWO_MEMS turns back on protected mode - push it off */
	*cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
	*cmds++ = 0;

	cmds += adreno_add_idle_cmds(adreno_dev, cmds);
	cmds += adreno_add_idle_cmds(adreno_dev, cmds);


	return cmds - start;
	return cmds - start;
@@ -1092,6 +1104,10 @@ static unsigned int kgsl_iommu_sync_unlock(struct kgsl_mmu *mmu,
	*cmds++ = 0x1;
	*cmds++ = 0x1;
	*cmds++ = 0x1;
	*cmds++ = 0x1;


	/* WAIT_REG_MEM turns back on protected mode - push it off */
	*cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
	*cmds++ = 0;

	cmds += adreno_add_idle_cmds(adreno_dev, cmds);
	cmds += adreno_add_idle_cmds(adreno_dev, cmds);


	return cmds - start;
	return cmds - start;