diff --git a/sys/dev/drm/radeon/r600_cs.c b/sys/dev/drm/radeon/r600_cs.c --- a/sys/dev/drm/radeon/r600_cs.c +++ b/sys/dev/drm/radeon/r600_cs.c @@ -351,6 +351,7 @@ { struct r600_cs_track *track = p->track; u32 slice_tile_max, size, tmp; + u64 tmp64; u32 height, height_align, pitch, pitch_align, depth_align; u64 base_offset, base_align; struct array_mode_checker array_check; @@ -426,21 +427,22 @@ return -EINVAL; } - /* check offset */ - tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) * - r600_fmt_get_blocksize(format) * nsamples; + /* check offset -- computed in 64-bit to avoid u32 overflow */ + tmp64 = (u64)r600_fmt_get_nblocksy(format, height) * + r600_fmt_get_nblocksx(format, pitch) * + r600_fmt_get_blocksize(format) * nsamples; switch (array_mode) { default: case V_0280A0_ARRAY_LINEAR_GENERAL: case V_0280A0_ARRAY_LINEAR_ALIGNED: - tmp += track->cb_color_view[i] & 0xFF; + tmp64 += track->cb_color_view[i] & 0xFF; break; case V_0280A0_ARRAY_1D_TILED_THIN1: case V_0280A0_ARRAY_2D_TILED_THIN1: - tmp += G_028080_SLICE_MAX(track->cb_color_view[i]) * tmp; + tmp64 += (u64)G_028080_SLICE_MAX(track->cb_color_view[i]) * tmp64; break; } - if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { + if ((tmp64 + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) { if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) { /* the initial DDX does bad things with the CB size occasionally */ /* it rounds up height too far for slice tile max but the BO is smaller */ @@ -449,9 +451,9 @@ * broken userspace. */ } else { - dev_warn(p->dev, "%s offset[%d] %d %llu %d %lu too big (%d %d) (%d %d %d)\n", + dev_warn(p->dev, "%s offset[%d] %d %llu %llu %lu too big (%d %d) (%d %d %d)\n", __func__, i, array_mode, - track->cb_color_bo_offset[i], tmp, + track->cb_color_bo_offset[i], tmp64, radeon_bo_size(track->cb_color_bo[i]), pitch, height, r600_fmt_get_nblocksx(format, pitch), r600_fmt_get_nblocksy(format, height), @@ -517,7 +519,8 @@ static int r600_cs_track_validate_db(struct radeon_cs_parser *p) { struct r600_cs_track *track = p->track; - u32 nviews, bpe, ntiles, size, slice_tile_max, tmp; + u32 nviews, bpe, ntiles, size, slice_tile_max; + u64 tmp; u32 height_align, pitch_align, depth_align; u32 pitch = 8192; u32 height = 8192; @@ -619,9 +622,9 @@ ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1; nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1; - tmp = ntiles * bpe * 64 * nviews * track->nsamples; + tmp = (u64)ntiles * bpe * 64 * nviews * track->nsamples; if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) { - dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n", + dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %llu have %lu)\n", array_mode, track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset, radeon_bo_size(track->db_bo));