diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 4 | ||||
-rw-r--r-- | arch/x86/kernel/aperture_64.c | 89 | ||||
-rw-r--r-- | arch/x86/kernel/e820_64.c | 12 | ||||
-rw-r--r-- | arch/x86/kernel/setup_64.c | 3 | ||||
-rw-r--r-- | include/asm-x86/e820_64.h | 1 | ||||
-rw-r--r-- | include/asm-x86/gart.h | 5 |
6 files changed, 114 insertions, 0 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 40db7dd1d92a..860a90875491 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -660,6 +660,10 @@ and is between 256 and 4096 characters. It is defined in the file | |||
660 | 660 | ||
661 | gamma= [HW,DRM] | 661 | gamma= [HW,DRM] |
662 | 662 | ||
663 | gart_fix_e820= [X86_64] disable the fix e820 for K8 GART | ||
664 | Format: off | on | ||
665 | default: on | ||
666 | |||
663 | gdth= [HW,SCSI] | 667 | gdth= [HW,SCSI] |
664 | See header of drivers/scsi/gdth.c. | 668 | See header of drivers/scsi/gdth.c. |
665 | 669 | ||
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index 52d2beac4556..bf1b469d5847 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c | |||
@@ -218,6 +218,95 @@ static __u32 __init search_agp_bridge(u32 *order, int *valid_agp) | |||
218 | return 0; | 218 | return 0; |
219 | } | 219 | } |
220 | 220 | ||
221 | static int gart_fix_e820 __initdata = 1; | ||
222 | |||
223 | static int __init parse_gart_mem(char *p) | ||
224 | { | ||
225 | if (!p) | ||
226 | return -EINVAL; | ||
227 | |||
228 | if (!strncmp(p, "off", 3)) | ||
229 | gart_fix_e820 = 0; | ||
230 | else if (!strncmp(p, "on", 2)) | ||
231 | gart_fix_e820 = 1; | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | early_param("gart_fix_e820", parse_gart_mem); | ||
236 | |||
237 | void __init early_gart_iommu_check(void) | ||
238 | { | ||
239 | /* | ||
240 | * in case it is enabled before, esp for kexec/kdump, | ||
241 | * previous kernel already enable that. memset called | ||
242 | * by allocate_aperture/__alloc_bootmem_nopanic cause restart. | ||
243 | * or second kernel have different position for GART hole. and new | ||
244 | * kernel could use hole as RAM that is still used by GART set by | ||
245 | * first kernel | ||
246 | * or BIOS forget to put that in reserved. | ||
247 | * try to update e820 to make that region as reserved. | ||
248 | */ | ||
249 | int fix, num; | ||
250 | u32 ctl; | ||
251 | u32 aper_size = 0, aper_order = 0, last_aper_order = 0; | ||
252 | u64 aper_base = 0, last_aper_base = 0; | ||
253 | int aper_enabled = 0, last_aper_enabled = 0; | ||
254 | |||
255 | if (!early_pci_allowed()) | ||
256 | return; | ||
257 | |||
258 | fix = 0; | ||
259 | for (num = 24; num < 32; num++) { | ||
260 | if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) | ||
261 | continue; | ||
262 | |||
263 | ctl = read_pci_config(0, num, 3, 0x90); | ||
264 | aper_enabled = ctl & 1; | ||
265 | aper_order = (ctl >> 1) & 7; | ||
266 | aper_size = (32 * 1024 * 1024) << aper_order; | ||
267 | aper_base = read_pci_config(0, num, 3, 0x94) & 0x7fff; | ||
268 | aper_base <<= 25; | ||
269 | |||
270 | if ((last_aper_order && aper_order != last_aper_order) || | ||
271 | (last_aper_base && aper_base != last_aper_base) || | ||
272 | (last_aper_enabled && aper_enabled != last_aper_enabled)) { | ||
273 | fix = 1; | ||
274 | break; | ||
275 | } | ||
276 | last_aper_order = aper_order; | ||
277 | last_aper_base = aper_base; | ||
278 | last_aper_enabled = aper_enabled; | ||
279 | } | ||
280 | |||
281 | if (!fix && !aper_enabled) | ||
282 | return; | ||
283 | |||
284 | if (!aper_base || !aper_size || aper_base + aper_size > 0x100000000UL) | ||
285 | fix = 1; | ||
286 | |||
287 | if (gart_fix_e820 && !fix && aper_enabled) { | ||
288 | if (e820_any_mapped(aper_base, aper_base + aper_size, | ||
289 | E820_RAM)) { | ||
290 | /* reserved it, so we can resuse it in second kernel */ | ||
291 | printk(KERN_INFO "update e820 for GART\n"); | ||
292 | add_memory_region(aper_base, aper_size, E820_RESERVED); | ||
293 | update_e820(); | ||
294 | } | ||
295 | return; | ||
296 | } | ||
297 | |||
298 | /* different nodes have different setting, disable them all at first*/ | ||
299 | for (num = 24; num < 32; num++) { | ||
300 | if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00))) | ||
301 | continue; | ||
302 | |||
303 | ctl = read_pci_config(0, num, 3, 0x90); | ||
304 | ctl &= ~1; | ||
305 | write_pci_config(0, num, 3, 0x90, ctl); | ||
306 | } | ||
307 | |||
308 | } | ||
309 | |||
221 | void __init gart_iommu_hole_init(void) | 310 | void __init gart_iommu_hole_init(void) |
222 | { | 311 | { |
223 | u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0; | 312 | u32 aper_size, aper_alloc = 0, aper_order = 0, last_aper_order = 0; |
diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c index abc473bcabe8..07cfaae7ab07 100644 --- a/arch/x86/kernel/e820_64.c +++ b/arch/x86/kernel/e820_64.c | |||
@@ -728,6 +728,18 @@ void __init finish_e820_parsing(void) | |||
728 | } | 728 | } |
729 | } | 729 | } |
730 | 730 | ||
731 | void __init update_e820(void) | ||
732 | { | ||
733 | u8 nr_map; | ||
734 | |||
735 | nr_map = e820.nr_map; | ||
736 | if (sanitize_e820_map(e820.map, &nr_map)) | ||
737 | return; | ||
738 | e820.nr_map = nr_map; | ||
739 | printk(KERN_INFO "modified physical RAM map:\n"); | ||
740 | e820_print_map("modified"); | ||
741 | } | ||
742 | |||
731 | unsigned long pci_mem_start = 0xaeedbabe; | 743 | unsigned long pci_mem_start = 0xaeedbabe; |
732 | EXPORT_SYMBOL(pci_mem_start); | 744 | EXPORT_SYMBOL(pci_mem_start); |
733 | 745 | ||
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index 07547febac7a..12bad27d66f8 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <video/edid.h> | 53 | #include <video/edid.h> |
54 | #include <asm/e820.h> | 54 | #include <asm/e820.h> |
55 | #include <asm/dma.h> | 55 | #include <asm/dma.h> |
56 | #include <asm/gart.h> | ||
56 | #include <asm/mpspec.h> | 57 | #include <asm/mpspec.h> |
57 | #include <asm/mmu_context.h> | 58 | #include <asm/mmu_context.h> |
58 | #include <asm/proto.h> | 59 | #include <asm/proto.h> |
@@ -335,6 +336,8 @@ void __init setup_arch(char **cmdline_p) | |||
335 | 336 | ||
336 | finish_e820_parsing(); | 337 | finish_e820_parsing(); |
337 | 338 | ||
339 | early_gart_iommu_check(); | ||
340 | |||
338 | e820_register_active_regions(0, 0, -1UL); | 341 | e820_register_active_regions(0, 0, -1UL); |
339 | /* | 342 | /* |
340 | * partially used pages are not usable - thus | 343 | * partially used pages are not usable - thus |
diff --git a/include/asm-x86/e820_64.h b/include/asm-x86/e820_64.h index 8cba49da4795..ff36f434f00b 100644 --- a/include/asm-x86/e820_64.h +++ b/include/asm-x86/e820_64.h | |||
@@ -39,6 +39,7 @@ extern void e820_register_active_regions(int nid, | |||
39 | extern void finish_e820_parsing(void); | 39 | extern void finish_e820_parsing(void); |
40 | 40 | ||
41 | extern struct e820map e820; | 41 | extern struct e820map e820; |
42 | extern void update_e820(void); | ||
42 | 43 | ||
43 | extern unsigned ebda_addr, ebda_size; | 44 | extern unsigned ebda_addr, ebda_size; |
44 | extern unsigned long nodemap_addr, nodemap_size; | 45 | extern unsigned long nodemap_addr, nodemap_size; |
diff --git a/include/asm-x86/gart.h b/include/asm-x86/gart.h index f704c50519b8..90958ed993fa 100644 --- a/include/asm-x86/gart.h +++ b/include/asm-x86/gart.h | |||
@@ -9,6 +9,7 @@ extern int iommu_detected; | |||
9 | extern void gart_iommu_init(void); | 9 | extern void gart_iommu_init(void); |
10 | extern void gart_iommu_shutdown(void); | 10 | extern void gart_iommu_shutdown(void); |
11 | extern void __init gart_parse_options(char *); | 11 | extern void __init gart_parse_options(char *); |
12 | extern void early_gart_iommu_check(void); | ||
12 | extern void gart_iommu_hole_init(void); | 13 | extern void gart_iommu_hole_init(void); |
13 | extern int fallback_aper_order; | 14 | extern int fallback_aper_order; |
14 | extern int fallback_aper_force; | 15 | extern int fallback_aper_force; |
@@ -20,6 +21,10 @@ extern int fix_aperture; | |||
20 | #define gart_iommu_aperture 0 | 21 | #define gart_iommu_aperture 0 |
21 | #define gart_iommu_aperture_allowed 0 | 22 | #define gart_iommu_aperture_allowed 0 |
22 | 23 | ||
24 | static inline void early_gart_iommu_check(void) | ||
25 | { | ||
26 | } | ||
27 | |||
23 | static inline void gart_iommu_shutdown(void) | 28 | static inline void gart_iommu_shutdown(void) |
24 | { | 29 | { |
25 | } | 30 | } |