aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt4
-rw-r--r--arch/x86/kernel/aperture_64.c89
-rw-r--r--arch/x86/kernel/e820_64.c12
-rw-r--r--arch/x86/kernel/setup_64.c3
-rw-r--r--include/asm-x86/e820_64.h1
-rw-r--r--include/asm-x86/gart.h5
6 files changed, 114 insertions, 0 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 40db7dd1d92..860a9087549 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 52d2beac455..bf1b469d584 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
221static int gart_fix_e820 __initdata = 1;
222
223static 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}
235early_param("gart_fix_e820", parse_gart_mem);
236
237void __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
221void __init gart_iommu_hole_init(void) 310void __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 abc473bcabe..07cfaae7ab0 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
731void __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
731unsigned long pci_mem_start = 0xaeedbabe; 743unsigned long pci_mem_start = 0xaeedbabe;
732EXPORT_SYMBOL(pci_mem_start); 744EXPORT_SYMBOL(pci_mem_start);
733 745
diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
index 07547febac7..12bad27d66f 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 8cba49da479..ff36f434f00 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,
39extern void finish_e820_parsing(void); 39extern void finish_e820_parsing(void);
40 40
41extern struct e820map e820; 41extern struct e820map e820;
42extern void update_e820(void);
42 43
43extern unsigned ebda_addr, ebda_size; 44extern unsigned ebda_addr, ebda_size;
44extern unsigned long nodemap_addr, nodemap_size; 45extern unsigned long nodemap_addr, nodemap_size;
diff --git a/include/asm-x86/gart.h b/include/asm-x86/gart.h
index f704c50519b..90958ed993f 100644
--- a/include/asm-x86/gart.h
+++ b/include/asm-x86/gart.h
@@ -9,6 +9,7 @@ extern int iommu_detected;
9extern void gart_iommu_init(void); 9extern void gart_iommu_init(void);
10extern void gart_iommu_shutdown(void); 10extern void gart_iommu_shutdown(void);
11extern void __init gart_parse_options(char *); 11extern void __init gart_parse_options(char *);
12extern void early_gart_iommu_check(void);
12extern void gart_iommu_hole_init(void); 13extern void gart_iommu_hole_init(void);
13extern int fallback_aper_order; 14extern int fallback_aper_order;
14extern int fallback_aper_force; 15extern 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
24static inline void early_gart_iommu_check(void)
25{
26}
27
23static inline void gart_iommu_shutdown(void) 28static inline void gart_iommu_shutdown(void)
24{ 29{
25} 30}