OSDN Git Service

radeon: Fix u32 overflows when determining AGP base address in card space.
authorMichel Dänzer <michel@tungstengraphics.com>
Thu, 11 Jan 2007 08:02:07 +0000 (09:02 +0100)
committerMichel Dänzer <michel@tungstengraphics.com>
Thu, 11 Jan 2007 08:02:07 +0000 (09:02 +0100)
The overflows could lead to the AGP aperture overlapping the framebuffer area
in the card's address space when the latter is located at the very end of the
32 bit address space, which would result in a freeze on X server startup,
probably because the card read commands from the framebuffer instead of from
AGP.

See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=392915 .

shared-core/radeon_cp.c

index 4135f4d..0fa6535 100644 (file)
@@ -1563,8 +1563,8 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                if (dev_priv->flags & RADEON_IS_AGP) {
                        base = dev->agp->base;
                        /* Check if valid */
-                       if ((base + dev_priv->gart_size) > dev_priv->fb_location &&
-                           base < (dev_priv->fb_location + dev_priv->fb_size)) {
+                       if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location &&
+                           base < (dev_priv->fb_location + dev_priv->fb_size - 1)) {
                                DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
                                         dev->agp->base);
                                base = 0;
@@ -1574,8 +1574,8 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
                /* If not or if AGP is at 0 (Macs), try to put it elsewhere */
                if (base == 0) {
                        base = dev_priv->fb_location + dev_priv->fb_size;
-                       if (((base + dev_priv->gart_size) & 0xfffffffful)
-                           < base)
+                       if (base < dev_priv->fb_location ||
+                           ((base + dev_priv->gart_size) & 0xfffffffful) < base)
                                base = dev_priv->fb_location
                                        - dev_priv->gart_size;
                }