diff options
author | Jan Beulich <jbeulich@novell.com> | 2007-05-02 13:27:11 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2007-05-02 13:27:11 -0400 |
commit | b92e9fac400d4ae5bc7a75c568e9844ec53ea329 (patch) | |
tree | 2e5d5194d2532a4d8d4849802e19adcc617013f6 | |
parent | b00742d399513a4100c24cc2accefdc1bb1e0b15 (diff) |
[PATCH] x86: fix amd64-agp aperture validation
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.
AK: make e820 on x86-64 not initdata
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Acked-by: Mark Langsdorf <mark.langsdorf@amd.com>
-rw-r--r-- | arch/i386/kernel/e820.c | 20 | ||||
-rw-r--r-- | arch/x86_64/kernel/e820.c | 5 | ||||
-rw-r--r-- | drivers/char/agp/amd64-agp.c | 13 | ||||
-rw-r--r-- | include/asm-i386/e820.h | 1 |
4 files changed, 28 insertions, 11 deletions
diff --git a/arch/i386/kernel/e820.c b/arch/i386/kernel/e820.c index 31f4670ef740..829beec9247e 100644 --- a/arch/i386/kernel/e820.c +++ b/arch/i386/kernel/e820.c | |||
@@ -825,6 +825,26 @@ void __init limit_regions(unsigned long long size) | |||
825 | print_memory_map("limit_regions endfunc"); | 825 | print_memory_map("limit_regions endfunc"); |
826 | } | 826 | } |
827 | 827 | ||
828 | /* | ||
829 | * This function checks if any part of the range <start,end> is mapped | ||
830 | * with type. | ||
831 | */ | ||
832 | int | ||
833 | e820_any_mapped(u64 start, u64 end, unsigned type) | ||
834 | { | ||
835 | int i; | ||
836 | for (i = 0; i < e820.nr_map; i++) { | ||
837 | const struct e820entry *ei = &e820.map[i]; | ||
838 | if (type && ei->type != type) | ||
839 | continue; | ||
840 | if (ei->addr >= end || ei->addr + ei->size <= start) | ||
841 | continue; | ||
842 | return 1; | ||
843 | } | ||
844 | return 0; | ||
845 | } | ||
846 | EXPORT_SYMBOL_GPL(e820_any_mapped); | ||
847 | |||
828 | /* | 848 | /* |
829 | * This function checks if the entire range <start,end> is mapped with type. | 849 | * This function checks if the entire range <start,end> is mapped with type. |
830 | * | 850 | * |
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index a490fabfcf47..be8965427a93 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <asm/bootsetup.h> | 25 | #include <asm/bootsetup.h> |
26 | #include <asm/sections.h> | 26 | #include <asm/sections.h> |
27 | 27 | ||
28 | struct e820map e820 __initdata; | 28 | struct e820map e820; |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * PFN of last memory page. | 31 | * PFN of last memory page. |
@@ -98,7 +98,7 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size) | |||
98 | * This function checks if any part of the range <start,end> is mapped | 98 | * This function checks if any part of the range <start,end> is mapped |
99 | * with type. | 99 | * with type. |
100 | */ | 100 | */ |
101 | int __meminit | 101 | int |
102 | e820_any_mapped(unsigned long start, unsigned long end, unsigned type) | 102 | e820_any_mapped(unsigned long start, unsigned long end, unsigned type) |
103 | { | 103 | { |
104 | int i; | 104 | int i; |
@@ -112,6 +112,7 @@ e820_any_mapped(unsigned long start, unsigned long end, unsigned type) | |||
112 | } | 112 | } |
113 | return 0; | 113 | return 0; |
114 | } | 114 | } |
115 | EXPORT_SYMBOL_GPL(e820_any_mapped); | ||
115 | 116 | ||
116 | /* | 117 | /* |
117 | * This function checks if the entire range <start,end> is mapped with type. | 118 | * This function checks if the entire range <start,end> is mapped with type. |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 485720486d60..c9f0f250d78f 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/agp_backend.h> | 14 | #include <linux/agp_backend.h> |
15 | #include <linux/mmzone.h> | 15 | #include <linux/mmzone.h> |
16 | #include <asm/page.h> /* PAGE_SIZE */ | 16 | #include <asm/page.h> /* PAGE_SIZE */ |
17 | #include <asm/e820.h> | ||
17 | #include <asm/k8.h> | 18 | #include <asm/k8.h> |
18 | #include "agp.h" | 19 | #include "agp.h" |
19 | 20 | ||
@@ -259,7 +260,6 @@ static const struct agp_bridge_driver amd_8151_driver = { | |||
259 | /* Some basic sanity checks for the aperture. */ | 260 | /* Some basic sanity checks for the aperture. */ |
260 | static int __devinit aperture_valid(u64 aper, u32 size) | 261 | static int __devinit aperture_valid(u64 aper, u32 size) |
261 | { | 262 | { |
262 | u32 pfn, c; | ||
263 | if (aper == 0) { | 263 | if (aper == 0) { |
264 | printk(KERN_ERR PFX "No aperture\n"); | 264 | printk(KERN_ERR PFX "No aperture\n"); |
265 | return 0; | 265 | return 0; |
@@ -272,14 +272,9 @@ static int __devinit aperture_valid(u64 aper, u32 size) | |||
272 | printk(KERN_ERR PFX "Aperture out of bounds\n"); | 272 | printk(KERN_ERR PFX "Aperture out of bounds\n"); |
273 | return 0; | 273 | return 0; |
274 | } | 274 | } |
275 | pfn = aper >> PAGE_SHIFT; | 275 | if (e820_any_mapped(aper, aper + size, E820_RAM)) { |
276 | for (c = 0; c < size/PAGE_SIZE; c++) { | 276 | printk(KERN_ERR PFX "Aperture pointing to RAM\n"); |
277 | if (!pfn_valid(pfn + c)) | 277 | return 0; |
278 | break; | ||
279 | if (!PageReserved(pfn_to_page(pfn + c))) { | ||
280 | printk(KERN_ERR PFX "Aperture pointing to RAM\n"); | ||
281 | return 0; | ||
282 | } | ||
283 | } | 278 | } |
284 | 279 | ||
285 | /* Request the Aperture. This catches cases when someone else | 280 | /* Request the Aperture. This catches cases when someone else |
diff --git a/include/asm-i386/e820.h b/include/asm-i386/e820.h index c5b8fc6109d6..096a2a8eb1da 100644 --- a/include/asm-i386/e820.h +++ b/include/asm-i386/e820.h | |||
@@ -38,6 +38,7 @@ extern struct e820map e820; | |||
38 | 38 | ||
39 | extern int e820_all_mapped(unsigned long start, unsigned long end, | 39 | extern int e820_all_mapped(unsigned long start, unsigned long end, |
40 | unsigned type); | 40 | unsigned type); |
41 | extern int e820_any_mapped(u64 start, u64 end, unsigned type); | ||
41 | extern void find_max_pfn(void); | 42 | extern void find_max_pfn(void); |
42 | extern void register_bootmem_low_pages(unsigned long max_low_pfn); | 43 | extern void register_bootmem_low_pages(unsigned long max_low_pfn); |
43 | extern void e820_register_memory(void); | 44 | extern void e820_register_memory(void); |