Skip to content

Commit d3a569f

Browse files
Jordan Crouserobclark
authored andcommitted
drm/msm: a6xx: Use WHERE_AM_I for eligible targets
Support the WHERE_AM_I opcode for the A618, A630 and A640 GPUs if the microcode supports it. The WHERE_AM_I opcode allows the RPTR shadow to be updated in priviliged memory which protects the shadow from being read or written from user submissions. A650 already supports extended APRIV have built in hardware support for to access privilged memory from the CP and can go back to using the hardware RPTR shadow feature. Signed-off-by: Jordan Crouse <[email protected]> Signed-off-by: Rob Clark <[email protected]>
1 parent 8907afb commit d3a569f

File tree

2 files changed

+93
-3
lines changed

2 files changed

+93
-3
lines changed

drivers/gpu/drm/msm/adreno/a6xx_gpu.c

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,20 @@ bool a6xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
5151

5252
static void a6xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
5353
{
54+
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
55+
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
5456
uint32_t wptr;
5557
unsigned long flags;
5658

59+
/* Expanded APRIV doesn't need to issue the WHERE_AM_I opcode */
60+
if (a6xx_gpu->has_whereami && !adreno_gpu->base.hw_apriv) {
61+
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
62+
63+
OUT_PKT7(ring, CP_WHERE_AM_I, 2);
64+
OUT_RING(ring, lower_32_bits(shadowptr(a6xx_gpu, ring)));
65+
OUT_RING(ring, upper_32_bits(shadowptr(a6xx_gpu, ring)));
66+
}
67+
5768
spin_lock_irqsave(&ring->lock, flags);
5869

5970
/* Copy the shadow to the actual register */
@@ -508,6 +519,30 @@ static int a6xx_cp_init(struct msm_gpu *gpu)
508519
return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
509520
}
510521

522+
static void a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
523+
struct drm_gem_object *obj)
524+
{
525+
u32 *buf = msm_gem_get_vaddr_active(obj);
526+
527+
if (IS_ERR(buf))
528+
return;
529+
530+
/*
531+
* If the lowest nibble is 0xa that is an indication that this microcode
532+
* has been patched. The actual version is in dword [3] but we only care
533+
* about the patchlevel which is the lowest nibble of dword [3]
534+
*
535+
* Otherwise check that the firmware is greater than or equal to 1.90
536+
* which was the first version that had this fix built in
537+
*/
538+
if (((buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1)
539+
a6xx_gpu->has_whereami = true;
540+
else if ((buf[0] & 0xfff) > 0x190)
541+
a6xx_gpu->has_whereami = true;
542+
543+
msm_gem_put_vaddr(obj);
544+
}
545+
511546
static int a6xx_ucode_init(struct msm_gpu *gpu)
512547
{
513548
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -528,6 +563,7 @@ static int a6xx_ucode_init(struct msm_gpu *gpu)
528563
}
529564

530565
msm_gem_object_set_name(a6xx_gpu->sqe_bo, "sqefw");
566+
a6xx_ucode_check_version(a6xx_gpu, a6xx_gpu->sqe_bo);
531567
}
532568

533569
gpu_write64(gpu, REG_A6XX_CP_SQE_INSTR_BASE_LO,
@@ -743,8 +779,37 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
743779
gpu_write64(gpu, REG_A6XX_CP_RB_BASE, REG_A6XX_CP_RB_BASE_HI,
744780
gpu->rb[0]->iova);
745781

746-
gpu_write(gpu, REG_A6XX_CP_RB_CNTL,
747-
MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
782+
/* Targets that support extended APRIV can use the RPTR shadow from
783+
* hardware but all the other ones need to disable the feature. Targets
784+
* that support the WHERE_AM_I opcode can use that instead
785+
*/
786+
if (adreno_gpu->base.hw_apriv)
787+
gpu_write(gpu, REG_A6XX_CP_RB_CNTL, MSM_GPU_RB_CNTL_DEFAULT);
788+
else
789+
gpu_write(gpu, REG_A6XX_CP_RB_CNTL,
790+
MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE);
791+
792+
/*
793+
* Expanded APRIV and targets that support WHERE_AM_I both need a
794+
* privileged buffer to store the RPTR shadow
795+
*/
796+
797+
if (adreno_gpu->base.hw_apriv || a6xx_gpu->has_whereami) {
798+
if (!a6xx_gpu->shadow_bo) {
799+
a6xx_gpu->shadow = msm_gem_kernel_new_locked(gpu->dev,
800+
sizeof(u32) * gpu->nr_rings,
801+
MSM_BO_UNCACHED | MSM_BO_MAP_PRIV,
802+
gpu->aspace, &a6xx_gpu->shadow_bo,
803+
&a6xx_gpu->shadow_iova);
804+
805+
if (IS_ERR(a6xx_gpu->shadow))
806+
return PTR_ERR(a6xx_gpu->shadow);
807+
}
808+
809+
gpu_write64(gpu, REG_A6XX_CP_RB_RPTR_ADDR_LO,
810+
REG_A6XX_CP_RB_RPTR_ADDR_HI,
811+
shadowptr(a6xx_gpu, gpu->rb[0]));
812+
}
748813

749814
/* Always come up on rb 0 */
750815
a6xx_gpu->cur_ring = gpu->rb[0];
@@ -1033,6 +1098,11 @@ static void a6xx_destroy(struct msm_gpu *gpu)
10331098
drm_gem_object_put(a6xx_gpu->sqe_bo);
10341099
}
10351100

1101+
if (a6xx_gpu->shadow_bo) {
1102+
msm_gem_unpin_iova(a6xx_gpu->shadow_bo, gpu->aspace);
1103+
drm_gem_object_put(a6xx_gpu->shadow_bo);
1104+
}
1105+
10361106
a6xx_gmu_remove(a6xx_gpu);
10371107

10381108
adreno_gpu_cleanup(adreno_gpu);
@@ -1081,6 +1151,17 @@ a6xx_create_private_address_space(struct msm_gpu *gpu)
10811151
"gpu", 0x100000000ULL, 0x1ffffffffULL);
10821152
}
10831153

