Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 125

kernel-2.6.18-238.el5.src.rpm

From: Bhavana Nagendra <bnagendr@redhat.com>
Subject: Re: [RHEL5.1 PATCH : Fix AMD-64 AGP aperture validation
Date: Thu, 17 May 2007 10:36:07 -0400
Bugzilla: 236826
Message-Id: <464C6857.9030603@redhat.com>
Changelog: [agp] Fix AMD-64 AGP aperture validation


>>This fix is needed if RHEL5 defaults to CONFIG_DISCONTIGMEM and a quick 
>>look at .config looks like it does.  Though the default memory mapping in 
>>RHEL5 is sparse,
>>the patch is useful for those who prefer to use discongtiguous memory -- 
>>checked with Don Z.
>>
>>Under CONFIG_DISCONTIGMEM, assuming that a !pfn_valid() implies all 
>>subsequent pfn-s are also invalid is wrong. Thus replace this by 
>>explicitly checking against the E820 map.
>>
>>Upstream status: Patch has been accepted.
>>Upstream path: http://lkml.org/lkml/2007/3/29/39
>>

--- linux-2.6.18.x86_64/drivers/char/agp/amd64-agp.c.agporig	2007-05-17 09:47:53.000000000 -0400
+++ linux-2.6.18.x86_64/drivers/char/agp/amd64-agp.c	2007-05-17 10:14:57.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/mmzone.h>
 #include <asm/page.h>		/* PAGE_SIZE */
 #include <asm/k8.h>
+#include <asm/e820.h>
 #include "agp.h"
 
 /* PTE bits. */
@@ -252,7 +253,6 @@ static struct agp_bridge_driver amd_8151
 /* Some basic sanity checks for the aperture. */
 static int __devinit aperture_valid(u64 aper, u32 size)
 {
-	u32 pfn, c;
 	if (aper == 0) {
 		printk(KERN_ERR PFX "No aperture\n");
 		return 0;
@@ -265,14 +265,9 @@ static int __devinit aperture_valid(u64 
 		printk(KERN_ERR PFX "Aperture out of bounds\n");
 		return 0;
 	}
-	pfn = aper >> PAGE_SHIFT;
-	for (c = 0; c < size/PAGE_SIZE; c++) {
-		if (!pfn_valid(pfn + c))
-			break;
-		if (!PageReserved(pfn_to_page(pfn + c))) {
-			printk(KERN_ERR PFX "Aperture pointing to RAM\n");
-			return 0;
-		}
+	if (e820_any_mapped(aper, aper + size, E820_RAM)) {
+		printk(KERN_ERR PFX "Aperture pointing to RAM\n");
+		return 0;
 	}
 
 	/* Request the Aperture. This catches cases when someone else
--- linux-2.6.18.x86_64/arch/x86_64/kernel/e820.c.agporig	2007-05-17 09:54:50.000000000 -0400
+++ linux-2.6.18.x86_64/arch/x86_64/kernel/e820.c	2007-05-16 16:08:35.000000000 -0400
@@ -94,7 +94,7 @@ static inline int bad_addr(unsigned long
  * This function checks if any part of the range <start,end> is mapped
  * with type.
  */
-int __meminit
+int
 e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
 { 
 	int i;
@@ -108,6 +108,7 @@ e820_any_mapped(unsigned long start, uns
 	} 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(e820_any_mapped);
 
 /*
  * This function checks if the entire range <start,end> is mapped with type.
--- linux-2.6.18.x86_64/arch/i386/kernel/setup-xen.c.agporig	2007-05-17 10:09:07.000000000 -0400
+++ linux-2.6.18.x86_64/arch/i386/kernel/setup-xen.c	2007-05-17 10:30:13.000000000 -0400
@@ -395,6 +395,25 @@ EXPORT_SYMBOL(phys_to_machine_mapping);
 start_info_t *xen_start_info;
 EXPORT_SYMBOL(xen_start_info);
 
+/*
+ * This function checks if any part of the range <start,end> is mapped
+ * with type.
+ */
+int
+e820_any_mapped(u64 start, u64 end, unsigned type)
+{
+        int i;
+        for (i = 0; i < e820.nr_map; i++) {
+                const struct e820entry *ei = &e820.map[i];
+                if (type && ei->type != type)
+                        continue;
+                if (ei->addr >= end || ei->addr + ei->size <= start)
+                        continue;
+                return 1;
+        }
+        return 0;
+}
+
 void __init add_memory_region(unsigned long long start,
                                   unsigned long long size, int type)
 {
--- linux-2.6.18.x86_64/arch/i386/kernel/setup.c.agporig	2007-05-17 09:54:09.000000000 -0400
+++ linux-2.6.18.x86_64/arch/i386/kernel/setup.c	2007-05-17 09:53:13.000000000 -0400
@@ -409,6 +409,26 @@ static void __init limit_regions(unsigne
 	}
 }
 
+/*
+ * This function checks if any part of the range <start,end> is mapped
+ * with type.
+ */
+int
+e820_any_mapped(u64 start, u64 end, unsigned type)
+{
+	int i;
+	for (i = 0; i < e820.nr_map; i++) {
+		const struct e820entry *ei = &e820.map[i];
+		if (type && ei->type != type)
+			continue;
+		if (ei->addr >= end || ei->addr + ei->size <= start)
+			continue;
+		return 1;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(e820_any_mapped);
+
 void __init add_memory_region(unsigned long long start,
 			      unsigned long long size, int type)
 {

diff -urN ../kernel-2.6.18/linux-2.6.18.i686/include/asm-i386/e820.h linux-2.6.18.i686/include/asm-i386/e820.h
--- ../kernel-2.6.18/linux-2.6.18.i686/include/asm-i386/e820.h	2006-09-19 23:42:06.000000000 -0400
+++ linux-2.6.18.i686/include/asm-i386/e820.h	2007-06-22 03:04:38.000000000 -0400
@@ -36,6 +36,7 @@
 
 extern struct e820map e820;
 
+extern int e820_any_mapped(u64 start, u64 end, unsigned type);
 extern int e820_all_mapped(unsigned long start, unsigned long end,
 			   unsigned type);