aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-11 20:34:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-11 20:34:00 -0400
commitfd9879b9bb3258ebc27a4cc6d2d29f528f71901f (patch)
tree48b68994f5e8083aafe116533e8143cb2bf30c85 /arch/powerpc/mm
parent81ae31d78239318610d7c2acb3e2610d622a5aa4 (diff)
parentd53ba6b3bba33432cc37b7101a86f8f3392c46e7 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux
Pull powerpc updates from Michael Ellerman: "Here's a first pull request for powerpc updates for 3.18. The bulk of the additions are for the "cxl" driver, for IBM's Coherent Accelerator Processor Interface (CAPI). Most of it's in drivers/misc, which Greg & Arnd maintain, Greg said he was happy for us to take it through our tree. There's the usual minor cleanups and fixes, including a bit of noise in drivers from some of those. A bunch of updates to our EEH code, which has been getting more testing. Several nice speedups from Anton, including 20% in clear_page(). And a bunch of updates for freescale from Scott" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mpe/linux: (130 commits) cxl: Fix afu_read() not doing finish_wait() on signal or non-blocking cxl: Add documentation for userspace APIs cxl: Add driver to Kbuild and Makefiles cxl: Add userspace header file cxl: Driver code for powernv PCIe based cards for userspace access cxl: Add base builtin support powerpc/mm: Add hooks for cxl powerpc/opal: Add PHB to cxl mode call powerpc/mm: Add new hash_page_mm() powerpc/powerpc: Add new PCIe functions for allocating cxl interrupts cxl: Add new header for call backs and structs powerpc/powernv: Split out set MSI IRQ chip code powerpc/mm: Export mmu_kernel_ssize and mmu_linear_psize powerpc/msi: Improve IRQ bitmap allocator powerpc/cell: Make spu_flush_all_slbs() generic powerpc/cell: Move data segment faulting code out of cell platform powerpc/cell: Move spu_handle_mm_fault() out of cell platform powerpc/pseries: Use new defines when calling H_SET_MODE powerpc: Update contact info in Documentation files powerpc/perf/hv-24x7: Simplify catalog_read() ...
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r--arch/powerpc/mm/Makefile1
-rw-r--r--arch/powerpc/mm/copro_fault.c149
-rw-r--r--arch/powerpc/mm/fault.c43
-rw-r--r--arch/powerpc/mm/hash_native_64.c6
-rw-r--r--arch/powerpc/mm/hash_utils_64.c160
-rw-r--r--arch/powerpc/mm/init_32.c4
-rw-r--r--arch/powerpc/mm/init_64.c3
-rw-r--r--arch/powerpc/mm/mem.c68
-rw-r--r--arch/powerpc/mm/numa.c27
-rw-r--r--arch/powerpc/mm/pgtable.c2
-rw-r--r--arch/powerpc/mm/slb.c3
-rw-r--r--arch/powerpc/mm/slice.c12
12 files changed, 347 insertions, 131 deletions
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index d0130fff20e5..325e861616a1 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -34,3 +34,4 @@ obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += hugepage-hash64.o
34obj-$(CONFIG_PPC_SUBPAGE_PROT) += subpage-prot.o 34obj-$(CONFIG_PPC_SUBPAGE_PROT) += subpage-prot.o
35obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o 35obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o
36obj-$(CONFIG_HIGHMEM) += highmem.o 36obj-$(CONFIG_HIGHMEM) += highmem.o
37obj-$(CONFIG_PPC_COPRO_BASE) += copro_fault.o
diff --git a/arch/powerpc/mm/copro_fault.c b/arch/powerpc/mm/copro_fault.c
new file mode 100644
index 000000000000..0f9939e693df
--- /dev/null
+++ b/arch/powerpc/mm/copro_fault.c
@@ -0,0 +1,149 @@
1/*
2 * CoProcessor (SPU/AFU) mm fault handler
3 *
4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2007
5 *
6 * Author: Arnd Bergmann <arndb@de.ibm.com>
7 * Author: Jeremy Kerr <jk@ozlabs.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23#include <linux/sched.h>
24#include <linux/mm.h>
25#include <linux/export.h>
26#include <asm/reg.h>
27#include <asm/copro.h>
28#include <asm/spu.h>
29#include <misc/cxl.h>
30
31/*
32 * This ought to be kept in sync with the powerpc specific do_page_fault
33 * function. Currently, there are a few corner cases that we haven't had
34 * to handle fortunately.
35 */
36int copro_handle_mm_fault(struct mm_struct *mm, unsigned long ea,
37 unsigned long dsisr, unsigned *flt)
38{
39 struct vm_area_struct *vma;
40 unsigned long is_write;
41 int ret;
42
43 if (mm == NULL)
44 return -EFAULT;
45
46 if (mm->pgd == NULL)
47 return -EFAULT;
48
49 down_read(&mm->mmap_sem);
50 ret = -EFAULT;
51 vma = find_vma(mm, ea);
52 if (!vma)
53 goto out_unlock;
54
55 if (ea < vma->vm_start) {
56 if (!(vma->vm_flags & VM_GROWSDOWN))
57 goto out_unlock;
58 if (expand_stack(vma, ea))
59 goto out_unlock;
60 }
61
62 is_write = dsisr & DSISR_ISSTORE;
63 if (is_write) {
64 if (!(vma->vm_flags & VM_WRITE))
65 goto out_unlock;
66 } else {
67 if (dsisr & DSISR_PROTFAULT)
68 goto out_unlock;
69 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
70 goto out_unlock;
71 }
72
73 ret = 0;
74 *flt = handle_mm_fault(mm, vma, ea, is_write ? FAULT_FLAG_WRITE : 0);
75 if (unlikely(*flt & VM_FAULT_ERROR)) {
76 if (*flt & VM_FAULT_OOM) {
77 ret = -ENOMEM;
78 goto out_unlock;
79 } else if (*flt & VM_FAULT_SIGBUS) {
80 ret = -EFAULT;
81 goto out_unlock;
82 }
83 BUG();
84 }
85
86 if (*flt & VM_FAULT_MAJOR)
87 current->maj_flt++;
88 else
89 current->min_flt++;
90
91out_unlock:
92 up_read(&mm->mmap_sem);
93 return ret;
94}
95EXPORT_SYMBOL_GPL(copro_handle_mm_fault);
96
97int copro_calculate_slb(struct mm_struct *mm, u64 ea, struct copro_slb *slb)
98{
99 u64 vsid;
100 int psize, ssize;
101
102 slb->esid = (ea & ESID_MASK) | SLB_ESID_V;
103
104 switch (REGION_ID(ea)) {
105 case USER_REGION_ID:
106 pr_devel("%s: 0x%llx -- USER_REGION_ID\n", __func__, ea);
107 psize = get_slice_psize(mm, ea);
108 ssize = user_segment_size(ea);
109 vsid = get_vsid(mm->context.id, ea, ssize);
110 break;
111 case VMALLOC_REGION_ID:
112 pr_devel("%s: 0x%llx -- VMALLOC_REGION_ID\n", __func__, ea);
113 if (ea < VMALLOC_END)
114 psize = mmu_vmalloc_psize;
115 else
116 psize = mmu_io_psize;
117 ssize = mmu_kernel_ssize;
118 vsid = get_kernel_vsid(ea, mmu_kernel_ssize);
119 break;
120 case KERNEL_REGION_ID:
121 pr_devel("%s: 0x%llx -- KERNEL_REGION_ID\n", __func__, ea);
122 psize = mmu_linear_psize;
123 ssize = mmu_kernel_ssize;
124 vsid = get_kernel_vsid(ea, mmu_kernel_ssize);
125 break;
126 default:
127 pr_debug("%s: invalid region access at %016llx\n", __func__, ea);
128 return 1;
129 }
130
131 vsid = (vsid << slb_vsid_shift(ssize)) | SLB_VSID_USER;
132
133 vsid |= mmu_psize_defs[psize].sllp |
134 ((ssize == MMU_SEGSIZE_1T) ? SLB_VSID_B_1T : 0);
135
136 slb->vsid = vsid;
137
138 return 0;
139}
140EXPORT_SYMBOL_GPL(copro_calculate_slb);
141
142void copro_flush_all_slbs(struct mm_struct *mm)
143{
144#ifdef CONFIG_SPU_BASE
145 spu_flush_all_slbs(mm);
146#endif
147 cxl_slbia(mm);
148}
149EXPORT_SYMBOL_GPL(copro_flush_all_slbs);
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 51ab9e7e6c39..24b3f4949df4 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -33,6 +33,7 @@
33#include <linux/magic.h> 33#include <linux/magic.h>
34#include <linux/ratelimit.h> 34#include <linux/ratelimit.h>
35#include <linux/context_tracking.h> 35#include <linux/context_tracking.h>
36#include <linux/hugetlb.h>
36 37
37#include <asm/firmware.h> 38#include <asm/firmware.h>
38#include <asm/page.h> 39#include <asm/page.h>
@@ -114,22 +115,37 @@ static int store_updates_sp(struct pt_regs *regs)
114#define MM_FAULT_CONTINUE -1 115#define MM_FAULT_CONTINUE -1
115#define MM_FAULT_ERR(sig) (sig) 116#define MM_FAULT_ERR(sig) (sig)
116 117
117static int do_sigbus(struct pt_regs *regs, unsigned long address) 118static int do_sigbus(struct pt_regs *regs, unsigned long address,
119 unsigned int fault)
118{ 120{
119 siginfo_t info; 121 siginfo_t info;
122 unsigned int lsb = 0;
120 123
121 up_read(&current->mm->mmap_sem); 124 up_read(&current->mm->mmap_sem);
122 125
123 if (user_mode(regs)) { 126 if (!user_mode(regs))
124 current->thread.trap_nr = BUS_ADRERR; 127 return MM_FAULT_ERR(SIGBUS);
125 info.si_signo = SIGBUS; 128
126 info.si_errno = 0; 129 current->thread.trap_nr = BUS_ADRERR;
127 info.si_code = BUS_ADRERR; 130 info.si_signo = SIGBUS;
128 info.si_addr = (void __user *)address; 131 info.si_errno = 0;
129 force_sig_info(SIGBUS, &info, current); 132 info.si_code = BUS_ADRERR;
130 return MM_FAULT_RETURN; 133 info.si_addr = (void __user *)address;
134#ifdef CONFIG_MEMORY_FAILURE
135 if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) {
136 pr_err("MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n",
137 current->comm, current->pid, address);
138 info.si_code = BUS_MCEERR_AR;
131 } 139 }
132 return MM_FAULT_ERR(SIGBUS); 140
141 if (fault & VM_FAULT_HWPOISON_LARGE)
142 lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
143 if (fault & VM_FAULT_HWPOISON)
144 lsb = PAGE_SHIFT;
145#endif
146 info.si_addr_lsb = lsb;
147 force_sig_info(SIGBUS, &info, current);
148 return MM_FAULT_RETURN;
133} 149}
134 150
135static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault) 151static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault)
@@ -170,11 +186,8 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr, int fault)
170 return MM_FAULT_RETURN; 186 return MM_FAULT_RETURN;
171 } 187 }
172 188
173 /* Bus error. x86 handles HWPOISON here, we'll add this if/when 189 if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE))
174 * we support the feature in HW 190 return do_sigbus(regs, addr, fault);
175 */
176 if (fault & VM_FAULT_SIGBUS)
177 return do_sigbus(regs, addr);
178 191
179 /* We don't understand the fault code, this is fatal */ 192 /* We don't understand the fault code, this is fatal */
180 BUG(); 193 BUG();
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index afc0a8295f84..ae4962a06476 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -29,6 +29,8 @@
29#include <asm/kexec.h> 29#include <asm/kexec.h>
30#include <asm/ppc-opcode.h> 30#include <asm/ppc-opcode.h>
31 31
32#include <misc/cxl.h>
33
32#ifdef DEBUG_LOW 34#ifdef DEBUG_LOW
33#define DBG_LOW(fmt...) udbg_printf(fmt) 35#define DBG_LOW(fmt...) udbg_printf(fmt)
34#else 36#else
@@ -149,9 +151,11 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize)
149static inline void tlbie(unsigned long vpn, int psize, int apsize, 151static inline void tlbie(unsigned long vpn, int psize, int apsize,
150 int ssize, int local) 152 int ssize, int local)
151{ 153{
152 unsigned int use_local = local && mmu_has_feature(MMU_FTR_TLBIEL); 154 unsigned int use_local;
153 int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); 155 int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
154 156
157 use_local = local && mmu_has_feature(MMU_FTR_TLBIEL) && !cxl_ctx_in_use();
158
155 if (use_local) 159 if (use_local)
156 use_local = mmu_psize_defs[psize].tlbiel; 160 use_local = mmu_psize_defs[psize].tlbiel;
157 if (lock_tlbie && !use_local) 161 if (lock_tlbie && !use_local)
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index daee7f4e5a14..d5339a3b9945 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -51,7 +51,7 @@
51#include <asm/cacheflush.h> 51#include <asm/cacheflush.h>
52#include <asm/cputable.h> 52#include <asm/cputable.h>
53#include <asm/sections.h> 53#include <asm/sections.h>
54#include <asm/spu.h> 54#include <asm/copro.h>
55#include <asm/udbg.h> 55#include <asm/udbg.h>
56#include <asm/code-patching.h> 56#include <asm/code-patching.h>
57#include <asm/fadump.h> 57#include <asm/fadump.h>
@@ -92,12 +92,14 @@ extern unsigned long dart_tablebase;
92 92
93static unsigned long _SDR1; 93static unsigned long _SDR1;
94struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; 94struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
95EXPORT_SYMBOL_GPL(mmu_psize_defs);
95 96
96struct hash_pte *htab_address; 97struct hash_pte *htab_address;
97unsigned long htab_size_bytes; 98unsigned long htab_size_bytes;
98unsigned long htab_hash_mask; 99unsigned long htab_hash_mask;
99EXPORT_SYMBOL_GPL(htab_hash_mask); 100EXPORT_SYMBOL_GPL(htab_hash_mask);
100int mmu_linear_psize = MMU_PAGE_4K; 101int mmu_linear_psize = MMU_PAGE_4K;
102EXPORT_SYMBOL_GPL(mmu_linear_psize);
101int mmu_virtual_psize = MMU_PAGE_4K; 103int mmu_virtual_psize = MMU_PAGE_4K;
102int mmu_vmalloc_psize = MMU_PAGE_4K; 104int mmu_vmalloc_psize = MMU_PAGE_4K;
103#ifdef CONFIG_SPARSEMEM_VMEMMAP 105#ifdef CONFIG_SPARSEMEM_VMEMMAP
@@ -105,6 +107,7 @@ int mmu_vmemmap_psize = MMU_PAGE_4K;
105#endif 107#endif
106int mmu_io_psize = MMU_PAGE_4K; 108int mmu_io_psize = MMU_PAGE_4K;
107int mmu_kernel_ssize = MMU_SEGSIZE_256M; 109int mmu_kernel_ssize = MMU_SEGSIZE_256M;
110EXPORT_SYMBOL_GPL(mmu_kernel_ssize);
108int mmu_highuser_ssize = MMU_SEGSIZE_256M; 111int mmu_highuser_ssize = MMU_SEGSIZE_256M;
109u16 mmu_slb_size = 64; 112u16 mmu_slb_size = 64;
110EXPORT_SYMBOL_GPL(mmu_slb_size); 113EXPORT_SYMBOL_GPL(mmu_slb_size);
@@ -333,70 +336,69 @@ static int __init htab_dt_scan_page_sizes(unsigned long node,
333 return 0; 336 return 0;
334 337
335 prop = of_get_flat_dt_prop(node, "ibm,segment-page-sizes", &size); 338 prop = of_get_flat_dt_prop(node, "ibm,segment-page-sizes", &size);
336 if (prop != NULL) { 339 if (!prop)
337 pr_info("Page sizes from device-tree:\n"); 340 return 0;
338 size /= 4; 341
339 cur_cpu_spec->mmu_features &= ~(MMU_FTR_16M_PAGE); 342 pr_info("Page sizes from device-tree:\n");
340 while(size > 0) { 343 size /= 4;
341 unsigned int base_shift = be32_to_cpu(prop[0]); 344 cur_cpu_spec->mmu_features &= ~(MMU_FTR_16M_PAGE);
342 unsigned int slbenc = be32_to_cpu(prop[1]); 345 while(size > 0) {
343 unsigned int lpnum = be32_to_cpu(prop[2]); 346 unsigned int base_shift = be32_to_cpu(prop[0]);
344 struct mmu_psize_def *def; 347 unsigned int slbenc = be32_to_cpu(prop[1]);
345 int idx, base_idx; 348 unsigned int lpnum = be32_to_cpu(prop[2]);
346 349 struct mmu_psize_def *def;
347 size -= 3; prop += 3; 350 int idx, base_idx;
348 base_idx = get_idx_from_shift(base_shift); 351
349 if (base_idx < 0) { 352 size -= 3; prop += 3;
350 /* 353 base_idx = get_idx_from_shift(base_shift);
351 * skip the pte encoding also 354 if (base_idx < 0) {
352 */ 355 /* skip the pte encoding also */
353 prop += lpnum * 2; size -= lpnum * 2; 356 prop += lpnum * 2; size -= lpnum * 2;
357 continue;
358 }
359 def = &mmu_psize_defs[base_idx];
360 if (base_idx == MMU_PAGE_16M)
361 cur_cpu_spec->mmu_features |= MMU_FTR_16M_PAGE;
362
363 def->shift = base_shift;
364 if (base_shift <= 23)
365 def->avpnm = 0;
366 else
367 def->avpnm = (1 << (base_shift - 23)) - 1;
368 def->sllp = slbenc;
369 /*
370 * We don't know for sure what's up with tlbiel, so
371 * for now we only set it for 4K and 64K pages
372 */
373 if (base_idx == MMU_PAGE_4K || base_idx == MMU_PAGE_64K)
374 def->tlbiel = 1;
375 else
376 def->tlbiel = 0;
377
378 while (size > 0 && lpnum) {
379 unsigned int shift = be32_to_cpu(prop[0]);
380 int penc = be32_to_cpu(prop[1]);
381
382 prop += 2; size -= 2;
383 lpnum--;
384
385 idx = get_idx_from_shift(shift);
386 if (idx < 0)
354 continue; 387 continue;
355 } 388
356 def = &mmu_psize_defs[base_idx]; 389 if (penc == -1)
357 if (base_idx == MMU_PAGE_16M) 390 pr_err("Invalid penc for base_shift=%d "
358 cur_cpu_spec->mmu_features |= MMU_FTR_16M_PAGE; 391 "shift=%d\n", base_shift, shift);
359 392
360 def->shift = base_shift; 393 def->penc[idx] = penc;
361 if (base_shift <= 23) 394 pr_info("base_shift=%d: shift=%d, sllp=0x%04lx,"
362 def->avpnm = 0; 395 " avpnm=0x%08lx, tlbiel=%d, penc=%d\n",
363 else 396 base_shift, shift, def->sllp,
364 def->avpnm = (1 << (base_shift - 23)) - 1; 397 def->avpnm, def->tlbiel, def->penc[idx]);
365 def->sllp = slbenc;
366 /*
367 * We don't know for sure what's up with tlbiel, so
368 * for now we only set it for 4K and 64K pages
369 */
370 if (base_idx == MMU_PAGE_4K || base_idx == MMU_PAGE_64K)
371 def->tlbiel = 1;
372 else
373 def->tlbiel = 0;
374
375 while (size > 0 && lpnum) {
376 unsigned int shift = be32_to_cpu(prop[0]);
377 int penc = be32_to_cpu(prop[1]);
378
379 prop += 2; size -= 2;
380 lpnum--;
381
382 idx = get_idx_from_shift(shift);
383 if (idx < 0)
384 continue;
385
386 if (penc == -1)
387 pr_err("Invalid penc for base_shift=%d "
388 "shift=%d\n", base_shift, shift);
389
390 def->penc[idx] = penc;
391 pr_info("base_shift=%d: shift=%d, sllp=0x%04lx,"
392 " avpnm=0x%08lx, tlbiel=%d, penc=%d\n",
393 base_shift, shift, def->sllp,
394 def->avpnm, def->tlbiel, def->penc[idx]);
395 }
396 } 398 }
397 return 1;
398 } 399 }
399 return 0; 400
401 return 1;
400} 402}
401 403
402#ifdef CONFIG_HUGETLB_PAGE 404#ifdef CONFIG_HUGETLB_PAGE
@@ -867,7 +869,7 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
867} 869}
868 870
869#ifdef CONFIG_PPC_MM_SLICES 871#ifdef CONFIG_PPC_MM_SLICES
870unsigned int get_paca_psize(unsigned long addr) 872static unsigned int get_paca_psize(unsigned long addr)
871{ 873{
872 u64 lpsizes; 874 u64 lpsizes;
873 unsigned char *hpsizes; 875 unsigned char *hpsizes;
@@ -901,10 +903,8 @@ void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
901 if (get_slice_psize(mm, addr) == MMU_PAGE_4K) 903 if (get_slice_psize(mm, addr) == MMU_PAGE_4K)
902 return; 904 return;
903 slice_set_range_psize(mm, addr, 1, MMU_PAGE_4K); 905 slice_set_range_psize(mm, addr, 1, MMU_PAGE_4K);
904#ifdef CONFIG_SPU_BASE 906 copro_flush_all_slbs(mm);
905 spu_flush_all_slbs(mm); 907 if ((get_paca_psize(addr) != MMU_PAGE_4K) && (current->mm == mm)) {
906#endif
907 if (get_paca_psize(addr) != MMU_PAGE_4K) {
908 get_paca()->context = mm->context; 908 get_paca()->context = mm->context;
909 slb_flush_and_rebolt(); 909 slb_flush_and_rebolt();
910 } 910 }
@@ -989,12 +989,11 @@ static void check_paca_psize(unsigned long ea, struct mm_struct *mm,
989 * -1 - critical hash insertion error 989 * -1 - critical hash insertion error
990 * -2 - access not permitted by subpage protection mechanism 990 * -2 - access not permitted by subpage protection mechanism
991 */ 991 */
992int hash_page(unsigned long ea, unsigned long access, unsigned long trap) 992int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, unsigned long trap)
993{ 993{
994 enum ctx_state prev_state = exception_enter(); 994 enum ctx_state prev_state = exception_enter();
995 pgd_t *pgdir; 995 pgd_t *pgdir;
996 unsigned long vsid; 996 unsigned long vsid;
997 struct mm_struct *mm;
998 pte_t *ptep; 997 pte_t *ptep;
999 unsigned hugeshift; 998 unsigned hugeshift;
1000 const struct cpumask *tmp; 999 const struct cpumask *tmp;
@@ -1008,7 +1007,6 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1008 switch (REGION_ID(ea)) { 1007 switch (REGION_ID(ea)) {
1009 case USER_REGION_ID: 1008 case USER_REGION_ID:
1010 user_region = 1; 1009 user_region = 1;
1011 mm = current->mm;
1012 if (! mm) { 1010 if (! mm) {
1013 DBG_LOW(" user region with no mm !\n"); 1011 DBG_LOW(" user region with no mm !\n");
1014 rc = 1; 1012 rc = 1;
@@ -1019,7 +1017,6 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1019 vsid = get_vsid(mm->context.id, ea, ssize); 1017 vsid = get_vsid(mm->context.id, ea, ssize);
1020 break; 1018 break;
1021 case VMALLOC_REGION_ID: 1019 case VMALLOC_REGION_ID:
1022 mm = &init_mm;
1023 vsid = get_kernel_vsid(ea, mmu_kernel_ssize); 1020 vsid = get_kernel_vsid(ea, mmu_kernel_ssize);
1024 if (ea < VMALLOC_END) 1021 if (ea < VMALLOC_END)
1025 psize = mmu_vmalloc_psize; 1022 psize = mmu_vmalloc_psize;
@@ -1104,7 +1101,8 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1104 WARN_ON(1); 1101 WARN_ON(1);
1105 } 1102 }
1106#endif 1103#endif
1107 check_paca_psize(ea, mm, psize, user_region); 1104 if (current->mm == mm)
1105 check_paca_psize(ea, mm, psize, user_region);
1108 1106
1109 goto bail; 1107 goto bail;
1110 } 1108 }
@@ -1141,13 +1139,12 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1141 "to 4kB pages because of " 1139 "to 4kB pages because of "
1142 "non-cacheable mapping\n"); 1140 "non-cacheable mapping\n");
1143 psize = mmu_vmalloc_psize = MMU_PAGE_4K; 1141 psize = mmu_vmalloc_psize = MMU_PAGE_4K;
1144#ifdef CONFIG_SPU_BASE 1142 copro_flush_all_slbs(mm);
1145 spu_flush_all_slbs(mm);
1146#endif
1147 } 1143 }
1148 } 1144 }
1149 1145
1150 check_paca_psize(ea, mm, psize, user_region); 1146 if (current->mm == mm)
1147 check_paca_psize(ea, mm, psize, user_region);
1151#endif /* CONFIG_PPC_64K_PAGES */ 1148#endif /* CONFIG_PPC_64K_PAGES */
1152 1149
1153#ifdef CONFIG_PPC_HAS_HASH_64K 1150#ifdef CONFIG_PPC_HAS_HASH_64K
@@ -1182,6 +1179,17 @@ bail:
1182 exception_exit(prev_state); 1179 exception_exit(prev_state);
1183 return rc; 1180 return rc;
1184} 1181}
1182EXPORT_SYMBOL_GPL(hash_page_mm);
1183
1184int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1185{
1186 struct mm_struct *mm = current->mm;
1187
1188 if (REGION_ID(ea) == VMALLOC_REGION_ID)
1189 mm = &init_mm;
1190
1191 return hash_page_mm(mm, ea, access, trap);
1192}
1185EXPORT_SYMBOL_GPL(hash_page); 1193EXPORT_SYMBOL_GPL(hash_page);
1186 1194
1187void hash_preload(struct mm_struct *mm, unsigned long ea, 1195void hash_preload(struct mm_struct *mm, unsigned long ea,
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index cff59f1bec23..cad68ff8eca5 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -106,11 +106,11 @@ unsigned long __max_low_memory = MAX_LOW_MEM;
106void MMU_setup(void) 106void MMU_setup(void)
107{ 107{
108 /* Check for nobats option (used in mapin_ram). */ 108 /* Check for nobats option (used in mapin_ram). */
109 if (strstr(cmd_line, "nobats")) { 109 if (strstr(boot_command_line, "nobats")) {
110 __map_without_bats = 1; 110 __map_without_bats = 1;
111 } 111 }
112 112
113 if (strstr(cmd_line, "noltlbs")) { 113 if (strstr(boot_command_line, "noltlbs")) {
114 __map_without_ltlbs = 1; 114 __map_without_ltlbs = 1;
115 } 115 }
116#ifdef CONFIG_DEBUG_PAGEALLOC 116#ifdef CONFIG_DEBUG_PAGEALLOC
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 253b4b971c8a..3481556a1880 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -233,9 +233,6 @@ static void __meminit vmemmap_create_mapping(unsigned long start,
233} 233}
234 234
235#ifdef CONFIG_MEMORY_HOTPLUG 235#ifdef CONFIG_MEMORY_HOTPLUG
236extern int htab_remove_mapping(unsigned long vstart, unsigned long vend,
237 int psize, int ssize);
238
239static void vmemmap_remove_mapping(unsigned long start, 236static void vmemmap_remove_mapping(unsigned long start,
240 unsigned long page_size) 237 unsigned long page_size)
241{ 238{
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index e0f7a189c48e..8ebaac75c940 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -260,6 +260,60 @@ static int __init mark_nonram_nosave(void)
260 } 260 }
261 return 0; 261 return 0;
262} 262}
263#else /* CONFIG_NEED_MULTIPLE_NODES */
264static int __init mark_nonram_nosave(void)
265{
266 return 0;
267}
268#endif
269
270static bool zone_limits_final;
271
272static unsigned long max_zone_pfns[MAX_NR_ZONES] = {
273 [0 ... MAX_NR_ZONES - 1] = ~0UL
274};
275
276/*
277 * Restrict the specified zone and all more restrictive zones
278 * to be below the specified pfn. May not be called after
279 * paging_init().
280 */
281void __init limit_zone_pfn(enum zone_type zone, unsigned long pfn_limit)
282{
283 int i;
284
285 if (WARN_ON(zone_limits_final))
286 return;
287
288 for (i = zone; i >= 0; i--) {
289 if (max_zone_pfns[i] > pfn_limit)
290 max_zone_pfns[i] = pfn_limit;
291 }
292}
293
294/*
295 * Find the least restrictive zone that is entirely below the
296 * specified pfn limit. Returns < 0 if no suitable zone is found.
297 *
298 * pfn_limit must be u64 because it can exceed 32 bits even on 32-bit
299 * systems -- the DMA limit can be higher than any possible real pfn.
300 */
301int dma_pfn_limit_to_zone(u64 pfn_limit)
302{
303 enum zone_type top_zone = ZONE_NORMAL;
304 int i;
305
306#ifdef CONFIG_HIGHMEM
307 top_zone = ZONE_HIGHMEM;
308#endif
309
310 for (i = top_zone; i >= 0; i--) {
311 if (max_zone_pfns[i] <= pfn_limit)
312 return i;
313 }
314
315 return -EPERM;
316}
263 317
264/* 318/*
265 * paging_init() sets up the page tables - in fact we've already done this. 319 * paging_init() sets up the page tables - in fact we've already done this.
@@ -268,7 +322,7 @@ void __init paging_init(void)
268{ 322{
269 unsigned long long total_ram = memblock_phys_mem_size(); 323 unsigned long long total_ram = memblock_phys_mem_size();
270 phys_addr_t top_of_ram = memblock_end_of_DRAM(); 324 phys_addr_t top_of_ram = memblock_end_of_DRAM();
271 unsigned long max_zone_pfns[MAX_NR_ZONES]; 325 enum zone_type top_zone;
272 326
273#ifdef CONFIG_PPC32 327#ifdef CONFIG_PPC32
274 unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1); 328 unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1);
@@ -290,18 +344,20 @@ void __init paging_init(void)
290 (unsigned long long)top_of_ram, total_ram); 344 (unsigned long long)top_of_ram, total_ram);
291 printk(KERN_DEBUG "Memory hole size: %ldMB\n", 345 printk(KERN_DEBUG "Memory hole size: %ldMB\n",
292 (long int)((top_of_ram - total_ram) >> 20)); 346 (long int)((top_of_ram - total_ram) >> 20));
293 memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); 347
294#ifdef CONFIG_HIGHMEM 348#ifdef CONFIG_HIGHMEM
295 max_zone_pfns[ZONE_DMA] = lowmem_end_addr >> PAGE_SHIFT; 349 top_zone = ZONE_HIGHMEM;
296 max_zone_pfns[ZONE_HIGHMEM] = top_of_ram >> PAGE_SHIFT; 350 limit_zone_pfn(ZONE_NORMAL, lowmem_end_addr >> PAGE_SHIFT);
297#else 351#else
298 max_zone_pfns[ZONE_DMA] = top_of_ram >> PAGE_SHIFT; 352 top_zone = ZONE_NORMAL;
299#endif 353#endif
354
355 limit_zone_pfn(top_zone, top_of_ram >> PAGE_SHIFT);
356 zone_limits_final = true;
300 free_area_init_nodes(max_zone_pfns); 357 free_area_init_nodes(max_zone_pfns);
301 358
302 mark_nonram_nosave(); 359 mark_nonram_nosave();
303} 360}
304#endif /* ! CONFIG_NEED_MULTIPLE_NODES */
305 361
306static void __init register_page_bootmem_info(void) 362static void __init register_page_bootmem_info(void)
307{ 363{
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index d7737a542fd7..649666d5d1c2 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -538,7 +538,7 @@ static int of_drconf_to_nid_single(struct of_drconf_cell *drmem,
538 */ 538 */
539static int numa_setup_cpu(unsigned long lcpu) 539static int numa_setup_cpu(unsigned long lcpu)
540{ 540{
541 int nid; 541 int nid = -1;
542 struct device_node *cpu; 542 struct device_node *cpu;
543 543
544 /* 544 /*
@@ -555,19 +555,21 @@ static int numa_setup_cpu(unsigned long lcpu)
555 555
556 if (!cpu) { 556 if (!cpu) {
557 WARN_ON(1); 557 WARN_ON(1);
558 nid = 0; 558 if (cpu_present(lcpu))
559 goto out; 559 goto out_present;
560 else
561 goto out;
560 } 562 }
561 563
562 nid = of_node_to_nid_single(cpu); 564 nid = of_node_to_nid_single(cpu);
563 565
566out_present:
564 if (nid < 0 || !node_online(nid)) 567 if (nid < 0 || !node_online(nid))
565 nid = first_online_node; 568 nid = first_online_node;
566out:
567 map_cpu_to_node(lcpu, nid);
568 569
570 map_cpu_to_node(lcpu, nid);
569 of_node_put(cpu); 571 of_node_put(cpu);
570 572out:
571 return nid; 573 return nid;
572} 574}
573 575
@@ -1127,20 +1129,11 @@ void __init do_init_bootmem(void)
1127 * even before we online them, so that we can use cpu_to_{node,mem} 1129 * even before we online them, so that we can use cpu_to_{node,mem}
1128 * early in boot, cf. smp_prepare_cpus(). 1130 * early in boot, cf. smp_prepare_cpus().
1129 */ 1131 */
1130 for_each_possible_cpu(cpu) { 1132 for_each_present_cpu(cpu) {
1131 cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE, 1133 numa_setup_cpu((unsigned long)cpu);
1132 (void *)(unsigned long)cpu);
1133 } 1134 }
1134} 1135}
1135 1136
1136void __init paging_init(void)
1137{
1138 unsigned long max_zone_pfns[MAX_NR_ZONES];
1139 memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
1140 max_zone_pfns[ZONE_DMA] = memblock_end_of_DRAM() >> PAGE_SHIFT;
1141 free_area_init_nodes(max_zone_pfns);
1142}
1143
1144static int __init early_numa(char *p) 1137static int __init early_numa(char *p)
1145{ 1138{
1146 if (!p) 1139 if (!p)
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c
index c695943a513c..c90e602677c9 100644
--- a/arch/powerpc/mm/pgtable.c
+++ b/arch/powerpc/mm/pgtable.c
@@ -48,7 +48,7 @@ static inline int pte_looks_normal(pte_t pte)
48 (_PAGE_PRESENT | _PAGE_USER); 48 (_PAGE_PRESENT | _PAGE_USER);
49} 49}
50 50
51struct page * maybe_pte_to_page(pte_t pte) 51static struct page *maybe_pte_to_page(pte_t pte)
52{ 52{
53 unsigned long pfn = pte_pfn(pte); 53 unsigned long pfn = pte_pfn(pte);
54 struct page *page; 54 struct page *page;
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c
index 0399a6702958..6e450ca66526 100644
--- a/arch/powerpc/mm/slb.c
+++ b/arch/powerpc/mm/slb.c
@@ -46,9 +46,6 @@ static inline unsigned long mk_esid_data(unsigned long ea, int ssize,
46 return (ea & slb_esid_mask(ssize)) | SLB_ESID_V | slot; 46 return (ea & slb_esid_mask(ssize)) | SLB_ESID_V | slot;
47} 47}
48 48
49#define slb_vsid_shift(ssize) \
50 ((ssize) == MMU_SEGSIZE_256M? SLB_VSID_SHIFT: SLB_VSID_SHIFT_1T)
51
52static inline unsigned long mk_vsid_data(unsigned long ea, int ssize, 49static inline unsigned long mk_vsid_data(unsigned long ea, int ssize,
53 unsigned long flags) 50 unsigned long flags)
54{ 51{
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index b0c75cc15efc..8d7bda94d196 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -30,9 +30,11 @@
30#include <linux/err.h> 30#include <linux/err.h>
31#include <linux/spinlock.h> 31#include <linux/spinlock.h>
32#include <linux/export.h> 32#include <linux/export.h>
33#include <linux/hugetlb.h>
33#include <asm/mman.h> 34#include <asm/mman.h>
34#include <asm/mmu.h> 35#include <asm/mmu.h>
35#include <asm/spu.h> 36#include <asm/copro.h>
37#include <asm/hugetlb.h>
36 38
37/* some sanity checks */ 39/* some sanity checks */
38#if (PGTABLE_RANGE >> 43) > SLICE_MASK_SIZE 40#if (PGTABLE_RANGE >> 43) > SLICE_MASK_SIZE
@@ -232,9 +234,7 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
232 234
233 spin_unlock_irqrestore(&slice_convert_lock, flags); 235 spin_unlock_irqrestore(&slice_convert_lock, flags);
234 236
235#ifdef CONFIG_SPU_BASE 237 copro_flush_all_slbs(mm);
236 spu_flush_all_slbs(mm);
237#endif
238} 238}
239 239
240/* 240/*
@@ -671,9 +671,7 @@ void slice_set_psize(struct mm_struct *mm, unsigned long address,
671 671
672 spin_unlock_irqrestore(&slice_convert_lock, flags); 672 spin_unlock_irqrestore(&slice_convert_lock, flags);
673 673
674#ifdef CONFIG_SPU_BASE 674 copro_flush_all_slbs(mm);
675 spu_flush_all_slbs(mm);
676#endif
677} 675}
678 676
679void slice_set_range_psize(struct mm_struct *mm, unsigned long start, 677void slice_set_range_psize(struct mm_struct *mm, unsigned long start,