summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alexander.deucher@amd.com>2011-10-18 20:10:05 -0400
committerDave Airlie <airlied@redhat.com>2011-10-19 09:47:47 +0100
commit5a6e8482a16e61250a9121fc9ec719ab0529e760 (patch)
treed69c0e903f122acff0accf0e6f6e9bb4b9f2ce5d
parenta4863ca93ccc52a83e7fbfc068b411b7faa03805 (diff)
drm/radeon/kms/atom: fix handling of FB scratch indices
FB scratch indices are dword indices, but we were treating them as byte indices. As such, we were getting the wrong FB scratch data for non-0 indices. Fix the indices and guard the indexing against indices larger than the scratch allocation. Fixes memory corruption on some boards if data was written past the end of the FB scratch array. Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Reported-by: Dave Airlie <airlied@redhat.com> Tested-by: Dave Airlie <airlied@redhat.com> Cc: stable@kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/atom.c15
-rw-r--r--drivers/gpu/drm/radeon/atom.h1
2 files changed, 14 insertions, 2 deletions
diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c
index e88c64417a8..14cc88aaf3a 100644
--- a/drivers/gpu/drm/radeon/atom.c
+++ b/drivers/gpu/drm/radeon/atom.c
@@ -277,7 +277,12 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
case ATOM_ARG_FB:
idx = U8(*ptr);
(*ptr)++;
- val = gctx->scratch[((gctx->fb_base + idx) / 4)];
+ if ((gctx->fb_base + (idx * 4)) > gctx->scratch_size_bytes) {
+ DRM_ERROR("ATOM: fb read beyond scratch region: %d vs. %d\n",
+ gctx->fb_base + (idx * 4), gctx->scratch_size_bytes);
+ val = 0;
+ } else
+ val = gctx->scratch[(gctx->fb_base / 4) + idx];
if (print)
DEBUG("FB[0x%02X]", idx);
break;
@@ -531,7 +536,11 @@ static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr,
case ATOM_ARG_FB:
idx = U8(*ptr);
(*ptr)++;
- gctx->scratch[((gctx->fb_base + idx) / 4)] = val;
+ if ((gctx->fb_base + (idx * 4)) > gctx->scratch_size_bytes) {
+ DRM_ERROR("ATOM: fb write beyond scratch region: %d vs. %d\n",
+ gctx->fb_base + (idx * 4), gctx->scratch_size_bytes);
+ } else
+ gctx->scratch[(gctx->fb_base / 4) + idx] = val;
DEBUG("FB[0x%02X]", idx);
break;
case ATOM_ARG_PLL:
@@ -1370,11 +1379,13 @@ int atom_allocate_fb_scratch(struct atom_context *ctx)
usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
}
+ ctx->scratch_size_bytes = 0;
if (usage_bytes == 0)
usage_bytes = 20 * 1024;
/* allocate some scratch memory */
ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL);
if (!ctx->scratch)
return -ENOMEM;
+ ctx->scratch_size_bytes = usage_bytes;
return 0;
}
diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h
index a589a55b223..93cfe2086ba 100644
--- a/drivers/gpu/drm/radeon/atom.h
+++ b/drivers/gpu/drm/radeon/atom.h
@@ -137,6 +137,7 @@ struct atom_context {
int cs_equal, cs_above;
int io_mode;
uint32_t *scratch;
+ int scratch_size_bytes;
};
extern int atom_debug;