aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/cpu/addon_cpuid_features.c17
-rw-r--r--arch/x86/mm/ioremap.c4
-rw-r--r--arch/x86/mm/pageattr.c2
-rw-r--r--arch/x86/mm/pat.c83
-rw-r--r--arch/x86/pci/i386.c4
-rw-r--r--include/asm-x86/pat.h8
6 files changed, 64 insertions, 54 deletions
diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c
index c2e1ce33c7cb..84a8220a6072 100644
--- a/arch/x86/kernel/cpu/addon_cpuid_features.c
+++ b/arch/x86/kernel/cpu/addon_cpuid_features.c
@@ -1,9 +1,7 @@
1
2/* 1/*
3 * Routines to indentify additional cpu features that are scattered in 2 * Routines to indentify additional cpu features that are scattered in
4 * cpuid space. 3 * cpuid space.
5 */ 4 */
6
7#include <linux/cpu.h> 5#include <linux/cpu.h>
8 6
9#include <asm/pat.h> 7#include <asm/pat.h>
@@ -53,19 +51,20 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c)
53#ifdef CONFIG_X86_PAT 51#ifdef CONFIG_X86_PAT
54void __cpuinit validate_pat_support(struct cpuinfo_x86 *c) 52void __cpuinit validate_pat_support(struct cpuinfo_x86 *c)
55{ 53{
54 if (!cpu_has_pat)
55 pat_disable("PAT not supported by CPU.");
56
56 switch (c->x86_vendor) { 57 switch (c->x86_vendor) {
57 case X86_VENDOR_AMD:
58 if (c->x86 >= 0xf && c->x86 <= 0x11)
59 return;
60 break;
61 case X86_VENDOR_INTEL: 58 case X86_VENDOR_INTEL:
62 if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15)) 59 if (c->x86 == 0xF || (c->x86 == 6 && c->x86_model >= 15))
63 return; 60 return;
64 break; 61 break;
62 case X86_VENDOR_AMD:
63 case X86_VENDOR_CENTAUR:
64 case X86_VENDOR_TRANSMETA:
65 return;
65 } 66 }
66 67
67 pat_disable(cpu_has_pat ? 68 pat_disable("PAT disabled. Not yet verified on this CPU type.");
68 "PAT disabled. Not yet verified on this CPU type." :
69 "PAT not supported by CPU.");
70} 69}
71#endif 70#endif
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 2b2bb3f9b683..7452eb31ed12 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -261,7 +261,7 @@ void __iomem *ioremap_nocache(resource_size_t phys_addr, unsigned long size)
261{ 261{
262 /* 262 /*
263 * Ideally, this should be: 263 * Ideally, this should be:
264 * pat_wc_enabled ? _PAGE_CACHE_UC : _PAGE_CACHE_UC_MINUS; 264 * pat_enabled ? _PAGE_CACHE_UC : _PAGE_CACHE_UC_MINUS;
265 * 265 *
266 * Till we fix all X drivers to use ioremap_wc(), we will use 266 * Till we fix all X drivers to use ioremap_wc(), we will use
267 * UC MINUS. 267 * UC MINUS.
@@ -285,7 +285,7 @@ EXPORT_SYMBOL(ioremap_nocache);
285 */ 285 */
286void __iomem *ioremap_wc(unsigned long phys_addr, unsigned long size) 286void __iomem *ioremap_wc(unsigned long phys_addr, unsigned long size)
287{ 287{
288 if (pat_wc_enabled) 288 if (pat_enabled)
289 return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WC, 289 return __ioremap_caller(phys_addr, size, _PAGE_CACHE_WC,
290 __builtin_return_address(0)); 290 __builtin_return_address(0));
291 else 291 else
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 60bcb5b6a37e..6916fe4bf0cb 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -805,7 +805,7 @@ int _set_memory_wc(unsigned long addr, int numpages)
805 805
806int set_memory_wc(unsigned long addr, int numpages) 806int set_memory_wc(unsigned long addr, int numpages)
807{ 807{
808 if (!pat_wc_enabled) 808 if (!pat_enabled)
809 return set_memory_uc(addr, numpages); 809 return set_memory_uc(addr, numpages);
810 810
811 if (reserve_memtype(addr, addr + numpages * PAGE_SIZE, 811 if (reserve_memtype(addr, addr + numpages * PAGE_SIZE,
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c
index 06b7a1c90fb8..7c21572bbdda 100644
--- a/arch/x86/mm/pat.c
+++ b/arch/x86/mm/pat.c
@@ -26,11 +26,11 @@
26#include <asm/io.h> 26#include <asm/io.h>
27 27
28#ifdef CONFIG_X86_PAT 28#ifdef CONFIG_X86_PAT
29int __read_mostly pat_wc_enabled = 1; 29int __read_mostly pat_enabled = 1;
30 30
31void __cpuinit pat_disable(char *reason) 31void __cpuinit pat_disable(char *reason)
32{ 32{
33 pat_wc_enabled = 0; 33 pat_enabled = 0;
34 printk(KERN_INFO "%s\n", reason); 34 printk(KERN_INFO "%s\n", reason);
35} 35}
36 36
@@ -42,6 +42,19 @@ static int __init nopat(char *str)
42early_param("nopat", nopat); 42early_param("nopat", nopat);
43#endif 43#endif
44 44
45
46static int debug_enable;
47static int __init pat_debug_setup(char *str)
48{
49 debug_enable = 1;
50 return 0;
51}
52__setup("debugpat", pat_debug_setup);
53
54#define dprintk(fmt, arg...) \
55 do { if (debug_enable) printk(KERN_INFO fmt, ##arg); } while (0)
56
57
45static u64 __read_mostly boot_pat_state; 58static u64 __read_mostly boot_pat_state;
46 59
47enum { 60enum {
@@ -53,24 +66,25 @@ enum {
53 PAT_UC_MINUS = 7, /* UC, but can be overriden by MTRR */ 66 PAT_UC_MINUS = 7, /* UC, but can be overriden by MTRR */
54}; 67};
55 68
56#define PAT(x,y) ((u64)PAT_ ## y << ((x)*8)) 69#define PAT(x, y) ((u64)PAT_ ## y << ((x)*8))
57 70
58void pat_init(void) 71void pat_init(void)
59{ 72{
60 u64 pat; 73 u64 pat;
61 74
62 if (!pat_wc_enabled) 75 if (!pat_enabled)
63 return; 76 return;
64 77
65 /* Paranoia check. */ 78 /* Paranoia check. */
66 if (!cpu_has_pat) { 79 if (!cpu_has_pat && boot_pat_state) {
67 printk(KERN_ERR "PAT enabled, but CPU feature cleared\n");
68 /* 80 /*
69 * Panic if this happens on the secondary CPU, and we 81 * If this happens we are on a secondary CPU, but
70 * switched to PAT on the boot CPU. We have no way to 82 * switched to PAT on the boot CPU. We have no way to
71 * undo PAT. 83 * undo PAT.
72 */ 84 */
73 BUG_ON(boot_pat_state); 85 printk(KERN_ERR "PAT enabled, "
86 "but not supported by secondary CPU\n");
87 BUG();
74 } 88 }
75 89
76 /* Set PWT to Write-Combining. All other bits stay the same */ 90 /* Set PWT to Write-Combining. All other bits stay the same */
@@ -86,8 +100,8 @@ void pat_init(void)
86 * 011 UC _PAGE_CACHE_UC 100 * 011 UC _PAGE_CACHE_UC
87 * PAT bit unused 101 * PAT bit unused
88 */ 102 */
89 pat = PAT(0,WB) | PAT(1,WC) | PAT(2,UC_MINUS) | PAT(3,UC) | 103 pat = PAT(0, WB) | PAT(1, WC) | PAT(2, UC_MINUS) | PAT(3, UC) |
90 PAT(4,WB) | PAT(5,WC) | PAT(6,UC_MINUS) | PAT(7,UC); 104 PAT(4, WB) | PAT(5, WC) | PAT(6, UC_MINUS) | PAT(7, UC);
91 105
92 /* Boot CPU check */ 106 /* Boot CPU check */
93 if (!boot_pat_state) 107 if (!boot_pat_state)
@@ -103,11 +117,11 @@ void pat_init(void)
103static char *cattr_name(unsigned long flags) 117static char *cattr_name(unsigned long flags)
104{ 118{
105 switch (flags & _PAGE_CACHE_MASK) { 119 switch (flags & _PAGE_CACHE_MASK) {
106 case _PAGE_CACHE_UC: return "uncached"; 120 case _PAGE_CACHE_UC: return "uncached";
107 case _PAGE_CACHE_UC_MINUS: return "uncached-minus"; 121 case _PAGE_CACHE_UC_MINUS: return "uncached-minus";
108 case _PAGE_CACHE_WB: return "write-back"; 122 case _PAGE_CACHE_WB: return "write-back";
109 case _PAGE_CACHE_WC: return "write-combining"; 123 case _PAGE_CACHE_WC: return "write-combining";
110 default: return "broken"; 124 default: return "broken";
111 } 125 }
112} 126}
113 127
@@ -211,8 +225,8 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
211 unsigned long actual_type; 225 unsigned long actual_type;
212 int err = 0; 226 int err = 0;
213 227
214 /* Only track when pat_wc_enabled */ 228 /* Only track when pat_enabled */
215 if (!pat_wc_enabled) { 229 if (!pat_enabled) {
216 /* This is identical to page table setting without PAT */ 230 /* This is identical to page table setting without PAT */
217 if (ret_type) { 231 if (ret_type) {
218 if (req_type == -1) { 232 if (req_type == -1) {
@@ -278,7 +292,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
278 struct memtype *saved_ptr; 292 struct memtype *saved_ptr;
279 293
280 if (parse->start >= end) { 294 if (parse->start >= end) {
281 pr_debug("New Entry\n"); 295 dprintk("New Entry\n");
282 list_add(&new_entry->nd, parse->nd.prev); 296 list_add(&new_entry->nd, parse->nd.prev);
283 new_entry = NULL; 297 new_entry = NULL;
284 break; 298 break;
@@ -328,7 +342,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
328 break; 342 break;
329 } 343 }
330 344
331 pr_debug("Overlap at 0x%Lx-0x%Lx\n", 345 dprintk("Overlap at 0x%Lx-0x%Lx\n",
332 saved_ptr->start, saved_ptr->end); 346 saved_ptr->start, saved_ptr->end);
333 /* No conflict. Go ahead and add this new entry */ 347 /* No conflict. Go ahead and add this new entry */
334 list_add(&new_entry->nd, saved_ptr->nd.prev); 348 list_add(&new_entry->nd, saved_ptr->nd.prev);
@@ -380,7 +394,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
380 break; 394 break;
381 } 395 }
382 396
383 pr_debug(KERN_INFO "Overlap at 0x%Lx-0x%Lx\n", 397 dprintk("Overlap at 0x%Lx-0x%Lx\n",
384 saved_ptr->start, saved_ptr->end); 398 saved_ptr->start, saved_ptr->end);
385 /* No conflict. Go ahead and add this new entry */ 399 /* No conflict. Go ahead and add this new entry */
386 list_add(&new_entry->nd, &saved_ptr->nd); 400 list_add(&new_entry->nd, &saved_ptr->nd);
@@ -402,16 +416,16 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type,
402 if (new_entry) { 416 if (new_entry) {
403 /* No conflict. Not yet added to the list. Add to the tail */ 417 /* No conflict. Not yet added to the list. Add to the tail */
404 list_add_tail(&new_entry->nd, &memtype_list); 418 list_add_tail(&new_entry->nd, &memtype_list);
405 pr_debug("New Entry\n"); 419 dprintk("New Entry\n");
406 } 420 }
407 421
408 if (ret_type) { 422 if (ret_type) {
409 pr_debug( 423 dprintk(
410 "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n", 424 "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
411 start, end, cattr_name(actual_type), 425 start, end, cattr_name(actual_type),
412 cattr_name(req_type), cattr_name(*ret_type)); 426 cattr_name(req_type), cattr_name(*ret_type));
413 } else { 427 } else {
414 pr_debug( 428 dprintk(
415 "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s\n", 429 "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s\n",
416 start, end, cattr_name(actual_type), 430 start, end, cattr_name(actual_type),
417 cattr_name(req_type)); 431 cattr_name(req_type));
@@ -426,8 +440,8 @@ int free_memtype(u64 start, u64 end)
426 struct memtype *ml; 440 struct memtype *ml;
427 int err = -EINVAL; 441 int err = -EINVAL;
428 442
429 /* Only track when pat_wc_enabled */ 443 /* Only track when pat_enabled */
430 if (!pat_wc_enabled) { 444 if (!pat_enabled) {
431 return 0; 445 return 0;
432 } 446 }
433 447
@@ -452,7 +466,7 @@ int free_memtype(u64 start, u64 end)
452 current->comm, current->pid, start, end); 466 current->comm, current->pid, start, end);
453 } 467 }
454 468
455 pr_debug("free_memtype request 0x%Lx-0x%Lx\n", start, end); 469 dprintk("free_memtype request 0x%Lx-0x%Lx\n", start, end);
456 return err; 470 return err;
457} 471}
458 472
@@ -521,12 +535,12 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
521 * caching for the high addresses through the KEN pin, but 535 * caching for the high addresses through the KEN pin, but
522 * we maintain the tradition of paranoia in this code. 536 * we maintain the tradition of paranoia in this code.
523 */ 537 */
524 if (!pat_wc_enabled && 538 if (!pat_enabled &&
525 ! ( test_bit(X86_FEATURE_MTRR, boot_cpu_data.x86_capability) || 539 !(boot_cpu_has(X86_FEATURE_MTRR) ||
526 test_bit(X86_FEATURE_K6_MTRR, boot_cpu_data.x86_capability) || 540 boot_cpu_has(X86_FEATURE_K6_MTRR) ||
527 test_bit(X86_FEATURE_CYRIX_ARR, boot_cpu_data.x86_capability) || 541 boot_cpu_has(X86_FEATURE_CYRIX_ARR) ||
528 test_bit(X86_FEATURE_CENTAUR_MCR, boot_cpu_data.x86_capability)) && 542 boot_cpu_has(X86_FEATURE_CENTAUR_MCR)) &&
529 (pfn << PAGE_SHIFT) >= __pa(high_memory)) { 543 (pfn << PAGE_SHIFT) >= __pa(high_memory)) {
530 flags = _PAGE_CACHE_UC; 544 flags = _PAGE_CACHE_UC;
531 } 545 }
532#endif 546#endif
@@ -548,7 +562,7 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
548 return 0; 562 return 0;
549 563
550 if (pfn <= max_pfn_mapped && 564 if (pfn <= max_pfn_mapped &&
551 ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) { 565 ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) {
552 free_memtype(offset, offset + size); 566 free_memtype(offset, offset + size);
553 printk(KERN_INFO 567 printk(KERN_INFO
554 "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n", 568 "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n",
@@ -586,4 +600,3 @@ void unmap_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot)
586 600
587 free_memtype(addr, addr + size); 601 free_memtype(addr, addr + size);
588} 602}
589
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 10fb308fded8..6ccd7a108cd4 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -299,9 +299,9 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
299 return -EINVAL; 299 return -EINVAL;
300 300
301 prot = pgprot_val(vma->vm_page_prot); 301 prot = pgprot_val(vma->vm_page_prot);
302 if (pat_wc_enabled && write_combine) 302 if (pat_enabled && write_combine)
303 prot |= _PAGE_CACHE_WC; 303 prot |= _PAGE_CACHE_WC;
304 else if (pat_wc_enabled || boot_cpu_data.x86 > 3) 304 else if (pat_enabled || boot_cpu_data.x86 > 3)
305 /* 305 /*
306 * ioremap() and ioremap_nocache() defaults to UC MINUS for now. 306 * ioremap() and ioremap_nocache() defaults to UC MINUS for now.
307 * To avoid attribute conflicts, request UC MINUS here 307 * To avoid attribute conflicts, request UC MINUS here
diff --git a/include/asm-x86/pat.h b/include/asm-x86/pat.h
index 88f60cc6a227..7edc47307217 100644
--- a/include/asm-x86/pat.h
+++ b/include/asm-x86/pat.h
@@ -1,14 +1,13 @@
1
2#ifndef _ASM_PAT_H 1#ifndef _ASM_PAT_H
3#define _ASM_PAT_H 1 2#define _ASM_PAT_H
4 3
5#include <linux/types.h> 4#include <linux/types.h>
6 5
7#ifdef CONFIG_X86_PAT 6#ifdef CONFIG_X86_PAT
8extern int pat_wc_enabled; 7extern int pat_enabled;
9extern void validate_pat_support(struct cpuinfo_x86 *c); 8extern void validate_pat_support(struct cpuinfo_x86 *c);
10#else 9#else
11static const int pat_wc_enabled = 0; 10static const int pat_enabled;
12static inline void validate_pat_support(struct cpuinfo_x86 *c) { } 11static inline void validate_pat_support(struct cpuinfo_x86 *c) { }
13#endif 12#endif
14 13
@@ -21,4 +20,3 @@ extern int free_memtype(u64 start, u64 end);
21extern void pat_disable(char *reason); 20extern void pat_disable(char *reason);
22 21
23#endif 22#endif
24