From 7613c9d520ee4d227e635f6db0270d4cf26102bc Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 21 Apr 2014 15:04:54 -0600 Subject: 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: Jordan Crouse --- drivers/gpu/msm/adreno.c | 24 +++++++++++++----------- drivers/gpu/msm/adreno.h | 10 ++++++++++ drivers/gpu/msm/adreno_a3xx.c | 1 + drivers/gpu/msm/kgsl_iommu.c | 16 ++++++++++++++++ 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 4b21218..9bd07c6 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1150,9 +1150,7 @@ static int adreno_iommu_setstate(struct kgsl_device *device, uint32_t flags) { phys_addr_t pt_val; - unsigned int link[230]; - unsigned int *cmds = &link[0]; - int sizedwords = 0; + unsigned int *link = NULL, *cmds; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int num_iommu_units; struct kgsl_context *context; @@ -1170,6 +1168,14 @@ static int adreno_iommu_setstate(struct kgsl_device *device, if (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); if (result) @@ -1192,17 +1198,11 @@ static int adreno_iommu_setstate(struct kgsl_device *device, cmds += _adreno_iommu_setstate_v1(device, cmds, pt_val, num_iommu_units, flags); - sizedwords += (cmds - &link[0]); - if (sizedwords == 0) { - KGSL_DRV_ERR(device, "no commands generated\n"); - BUG(); - } /* invalidate all base pointers */ *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1); *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"); BUG(); } @@ -1211,7 +1211,8 @@ static int adreno_iommu_setstate(struct kgsl_device *device, * use the global timestamp for iommu clock disablement */ 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 @@ -1225,6 +1226,7 @@ static int adreno_iommu_setstate(struct kgsl_device *device, KGSL_IOMMU_CONTEXT_USER); done: + kfree(link); kgsl_context_put(context); return result; } diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 8e162ca..0b793fa 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -805,6 +805,11 @@ static inline int adreno_add_read_cmds(struct kgsl_device *device, *cmds++ = val; *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); return cmds - start; } @@ -850,6 +855,11 @@ static inline int adreno_wait_reg_mem(unsigned int *cmds, unsigned int addr, *cmds++ = val; /* ref val */ *cmds++ = mask; *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; } /* diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 70ba50e..873a5c9 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -2038,6 +2038,7 @@ static void a3xx_protect_init(struct kgsl_device *device) /* CP registers */ 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, 0x1F8, 2); adreno_set_protected_registers(device, &index, 0x45E, 2); diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index dba23b0..68b3420 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -1036,6 +1036,10 @@ static unsigned int kgsl_iommu_sync_lock(struct kgsl_mmu *mmu, *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++ = lock_vars->turn; *cmds++ = 0; @@ -1050,11 +1054,19 @@ static unsigned int kgsl_iommu_sync_lock(struct kgsl_mmu *mmu, *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++ = lock_vars->flag[PROC_APPS]; *cmds++ = lock_vars->turn; *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); return cmds - start; @@ -1092,6 +1104,10 @@ static unsigned int kgsl_iommu_sync_unlock(struct kgsl_mmu *mmu, *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); return cmds - start; -- cgit v1.1