diff options
-rw-r--r-- | arch/x86/kernel/cpu/addon_cpuid_features.c | 17 | ||||
-rw-r--r-- | arch/x86/mm/ioremap.c | 4 | ||||
-rw-r--r-- | arch/x86/mm/pageattr.c | 2 | ||||
-rw-r--r-- | arch/x86/mm/pat.c | 83 | ||||
-rw-r--r-- | arch/x86/pci/i386.c | 4 | ||||
-rw-r--r-- | include/asm-x86/pat.h | 8 |
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 |
54 | void __cpuinit validate_pat_support(struct cpuinfo_x86 *c) | 52 | void __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 | */ |
286 | void __iomem *ioremap_wc(unsigned long phys_addr, unsigned long size) | 286 | void __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 | ||
806 | int set_memory_wc(unsigned long addr, int numpages) | 806 | int 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 |
29 | int __read_mostly pat_wc_enabled = 1; | 29 | int __read_mostly pat_enabled = 1; |
30 | 30 | ||
31 | void __cpuinit pat_disable(char *reason) | 31 | void __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) | |||
42 | early_param("nopat", nopat); | 42 | early_param("nopat", nopat); |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | |||
46 | static int debug_enable; | ||
47 | static 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 | |||
45 | static u64 __read_mostly boot_pat_state; | 58 | static u64 __read_mostly boot_pat_state; |
46 | 59 | ||
47 | enum { | 60 | enum { |
@@ -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 | ||
58 | void pat_init(void) | 71 | void 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) | |||
103 | static char *cattr_name(unsigned long flags) | 117 | static 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 |
8 | extern int pat_wc_enabled; | 7 | extern int pat_enabled; |
9 | extern void validate_pat_support(struct cpuinfo_x86 *c); | 8 | extern void validate_pat_support(struct cpuinfo_x86 *c); |
10 | #else | 9 | #else |
11 | static const int pat_wc_enabled = 0; | 10 | static const int pat_enabled; |
12 | static inline void validate_pat_support(struct cpuinfo_x86 *c) { } | 11 | static 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); | |||
21 | extern void pat_disable(char *reason); | 20 | extern void pat_disable(char *reason); |
22 | 21 | ||
23 | #endif | 22 | #endif |
24 | |||