1154+
static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
1155+
{
1156+
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
1157+
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
1158+
1159+
if (adreno_gpu->base.hw_apriv || a6xx_gpu->has_whereami)
1160+
return a6xx_gpu->shadow[ring->id];
1161+
1162+
return ring->memptrs->rptr = gpu_read(gpu, REG_A6XX_CP_RB_RPTR);
1163+
}
1164+
10841165
static const struct adreno_gpu_funcs funcs = {
10851166
.base = {
10861167
.get_param = adreno_get_param,
@@ -1089,7 +1170,6 @@ static const struct adreno_gpu_funcs funcs = {
10891170
.pm_resume = a6xx_pm_resume,
10901171
.recover = a6xx_recover,
10911172
.submit = a6xx_submit,
1092-
.flush = a6xx_flush,
10931173
.active_ring = a6xx_active_ring,
10941174
.irq = a6xx_irq,
10951175
.destroy = a6xx_destroy,
@@ -1105,6 +1185,7 @@ static const struct adreno_gpu_funcs funcs = {
11051185
#endif
11061186
.create_address_space = adreno_iommu_create_address_space,
11071187
.create_private_address_space = a6xx_create_private_address_space,
1188+
.get_rptr = a6xx_get_rptr,
11081189
},
11091190
.get_timestamp = a6xx_get_timestamp,
11101191
};

drivers/gpu/drm/msm/adreno/a6xx_gpu.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ struct a6xx_gpu {
2222
struct msm_file_private *cur_ctx;
2323

2424
struct a6xx_gmu gmu;
25+
26+
struct drm_gem_object *shadow_bo;
27+
uint64_t shadow_iova;
28+
uint32_t *shadow;
29+
30+
bool has_whereami;
2531
};
2632

2733
#define to_a6xx_gpu(x) container_of(x, struct a6xx_gpu, base)
@@ -51,6 +57,9 @@ static inline bool a6xx_has_gbif(struct adreno_gpu *gpu)
5157
return true;
5258
}
5359

60+
#define shadowptr(_a6xx_gpu, _ring) ((_a6xx_gpu)->shadow_iova + \
61+
((_ring)->id * sizeof(uint32_t)))
62+
5463
int a6xx_gmu_resume(struct a6xx_gpu *gpu);
5564
int a6xx_gmu_stop(struct a6xx_gpu *gpu);
5665

0 commit comments

Comments
 (0)