diff options
Diffstat (limited to 'arch/x86/mm/pat.c')
-rw-r--r-- | arch/x86/mm/pat.c | 74 |
1 files changed, 50 insertions, 24 deletions
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 8b08fb955274..9127e31c7268 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #ifdef CONFIG_X86_PAT | 30 | #ifdef CONFIG_X86_PAT |
31 | int __read_mostly pat_enabled = 1; | 31 | int __read_mostly pat_enabled = 1; |
32 | 32 | ||
33 | void __cpuinit pat_disable(char *reason) | 33 | void __cpuinit pat_disable(const char *reason) |
34 | { | 34 | { |
35 | pat_enabled = 0; | 35 | pat_enabled = 0; |
36 | printk(KERN_INFO "%s\n", reason); | 36 | printk(KERN_INFO "%s\n", reason); |
@@ -42,6 +42,11 @@ static int __init nopat(char *str) | |||
42 | return 0; | 42 | return 0; |
43 | } | 43 | } |
44 | early_param("nopat", nopat); | 44 | early_param("nopat", nopat); |
45 | #else | ||
46 | static inline void pat_disable(const char *reason) | ||
47 | { | ||
48 | (void)reason; | ||
49 | } | ||
45 | #endif | 50 | #endif |
46 | 51 | ||
47 | 52 | ||
@@ -78,16 +83,20 @@ void pat_init(void) | |||
78 | if (!pat_enabled) | 83 | if (!pat_enabled) |
79 | return; | 84 | return; |
80 | 85 | ||
81 | /* Paranoia check. */ | 86 | if (!cpu_has_pat) { |
82 | if (!cpu_has_pat && boot_pat_state) { | 87 | if (!boot_pat_state) { |
83 | /* | 88 | pat_disable("PAT not supported by CPU."); |
84 | * If this happens we are on a secondary CPU, but | 89 | return; |
85 | * switched to PAT on the boot CPU. We have no way to | 90 | } else { |
86 | * undo PAT. | 91 | /* |
87 | */ | 92 | * If this happens we are on a secondary CPU, but |
88 | printk(KERN_ERR "PAT enabled, " | 93 | * switched to PAT on the boot CPU. We have no way to |
89 | "but not supported by secondary CPU\n"); | 94 | * undo PAT. |
90 | BUG(); | 95 | */ |
96 | printk(KERN_ERR "PAT enabled, " | ||
97 | "but not supported by secondary CPU\n"); | ||
98 | BUG(); | ||
99 | } | ||
91 | } | 100 | } |
92 | 101 | ||
93 | /* Set PWT to Write-Combining. All other bits stay the same */ | 102 | /* Set PWT to Write-Combining. All other bits stay the same */ |
@@ -333,11 +342,23 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, | |||
333 | req_type & _PAGE_CACHE_MASK); | 342 | req_type & _PAGE_CACHE_MASK); |
334 | } | 343 | } |
335 | 344 | ||
336 | is_range_ram = pagerange_is_ram(start, end); | 345 | if (new_type) |
337 | if (is_range_ram == 1) | 346 | *new_type = actual_type; |
338 | return reserve_ram_pages_type(start, end, req_type, new_type); | 347 | |
339 | else if (is_range_ram < 0) | 348 | /* |
340 | return -EINVAL; | 349 | * For legacy reasons, some parts of the physical address range in the |
350 | * legacy 1MB region is treated as non-RAM (even when listed as RAM in | ||
351 | * the e820 tables). So we will track the memory attributes of this | ||
352 | * legacy 1MB region using the linear memtype_list always. | ||
353 | */ | ||
354 | if (end >= ISA_END_ADDRESS) { | ||
355 | is_range_ram = pagerange_is_ram(start, end); | ||
356 | if (is_range_ram == 1) | ||
357 | return reserve_ram_pages_type(start, end, req_type, | ||
358 | new_type); | ||
359 | else if (is_range_ram < 0) | ||
360 | return -EINVAL; | ||
361 | } | ||
341 | 362 | ||
342 | new = kmalloc(sizeof(struct memtype), GFP_KERNEL); | 363 | new = kmalloc(sizeof(struct memtype), GFP_KERNEL); |
343 | if (!new) | 364 | if (!new) |
@@ -347,9 +368,6 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, | |||
347 | new->end = end; | 368 | new->end = end; |
348 | new->type = actual_type; | 369 | new->type = actual_type; |
349 | 370 | ||
350 | if (new_type) | ||
351 | *new_type = actual_type; | ||
352 | |||
353 | spin_lock(&memtype_lock); | 371 | spin_lock(&memtype_lock); |
354 | 372 | ||
355 | if (cached_entry && start >= cached_start) | 373 | if (cached_entry && start >= cached_start) |
@@ -437,11 +455,19 @@ int free_memtype(u64 start, u64 end) | |||
437 | if (is_ISA_range(start, end - 1)) | 455 | if (is_ISA_range(start, end - 1)) |
438 | return 0; | 456 | return 0; |
439 | 457 | ||
440 | is_range_ram = pagerange_is_ram(start, end); | 458 | /* |
441 | if (is_range_ram == 1) | 459 | * For legacy reasons, some parts of the physical address range in the |
442 | return free_ram_pages_type(start, end); | 460 | * legacy 1MB region is treated as non-RAM (even when listed as RAM in |
443 | else if (is_range_ram < 0) | 461 | * the e820 tables). So we will track the memory attributes of this |
444 | return -EINVAL; | 462 | * legacy 1MB region using the linear memtype_list always. |
463 | */ | ||
464 | if (end >= ISA_END_ADDRESS) { | ||
465 | is_range_ram = pagerange_is_ram(start, end); | ||
466 | if (is_range_ram == 1) | ||
467 | return free_ram_pages_type(start, end); | ||
468 | else if (is_range_ram < 0) | ||
469 | return -EINVAL; | ||
470 | } | ||
445 | 471 | ||
446 | spin_lock(&memtype_lock); | 472 | spin_lock(&memtype_lock); |
447 | list_for_each_entry(entry, &memtype_list, nd) { | 473 | list_for_each_entry(entry, &memtype_list, nd) { |