aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
author=?utf-8?q?Michel_D=C3=A4nzer?= <michel@tungstengraphics.com>2006-12-15 02:54:35 -0500
committerDave Airlie <airlied@linux.ie>2006-12-15 02:54:35 -0500
commit1d6bb8e51dba3db1c15575901022fe72d363e5a4 (patch)
treed7a3a26d427050ab3d7ca76d9df5083afc3df888 /drivers/char
parent3188a24c256bae0ed93d81d82db1f1bb6060d727 (diff)
drm: Unify radeon offset checking.
Replace r300_check_offset() with generic radeon_check_offset(), which doesn't reject valid offsets when the framebuffer area is at the very end of the card's 32 bit address space. Make radeon_check_and_fixup_offset() use radeon_check_offset() as well. This fixes https://bugs.freedesktop.org/show_bug.cgi?id=7697 .
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/drm/r300_cmdbuf.c32
-rw-r--r--drivers/char/drm/radeon_drv.h15
-rw-r--r--drivers/char/drm/radeon_state.c13
3 files changed, 25 insertions, 35 deletions
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c
index d14477ba3679..032a022ec6a8 100644
--- a/drivers/char/drm/r300_cmdbuf.c
+++ b/drivers/char/drm/r300_cmdbuf.c
@@ -242,26 +242,6 @@ static __inline__ int r300_check_range(unsigned reg, int count)
242 return 0; 242 return 0;
243} 243}
244 244
245/*
246 * we expect offsets passed to the framebuffer to be either within video
247 * memory or within AGP space
248 */
249static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv,
250 u32 offset)
251{
252 /* we realy want to check against end of video aperture
253 but this value is not being kept.
254 This code is correct for now (does the same thing as the
255 code that sets MC_FB_LOCATION) in radeon_cp.c */
256 if (offset >= dev_priv->fb_location &&
257 offset < (dev_priv->fb_location + dev_priv->fb_size))
258 return 0;
259 if (offset >= dev_priv->gart_vm_start &&
260 offset < (dev_priv->gart_vm_start + dev_priv->gart_size))
261 return 0;
262 return 1;
263}
264
265static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t * 245static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
266 dev_priv, 246 dev_priv,
267 drm_radeon_kcmd_buffer_t 247 drm_radeon_kcmd_buffer_t
@@ -290,7 +270,7 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t *
290 case MARK_SAFE: 270 case MARK_SAFE:
291 break; 271 break;
292 case MARK_CHECK_OFFSET: 272 case MARK_CHECK_OFFSET:
293 if (r300_check_offset(dev_priv, (u32) values[i])) { 273 if (!radeon_check_offset(dev_priv, (u32) values[i])) {
294 DRM_ERROR 274 DRM_ERROR
295 ("Offset failed range check (reg=%04x sz=%d)\n", 275 ("Offset failed range check (reg=%04x sz=%d)\n",
296 reg, sz); 276 reg, sz);
@@ -452,7 +432,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
452 i = 1; 432 i = 1;
453 while ((k < narrays) && (i < (count + 1))) { 433 while ((k < narrays) && (i < (count + 1))) {
454 i++; /* skip attribute field */ 434 i++; /* skip attribute field */
455 if (r300_check_offset(dev_priv, payload[i])) { 435 if (!radeon_check_offset(dev_priv, payload[i])) {
456 DRM_ERROR 436 DRM_ERROR
457 ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", 437 ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
458 k, i); 438 k, i);
@@ -463,7 +443,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv,
463 if (k == narrays) 443 if (k == narrays)
464 break; 444 break;
465 /* have one more to process, they come in pairs */ 445 /* have one more to process, they come in pairs */
466 if (r300_check_offset(dev_priv, payload[i])) { 446 if (!radeon_check_offset(dev_priv, payload[i])) {
467 DRM_ERROR 447 DRM_ERROR
468 ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", 448 ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n",
469 k, i); 449 k, i);
@@ -508,7 +488,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
508 if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL 488 if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
509 | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { 489 | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
510 offset = cmd[2] << 10; 490 offset = cmd[2] << 10;
511 ret = r300_check_offset(dev_priv, offset); 491 ret = !radeon_check_offset(dev_priv, offset);
512 if (ret) { 492 if (ret) {
513 DRM_ERROR("Invalid bitblt first offset is %08X\n", offset); 493 DRM_ERROR("Invalid bitblt first offset is %08X\n", offset);
514 return DRM_ERR(EINVAL); 494 return DRM_ERR(EINVAL);
@@ -518,7 +498,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv,
518 if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && 498 if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
519 (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { 499 (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
520 offset = cmd[3] << 10; 500 offset = cmd[3] << 10;
521 ret = r300_check_offset(dev_priv, offset); 501 ret = !radeon_check_offset(dev_priv, offset);
522 if (ret) { 502 if (ret) {
523 DRM_ERROR("Invalid bitblt second offset is %08X\n", offset); 503 DRM_ERROR("Invalid bitblt second offset is %08X\n", offset);
524 return DRM_ERR(EINVAL); 504 return DRM_ERR(EINVAL);
@@ -551,7 +531,7 @@ static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv,
551 DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); 531 DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]);
552 return DRM_ERR(EINVAL); 532 return DRM_ERR(EINVAL);
553 } 533 }
554 ret = r300_check_offset(dev_priv, cmd[2]); 534 ret = !radeon_check_offset(dev_priv, cmd[2]);
555 if (ret) { 535 if (ret) {
556 DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); 536 DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]);
557 return DRM_ERR(EINVAL); 537 return DRM_ERR(EINVAL);
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index f45cd7f147a5..8b105f1460a7 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -303,6 +303,21 @@ extern int radeon_no_wb;
303extern drm_ioctl_desc_t radeon_ioctls[]; 303extern drm_ioctl_desc_t radeon_ioctls[];
304extern int radeon_max_ioctl; 304extern int radeon_max_ioctl;
305 305
306/* Check whether the given hardware address is inside the framebuffer or the
307 * GART area.
308 */
309static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv,
310 u64 off)
311{
312 u32 fb_start = dev_priv->fb_location;
313 u32 fb_end = fb_start + dev_priv->fb_size - 1;
314 u32 gart_start = dev_priv->gart_vm_start;
315 u32 gart_end = gart_start + dev_priv->gart_size - 1;
316
317 return ((off >= fb_start && off <= fb_end) ||
318 (off >= gart_start && off <= gart_end));
319}
320
306 /* radeon_cp.c */ 321 /* radeon_cp.c */
307extern int radeon_cp_init(DRM_IOCTL_ARGS); 322extern int radeon_cp_init(DRM_IOCTL_ARGS);
308extern int radeon_cp_start(DRM_IOCTL_ARGS); 323extern int radeon_cp_start(DRM_IOCTL_ARGS);
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index 6e04fdd732ac..938eccb78cc0 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -43,10 +43,7 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
43 u32 *offset) 43 u32 *offset)
44{ 44{
45 u64 off = *offset; 45 u64 off = *offset;
46 u32 fb_start = dev_priv->fb_location; 46 u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1;
47 u32 fb_end = fb_start + dev_priv->fb_size - 1;
48 u32 gart_start = dev_priv->gart_vm_start;
49 u32 gart_end = gart_start + dev_priv->gart_size - 1;
50 struct drm_radeon_driver_file_fields *radeon_priv; 47 struct drm_radeon_driver_file_fields *radeon_priv;
51 48
52 /* Hrm ... the story of the offset ... So this function converts 49 /* Hrm ... the story of the offset ... So this function converts
@@ -66,8 +63,7 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
66 /* First, the best case, the offset already lands in either the 63 /* First, the best case, the offset already lands in either the
67 * framebuffer or the GART mapped space 64 * framebuffer or the GART mapped space
68 */ 65 */
69 if ((off >= fb_start && off <= fb_end) || 66 if (radeon_check_offset(dev_priv, off))
70 (off >= gart_start && off <= gart_end))
71 return 0; 67 return 0;
72 68
73 /* Ok, that didn't happen... now check if we have a zero based 69 /* Ok, that didn't happen... now check if we have a zero based
@@ -81,11 +77,10 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t *
81 77
82 /* Finally, assume we aimed at a GART offset if beyond the fb */ 78 /* Finally, assume we aimed at a GART offset if beyond the fb */
83 if (off > fb_end) 79 if (off > fb_end)
84 off = off - fb_end - 1 + gart_start; 80 off = off - fb_end - 1 + dev_priv->gart_vm_start;
85 81
86 /* Now recheck and fail if out of bounds */ 82 /* Now recheck and fail if out of bounds */
87 if ((off >= fb_start && off <= fb_end) || 83 if (radeon_check_offset(dev_priv, off)) {
88 (off >= gart_start && off <= gart_end)) {
89 DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off); 84 DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off);
90 *offset = off; 85 *offset = off;
91 return 0; 86 return 0;