| From 5a6e8482a16e61250a9121fc9ec719ab0529e760 Mon Sep 17 00:00:00 2001 |
| From: Alex Deucher <alexander.deucher@amd.com> |
| Date: Tue, 18 Oct 2011 20:10:05 -0400 |
| Subject: drm/radeon/kms/atom: fix handling of FB scratch indices |
| |
| From: Alex Deucher <alexander.deucher@amd.com> |
| |
| commit 5a6e8482a16e61250a9121fc9ec719ab0529e760 upstream. |
| |
| 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> |
| Signed-off-by: Dave Airlie <airlied@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/gpu/drm/radeon/atom.c | 15 +++++++++++++-- |
| drivers/gpu/drm/radeon/atom.h | 1 + |
| 2 files changed, 14 insertions(+), 2 deletions(-) |
| |
| --- 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_ex |
| 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_conte |
| 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: |
| @@ -1367,11 +1376,13 @@ int atom_allocate_fb_scratch(struct atom |
| |
| 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; |
| } |
| --- 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; |