diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-03-30 17:53:32 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-30 17:53:32 -0400 |
commit | 65fb0d23fcddd8697c871047b700c78817bdaa43 (patch) | |
tree | 119e6e5f276622c4c862f6c9b6d795264ba1603a /arch/x86/mm | |
parent | 8c083f081d0014057901c68a0a3e0f8ca7ac8d23 (diff) | |
parent | dfbbe89e197a77f2c8046a51c74e33e35f878080 (diff) |
Merge branch 'linus' into cpumask-for-linus
Conflicts:
arch/x86/kernel/cpu/common.c
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/highmem_32.c | 15 | ||||
-rw-r--r-- | arch/x86/mm/init.c | 6 | ||||
-rw-r--r-- | arch/x86/mm/iomap_32.c | 26 | ||||
-rw-r--r-- | arch/x86/mm/ioremap.c | 19 | ||||
-rw-r--r-- | arch/x86/mm/kmmio.c | 2 | ||||
-rw-r--r-- | arch/x86/mm/pageattr.c | 147 | ||||
-rw-r--r-- | arch/x86/mm/pat.c | 5 | ||||
-rw-r--r-- | arch/x86/mm/pgtable_32.c | 2 | ||||
-rw-r--r-- | arch/x86/mm/tlb.c | 5 |
9 files changed, 152 insertions, 75 deletions
diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c index d11745334a67..522db5e3d0bf 100644 --- a/arch/x86/mm/highmem_32.c +++ b/arch/x86/mm/highmem_32.c | |||
@@ -121,22 +121,13 @@ void kunmap_atomic(void *kvaddr, enum km_type type) | |||
121 | pagefault_enable(); | 121 | pagefault_enable(); |
122 | } | 122 | } |
123 | 123 | ||
124 | /* This is the same as kmap_atomic() but can map memory that doesn't | 124 | /* |
125 | * This is the same as kmap_atomic() but can map memory that doesn't | ||
125 | * have a struct page associated with it. | 126 | * have a struct page associated with it. |
126 | */ | 127 | */ |
127 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) | 128 | void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) |
128 | { | 129 | { |
129 | enum fixed_addresses idx; | 130 | return kmap_atomic_prot_pfn(pfn, type, kmap_prot); |
130 | unsigned long vaddr; | ||
131 | |||
132 | pagefault_disable(); | ||
133 | |||
134 | idx = type + KM_TYPE_NR*smp_processor_id(); | ||
135 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | ||
136 | set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot)); | ||
137 | arch_flush_lazy_mmu_mode(); | ||
138 | |||
139 | return (void*) vaddr; | ||
140 | } | 131 | } |
141 | EXPORT_SYMBOL_GPL(kmap_atomic_pfn); /* temporarily in use by i915 GEM until vmap */ | 132 | EXPORT_SYMBOL_GPL(kmap_atomic_pfn); /* temporarily in use by i915 GEM until vmap */ |
142 | 133 | ||
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 15219e0d1243..fd3da1dda1c9 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
@@ -94,9 +94,9 @@ struct map_range { | |||
94 | #define NR_RANGE_MR 5 | 94 | #define NR_RANGE_MR 5 |
95 | #endif | 95 | #endif |
96 | 96 | ||
97 | static int save_mr(struct map_range *mr, int nr_range, | 97 | static int __meminit save_mr(struct map_range *mr, int nr_range, |
98 | unsigned long start_pfn, unsigned long end_pfn, | 98 | unsigned long start_pfn, unsigned long end_pfn, |
99 | unsigned long page_size_mask) | 99 | unsigned long page_size_mask) |
100 | { | 100 | { |
101 | if (start_pfn < end_pfn) { | 101 | if (start_pfn < end_pfn) { |
102 | if (nr_range >= NR_RANGE_MR) | 102 | if (nr_range >= NR_RANGE_MR) |
diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c index 04102d42ff42..699c9b2895ae 100644 --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c | |||
@@ -31,16 +31,27 @@ int is_io_mapping_possible(resource_size_t base, unsigned long size) | |||
31 | } | 31 | } |
32 | EXPORT_SYMBOL_GPL(is_io_mapping_possible); | 32 | EXPORT_SYMBOL_GPL(is_io_mapping_possible); |
33 | 33 | ||
34 | /* Map 'pfn' using fixed map 'type' and protections 'prot' | 34 | void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) |
35 | */ | ||
36 | void * | ||
37 | iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) | ||
38 | { | 35 | { |
39 | enum fixed_addresses idx; | 36 | enum fixed_addresses idx; |
40 | unsigned long vaddr; | 37 | unsigned long vaddr; |
41 | 38 | ||
42 | pagefault_disable(); | 39 | pagefault_disable(); |
43 | 40 | ||
41 | idx = type + KM_TYPE_NR * smp_processor_id(); | ||
42 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | ||
43 | set_pte(kmap_pte - idx, pfn_pte(pfn, prot)); | ||
44 | arch_flush_lazy_mmu_mode(); | ||
45 | |||
46 | return (void *)vaddr; | ||
47 | } | ||
48 | |||
49 | /* | ||
50 | * Map 'pfn' using fixed map 'type' and protections 'prot' | ||
51 | */ | ||
52 | void * | ||
53 | iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) | ||
54 | { | ||
44 | /* | 55 | /* |
45 | * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS. | 56 | * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS. |
46 | * PAGE_KERNEL_WC maps to PWT, which translates to uncached if the | 57 | * PAGE_KERNEL_WC maps to PWT, which translates to uncached if the |
@@ -50,12 +61,7 @@ iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot) | |||
50 | if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC)) | 61 | if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC)) |
51 | prot = PAGE_KERNEL_UC_MINUS; | 62 | prot = PAGE_KERNEL_UC_MINUS; |
52 | 63 | ||
53 | idx = type + KM_TYPE_NR*smp_processor_id(); | 64 | return kmap_atomic_prot_pfn(pfn, type, prot); |
54 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | ||
55 | set_pte(kmap_pte-idx, pfn_pte(pfn, prot)); | ||
56 | arch_flush_lazy_mmu_mode(); | ||
57 | |||
58 | return (void*) vaddr; | ||
59 | } | 65 | } |
60 | EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn); | 66 | EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn); |
61 | 67 | ||
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index aca924a30ee6..0dfa09d69e80 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c | |||
@@ -22,13 +22,17 @@ | |||
22 | #include <asm/pgalloc.h> | 22 | #include <asm/pgalloc.h> |
23 | #include <asm/pat.h> | 23 | #include <asm/pat.h> |
24 | 24 | ||
25 | #ifdef CONFIG_X86_64 | 25 | static inline int phys_addr_valid(resource_size_t addr) |
26 | |||
27 | static inline int phys_addr_valid(unsigned long addr) | ||
28 | { | 26 | { |
29 | return addr < (1UL << boot_cpu_data.x86_phys_bits); | 27 | #ifdef CONFIG_PHYS_ADDR_T_64BIT |
28 | return !(addr >> boot_cpu_data.x86_phys_bits); | ||
29 | #else | ||
30 | return 1; | ||
31 | #endif | ||
30 | } | 32 | } |
31 | 33 | ||
34 | #ifdef CONFIG_X86_64 | ||
35 | |||
32 | unsigned long __phys_addr(unsigned long x) | 36 | unsigned long __phys_addr(unsigned long x) |
33 | { | 37 | { |
34 | if (x >= __START_KERNEL_map) { | 38 | if (x >= __START_KERNEL_map) { |
@@ -65,11 +69,6 @@ EXPORT_SYMBOL(__virt_addr_valid); | |||
65 | 69 | ||
66 | #else | 70 | #else |
67 | 71 | ||
68 | static inline int phys_addr_valid(unsigned long addr) | ||
69 | { | ||
70 | return 1; | ||
71 | } | ||
72 | |||
73 | #ifdef CONFIG_DEBUG_VIRTUAL | 72 | #ifdef CONFIG_DEBUG_VIRTUAL |
74 | unsigned long __phys_addr(unsigned long x) | 73 | unsigned long __phys_addr(unsigned long x) |
75 | { | 74 | { |
@@ -517,7 +516,7 @@ void __init early_ioremap_init(void) | |||
517 | printk(KERN_INFO "early_ioremap_init()\n"); | 516 | printk(KERN_INFO "early_ioremap_init()\n"); |
518 | 517 | ||
519 | for (i = 0; i < FIX_BTMAPS_SLOTS; i++) | 518 | for (i = 0; i < FIX_BTMAPS_SLOTS; i++) |
520 | slot_virt[i] = fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i); | 519 | slot_virt[i] = __fix_to_virt(FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*i); |
521 | 520 | ||
522 | pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)); | 521 | pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)); |
523 | memset(bm_pte, 0, sizeof(bm_pte)); | 522 | memset(bm_pte, 0, sizeof(bm_pte)); |
diff --git a/arch/x86/mm/kmmio.c b/arch/x86/mm/kmmio.c index 6a518dd08a36..4f115e00486b 100644 --- a/arch/x86/mm/kmmio.c +++ b/arch/x86/mm/kmmio.c | |||
@@ -310,7 +310,7 @@ static int post_kmmio_handler(unsigned long condition, struct pt_regs *regs) | |||
310 | struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx); | 310 | struct kmmio_context *ctx = &get_cpu_var(kmmio_ctx); |
311 | 311 | ||
312 | if (!ctx->active) { | 312 | if (!ctx->active) { |
313 | pr_warning("kmmio: spurious debug trap on CPU %d.\n", | 313 | pr_debug("kmmio: spurious debug trap on CPU %d.\n", |
314 | smp_processor_id()); | 314 | smp_processor_id()); |
315 | goto out; | 315 | goto out; |
316 | } | 316 | } |
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 9c4294986af7..d71e1b636ce6 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <asm/processor.h> | 16 | #include <asm/processor.h> |
17 | #include <asm/tlbflush.h> | 17 | #include <asm/tlbflush.h> |
18 | #include <asm/sections.h> | 18 | #include <asm/sections.h> |
19 | #include <asm/setup.h> | ||
19 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
20 | #include <asm/pgalloc.h> | 21 | #include <asm/pgalloc.h> |
21 | #include <asm/proto.h> | 22 | #include <asm/proto.h> |
@@ -33,6 +34,7 @@ struct cpa_data { | |||
33 | unsigned long pfn; | 34 | unsigned long pfn; |
34 | unsigned force_split : 1; | 35 | unsigned force_split : 1; |
35 | int curpage; | 36 | int curpage; |
37 | struct page **pages; | ||
36 | }; | 38 | }; |
37 | 39 | ||
38 | /* | 40 | /* |
@@ -45,6 +47,7 @@ static DEFINE_SPINLOCK(cpa_lock); | |||
45 | 47 | ||
46 | #define CPA_FLUSHTLB 1 | 48 | #define CPA_FLUSHTLB 1 |
47 | #define CPA_ARRAY 2 | 49 | #define CPA_ARRAY 2 |
50 | #define CPA_PAGES_ARRAY 4 | ||
48 | 51 | ||
49 | #ifdef CONFIG_PROC_FS | 52 | #ifdef CONFIG_PROC_FS |
50 | static unsigned long direct_pages_count[PG_LEVEL_NUM]; | 53 | static unsigned long direct_pages_count[PG_LEVEL_NUM]; |
@@ -95,7 +98,7 @@ static inline unsigned long highmap_start_pfn(void) | |||
95 | 98 | ||
96 | static inline unsigned long highmap_end_pfn(void) | 99 | static inline unsigned long highmap_end_pfn(void) |
97 | { | 100 | { |
98 | return __pa(roundup((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT; | 101 | return __pa(roundup(_brk_end, PMD_SIZE)) >> PAGE_SHIFT; |
99 | } | 102 | } |
100 | 103 | ||
101 | #endif | 104 | #endif |
@@ -201,10 +204,10 @@ static void cpa_flush_range(unsigned long start, int numpages, int cache) | |||
201 | } | 204 | } |
202 | } | 205 | } |
203 | 206 | ||
204 | static void cpa_flush_array(unsigned long *start, int numpages, int cache) | 207 | static void cpa_flush_array(unsigned long *start, int numpages, int cache, |
208 | int in_flags, struct page **pages) | ||
205 | { | 209 | { |
206 | unsigned int i, level; | 210 | unsigned int i, level; |
207 | unsigned long *addr; | ||
208 | 211 | ||
209 | BUG_ON(irqs_disabled()); | 212 | BUG_ON(irqs_disabled()); |
210 | 213 | ||
@@ -225,14 +228,22 @@ static void cpa_flush_array(unsigned long *start, int numpages, int cache) | |||
225 | * will cause all other CPUs to flush the same | 228 | * will cause all other CPUs to flush the same |
226 | * cachelines: | 229 | * cachelines: |
227 | */ | 230 | */ |
228 | for (i = 0, addr = start; i < numpages; i++, addr++) { | 231 | for (i = 0; i < numpages; i++) { |
229 | pte_t *pte = lookup_address(*addr, &level); | 232 | unsigned long addr; |
233 | pte_t *pte; | ||
234 | |||
235 | if (in_flags & CPA_PAGES_ARRAY) | ||
236 | addr = (unsigned long)page_address(pages[i]); | ||
237 | else | ||
238 | addr = start[i]; | ||
239 | |||
240 | pte = lookup_address(addr, &level); | ||
230 | 241 | ||
231 | /* | 242 | /* |
232 | * Only flush present addresses: | 243 | * Only flush present addresses: |
233 | */ | 244 | */ |
234 | if (pte && (pte_val(*pte) & _PAGE_PRESENT)) | 245 | if (pte && (pte_val(*pte) & _PAGE_PRESENT)) |
235 | clflush_cache_range((void *) *addr, PAGE_SIZE); | 246 | clflush_cache_range((void *)addr, PAGE_SIZE); |
236 | } | 247 | } |
237 | } | 248 | } |
238 | 249 | ||
@@ -584,7 +595,9 @@ static int __change_page_attr(struct cpa_data *cpa, int primary) | |||
584 | unsigned int level; | 595 | unsigned int level; |
585 | pte_t *kpte, old_pte; | 596 | pte_t *kpte, old_pte; |
586 | 597 | ||
587 | if (cpa->flags & CPA_ARRAY) | 598 | if (cpa->flags & CPA_PAGES_ARRAY) |
599 | address = (unsigned long)page_address(cpa->pages[cpa->curpage]); | ||
600 | else if (cpa->flags & CPA_ARRAY) | ||
588 | address = cpa->vaddr[cpa->curpage]; | 601 | address = cpa->vaddr[cpa->curpage]; |
589 | else | 602 | else |
590 | address = *cpa->vaddr; | 603 | address = *cpa->vaddr; |
@@ -687,7 +700,9 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
687 | * No need to redo, when the primary call touched the direct | 700 | * No need to redo, when the primary call touched the direct |
688 | * mapping already: | 701 | * mapping already: |
689 | */ | 702 | */ |
690 | if (cpa->flags & CPA_ARRAY) | 703 | if (cpa->flags & CPA_PAGES_ARRAY) |
704 | vaddr = (unsigned long)page_address(cpa->pages[cpa->curpage]); | ||
705 | else if (cpa->flags & CPA_ARRAY) | ||
691 | vaddr = cpa->vaddr[cpa->curpage]; | 706 | vaddr = cpa->vaddr[cpa->curpage]; |
692 | else | 707 | else |
693 | vaddr = *cpa->vaddr; | 708 | vaddr = *cpa->vaddr; |
@@ -698,7 +713,7 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
698 | alias_cpa = *cpa; | 713 | alias_cpa = *cpa; |
699 | temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); | 714 | temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); |
700 | alias_cpa.vaddr = &temp_cpa_vaddr; | 715 | alias_cpa.vaddr = &temp_cpa_vaddr; |
701 | alias_cpa.flags &= ~CPA_ARRAY; | 716 | alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); |
702 | 717 | ||
703 | 718 | ||
704 | ret = __change_page_attr_set_clr(&alias_cpa, 0); | 719 | ret = __change_page_attr_set_clr(&alias_cpa, 0); |
@@ -711,7 +726,7 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
711 | * No need to redo, when the primary call touched the high | 726 | * No need to redo, when the primary call touched the high |
712 | * mapping already: | 727 | * mapping already: |
713 | */ | 728 | */ |
714 | if (within(vaddr, (unsigned long) _text, (unsigned long) _end)) | 729 | if (within(vaddr, (unsigned long) _text, _brk_end)) |
715 | return 0; | 730 | return 0; |
716 | 731 | ||
717 | /* | 732 | /* |
@@ -724,7 +739,7 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
724 | alias_cpa = *cpa; | 739 | alias_cpa = *cpa; |
725 | temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base; | 740 | temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base; |
726 | alias_cpa.vaddr = &temp_cpa_vaddr; | 741 | alias_cpa.vaddr = &temp_cpa_vaddr; |
727 | alias_cpa.flags &= ~CPA_ARRAY; | 742 | alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); |
728 | 743 | ||
729 | /* | 744 | /* |
730 | * The high mapping range is imprecise, so ignore the return value. | 745 | * The high mapping range is imprecise, so ignore the return value. |
@@ -745,7 +760,7 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) | |||
745 | */ | 760 | */ |
746 | cpa->numpages = numpages; | 761 | cpa->numpages = numpages; |
747 | /* for array changes, we can't use large page */ | 762 | /* for array changes, we can't use large page */ |
748 | if (cpa->flags & CPA_ARRAY) | 763 | if (cpa->flags & (CPA_ARRAY | CPA_PAGES_ARRAY)) |
749 | cpa->numpages = 1; | 764 | cpa->numpages = 1; |
750 | 765 | ||
751 | if (!debug_pagealloc) | 766 | if (!debug_pagealloc) |
@@ -769,7 +784,7 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) | |||
769 | */ | 784 | */ |
770 | BUG_ON(cpa->numpages > numpages); | 785 | BUG_ON(cpa->numpages > numpages); |
771 | numpages -= cpa->numpages; | 786 | numpages -= cpa->numpages; |
772 | if (cpa->flags & CPA_ARRAY) | 787 | if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) |
773 | cpa->curpage++; | 788 | cpa->curpage++; |
774 | else | 789 | else |
775 | *cpa->vaddr += cpa->numpages * PAGE_SIZE; | 790 | *cpa->vaddr += cpa->numpages * PAGE_SIZE; |
@@ -786,7 +801,8 @@ static inline int cache_attr(pgprot_t attr) | |||
786 | 801 | ||
787 | static int change_page_attr_set_clr(unsigned long *addr, int numpages, | 802 | static int change_page_attr_set_clr(unsigned long *addr, int numpages, |
788 | pgprot_t mask_set, pgprot_t mask_clr, | 803 | pgprot_t mask_set, pgprot_t mask_clr, |
789 | int force_split, int array) | 804 | int force_split, int in_flag, |
805 | struct page **pages) | ||
790 | { | 806 | { |
791 | struct cpa_data cpa; | 807 | struct cpa_data cpa; |
792 | int ret, cache, checkalias; | 808 | int ret, cache, checkalias; |
@@ -801,15 +817,7 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, | |||
801 | return 0; | 817 | return 0; |
802 | 818 | ||
803 | /* Ensure we are PAGE_SIZE aligned */ | 819 | /* Ensure we are PAGE_SIZE aligned */ |
804 | if (!array) { | 820 | if (in_flag & CPA_ARRAY) { |
805 | if (*addr & ~PAGE_MASK) { | ||
806 | *addr &= PAGE_MASK; | ||
807 | /* | ||
808 | * People should not be passing in unaligned addresses: | ||
809 | */ | ||
810 | WARN_ON_ONCE(1); | ||
811 | } | ||
812 | } else { | ||
813 | int i; | 821 | int i; |
814 | for (i = 0; i < numpages; i++) { | 822 | for (i = 0; i < numpages; i++) { |
815 | if (addr[i] & ~PAGE_MASK) { | 823 | if (addr[i] & ~PAGE_MASK) { |
@@ -817,6 +825,18 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, | |||
817 | WARN_ON_ONCE(1); | 825 | WARN_ON_ONCE(1); |
818 | } | 826 | } |
819 | } | 827 | } |
828 | } else if (!(in_flag & CPA_PAGES_ARRAY)) { | ||
829 | /* | ||
830 | * in_flag of CPA_PAGES_ARRAY implies it is aligned. | ||
831 | * No need to cehck in that case | ||
832 | */ | ||
833 | if (*addr & ~PAGE_MASK) { | ||
834 | *addr &= PAGE_MASK; | ||
835 | /* | ||
836 | * People should not be passing in unaligned addresses: | ||
837 | */ | ||
838 | WARN_ON_ONCE(1); | ||
839 | } | ||
820 | } | 840 | } |
821 | 841 | ||
822 | /* Must avoid aliasing mappings in the highmem code */ | 842 | /* Must avoid aliasing mappings in the highmem code */ |
@@ -832,6 +852,7 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, | |||
832 | arch_flush_lazy_mmu_mode(); | 852 | arch_flush_lazy_mmu_mode(); |
833 | 853 | ||
834 | cpa.vaddr = addr; | 854 | cpa.vaddr = addr; |
855 | cpa.pages = pages; | ||
835 | cpa.numpages = numpages; | 856 | cpa.numpages = numpages; |
836 | cpa.mask_set = mask_set; | 857 | cpa.mask_set = mask_set; |
837 | cpa.mask_clr = mask_clr; | 858 | cpa.mask_clr = mask_clr; |
@@ -839,8 +860,8 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, | |||
839 | cpa.curpage = 0; | 860 | cpa.curpage = 0; |
840 | cpa.force_split = force_split; | 861 | cpa.force_split = force_split; |
841 | 862 | ||
842 | if (array) | 863 | if (in_flag & (CPA_ARRAY | CPA_PAGES_ARRAY)) |
843 | cpa.flags |= CPA_ARRAY; | 864 | cpa.flags |= in_flag; |
844 | 865 | ||
845 | /* No alias checking for _NX bit modifications */ | 866 | /* No alias checking for _NX bit modifications */ |
846 | checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX; | 867 | checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX; |
@@ -866,9 +887,10 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages, | |||
866 | * wbindv): | 887 | * wbindv): |
867 | */ | 888 | */ |
868 | if (!ret && cpu_has_clflush) { | 889 | if (!ret && cpu_has_clflush) { |
869 | if (cpa.flags & CPA_ARRAY) | 890 | if (cpa.flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) { |
870 | cpa_flush_array(addr, numpages, cache); | 891 | cpa_flush_array(addr, numpages, cache, |
871 | else | 892 | cpa.flags, pages); |
893 | } else | ||
872 | cpa_flush_range(*addr, numpages, cache); | 894 | cpa_flush_range(*addr, numpages, cache); |
873 | } else | 895 | } else |
874 | cpa_flush_all(cache); | 896 | cpa_flush_all(cache); |
@@ -888,14 +910,28 @@ static inline int change_page_attr_set(unsigned long *addr, int numpages, | |||
888 | pgprot_t mask, int array) | 910 | pgprot_t mask, int array) |
889 | { | 911 | { |
890 | return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0, | 912 | return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0), 0, |
891 | array); | 913 | (array ? CPA_ARRAY : 0), NULL); |
892 | } | 914 | } |
893 | 915 | ||
894 | static inline int change_page_attr_clear(unsigned long *addr, int numpages, | 916 | static inline int change_page_attr_clear(unsigned long *addr, int numpages, |
895 | pgprot_t mask, int array) | 917 | pgprot_t mask, int array) |
896 | { | 918 | { |
897 | return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0, | 919 | return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask, 0, |
898 | array); | 920 | (array ? CPA_ARRAY : 0), NULL); |
921 | } | ||
922 | |||
923 | static inline int cpa_set_pages_array(struct page **pages, int numpages, | ||
924 | pgprot_t mask) | ||
925 | { | ||
926 | return change_page_attr_set_clr(NULL, numpages, mask, __pgprot(0), 0, | ||
927 | CPA_PAGES_ARRAY, pages); | ||
928 | } | ||
929 | |||
930 | static inline int cpa_clear_pages_array(struct page **pages, int numpages, | ||
931 | pgprot_t mask) | ||
932 | { | ||
933 | return change_page_attr_set_clr(NULL, numpages, __pgprot(0), mask, 0, | ||
934 | CPA_PAGES_ARRAY, pages); | ||
899 | } | 935 | } |
900 | 936 | ||
901 | int _set_memory_uc(unsigned long addr, int numpages) | 937 | int _set_memory_uc(unsigned long addr, int numpages) |
@@ -1043,7 +1079,7 @@ int set_memory_np(unsigned long addr, int numpages) | |||
1043 | int set_memory_4k(unsigned long addr, int numpages) | 1079 | int set_memory_4k(unsigned long addr, int numpages) |
1044 | { | 1080 | { |
1045 | return change_page_attr_set_clr(&addr, numpages, __pgprot(0), | 1081 | return change_page_attr_set_clr(&addr, numpages, __pgprot(0), |
1046 | __pgprot(0), 1, 0); | 1082 | __pgprot(0), 1, 0, NULL); |
1047 | } | 1083 | } |
1048 | 1084 | ||
1049 | int set_pages_uc(struct page *page, int numpages) | 1085 | int set_pages_uc(struct page *page, int numpages) |
@@ -1054,6 +1090,35 @@ int set_pages_uc(struct page *page, int numpages) | |||
1054 | } | 1090 | } |
1055 | EXPORT_SYMBOL(set_pages_uc); | 1091 | EXPORT_SYMBOL(set_pages_uc); |
1056 | 1092 | ||
1093 | int set_pages_array_uc(struct page **pages, int addrinarray) | ||
1094 | { | ||
1095 | unsigned long start; | ||
1096 | unsigned long end; | ||
1097 | int i; | ||
1098 | int free_idx; | ||
1099 | |||
1100 | for (i = 0; i < addrinarray; i++) { | ||
1101 | start = (unsigned long)page_address(pages[i]); | ||
1102 | end = start + PAGE_SIZE; | ||
1103 | if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL)) | ||
1104 | goto err_out; | ||
1105 | } | ||
1106 | |||
1107 | if (cpa_set_pages_array(pages, addrinarray, | ||
1108 | __pgprot(_PAGE_CACHE_UC_MINUS)) == 0) { | ||
1109 | return 0; /* Success */ | ||
1110 | } | ||
1111 | err_out: | ||
1112 | free_idx = i; | ||
1113 | for (i = 0; i < free_idx; i++) { | ||
1114 | start = (unsigned long)page_address(pages[i]); | ||
1115 | end = start + PAGE_SIZE; | ||
1116 | free_memtype(start, end); | ||
1117 | } | ||
1118 | return -EINVAL; | ||
1119 | } | ||
1120 | EXPORT_SYMBOL(set_pages_array_uc); | ||
1121 | |||
1057 | int set_pages_wb(struct page *page, int numpages) | 1122 | int set_pages_wb(struct page *page, int numpages) |
1058 | { | 1123 | { |
1059 | unsigned long addr = (unsigned long)page_address(page); | 1124 | unsigned long addr = (unsigned long)page_address(page); |
@@ -1062,6 +1127,26 @@ int set_pages_wb(struct page *page, int numpages) | |||
1062 | } | 1127 | } |
1063 | EXPORT_SYMBOL(set_pages_wb); | 1128 | EXPORT_SYMBOL(set_pages_wb); |
1064 | 1129 | ||
1130 | int set_pages_array_wb(struct page **pages, int addrinarray) | ||
1131 | { | ||
1132 | int retval; | ||
1133 | unsigned long start; | ||
1134 | unsigned long end; | ||
1135 | int i; | ||
1136 | |||
1137 | retval = cpa_clear_pages_array(pages, addrinarray, | ||
1138 | __pgprot(_PAGE_CACHE_MASK)); | ||
1139 | |||
1140 | for (i = 0; i < addrinarray; i++) { | ||
1141 | start = (unsigned long)page_address(pages[i]); | ||
1142 | end = start + PAGE_SIZE; | ||
1143 | free_memtype(start, end); | ||
1144 | } | ||
1145 | |||
1146 | return retval; | ||
1147 | } | ||
1148 | EXPORT_SYMBOL(set_pages_array_wb); | ||
1149 | |||
1065 | int set_pages_x(struct page *page, int numpages) | 1150 | int set_pages_x(struct page *page, int numpages) |
1066 | { | 1151 | { |
1067 | unsigned long addr = (unsigned long)page_address(page); | 1152 | unsigned long addr = (unsigned long)page_address(page); |
diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 2ed37158012d..640339ee4fb2 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c | |||
@@ -677,10 +677,11 @@ static int reserve_pfn_range(u64 paddr, unsigned long size, pgprot_t *vma_prot, | |||
677 | is_ram = pat_pagerange_is_ram(paddr, paddr + size); | 677 | is_ram = pat_pagerange_is_ram(paddr, paddr + size); |
678 | 678 | ||
679 | /* | 679 | /* |
680 | * reserve_pfn_range() doesn't support RAM pages. | 680 | * reserve_pfn_range() doesn't support RAM pages. Maintain the current |
681 | * behavior with RAM pages by returning success. | ||
681 | */ | 682 | */ |
682 | if (is_ram != 0) | 683 | if (is_ram != 0) |
683 | return -EINVAL; | 684 | return 0; |
684 | 685 | ||
685 | ret = reserve_memtype(paddr, paddr + size, want_flags, &flags); | 686 | ret = reserve_memtype(paddr, paddr + size, want_flags, &flags); |
686 | if (ret) | 687 | if (ret) |
diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c index f2e477c91c1b..46c8834aedc0 100644 --- a/arch/x86/mm/pgtable_32.c +++ b/arch/x86/mm/pgtable_32.c | |||
@@ -50,7 +50,7 @@ void set_pte_vaddr(unsigned long vaddr, pte_t pteval) | |||
50 | } | 50 | } |
51 | pte = pte_offset_kernel(pmd, vaddr); | 51 | pte = pte_offset_kernel(pmd, vaddr); |
52 | if (pte_val(pteval)) | 52 | if (pte_val(pteval)) |
53 | set_pte_present(&init_mm, vaddr, pte, pteval); | 53 | set_pte_at(&init_mm, vaddr, pte, pteval); |
54 | else | 54 | else |
55 | pte_clear(&init_mm, vaddr, pte); | 55 | pte_clear(&init_mm, vaddr, pte); |
56 | 56 | ||
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index a654d59e4483..821e97017e95 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c | |||
@@ -187,11 +187,6 @@ static void flush_tlb_others_ipi(const struct cpumask *cpumask, | |||
187 | cpumask, cpumask_of(smp_processor_id())); | 187 | cpumask, cpumask_of(smp_processor_id())); |
188 | 188 | ||
189 | /* | 189 | /* |
190 | * Make the above memory operations globally visible before | ||
191 | * sending the IPI. | ||
192 | */ | ||
193 | smp_mb(); | ||
194 | /* | ||
195 | * We have to send the IPI only to | 190 | * We have to send the IPI only to |
196 | * CPUs affected. | 191 | * CPUs affected. |
197 | */ | 192 | */ |