aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/mm')
-rw-r--r--arch/ppc/mm/44x_mmu.c101
-rw-r--r--arch/ppc/mm/4xx_mmu.c135
-rw-r--r--arch/ppc/mm/Makefile10
-rw-r--r--arch/ppc/mm/fault.c436
-rw-r--r--arch/ppc/mm/hashtable.S617
-rw-r--r--arch/ppc/mm/init.c603
-rw-r--r--arch/ppc/mm/mem_pieces.c162
-rw-r--r--arch/ppc/mm/mem_pieces.h48
-rw-r--r--arch/ppc/mm/mmu_context.c85
-rw-r--r--arch/ppc/mm/mmu_decl.h79
-rw-r--r--arch/ppc/mm/pgtable.c403
-rw-r--r--arch/ppc/mm/ppc_mmu.c269
-rw-r--r--arch/ppc/mm/tlb.c183
13 files changed, 0 insertions, 3131 deletions
diff --git a/arch/ppc/mm/44x_mmu.c b/arch/ppc/mm/44x_mmu.c
deleted file mode 100644
index fbb577a0d165..000000000000
--- a/arch/ppc/mm/44x_mmu.c
+++ /dev/null
@@ -1,101 +0,0 @@
1/*
2 * Modifications by Matt Porter (mporter@mvista.com) to support
3 * PPC44x Book E processors.
4 *
5 * This file contains the routines for initializing the MMU
6 * on the 4xx series of chips.
7 * -- paulus
8 *
9 * Derived from arch/ppc/mm/init.c:
10 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
11 *
12 * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
13 * and Cort Dougan (PReP) (cort@cs.nmt.edu)
14 * Copyright (C) 1996 Paul Mackerras
15 * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
16 *
17 * Derived from "arch/i386/mm/init.c"
18 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
19 *
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version
23 * 2 of the License, or (at your option) any later version.
24 *
25 */
26
27#include <linux/signal.h>
28#include <linux/sched.h>
29#include <linux/kernel.h>
30#include <linux/errno.h>
31#include <linux/string.h>
32#include <linux/types.h>
33#include <linux/ptrace.h>
34#include <linux/mman.h>
35#include <linux/mm.h>
36#include <linux/swap.h>
37#include <linux/stddef.h>
38#include <linux/vmalloc.h>
39#include <linux/init.h>
40#include <linux/delay.h>
41#include <linux/highmem.h>
42
43#include <asm/pgalloc.h>
44#include <asm/prom.h>
45#include <asm/io.h>
46#include <asm/mmu_context.h>
47#include <asm/pgtable.h>
48#include <asm/mmu.h>
49#include <asm/uaccess.h>
50#include <asm/smp.h>
51#include <asm/bootx.h>
52#include <asm/machdep.h>
53#include <asm/setup.h>
54
55#include "mmu_decl.h"
56
57extern char etext[], _stext[];
58
59/* Used by the 44x TLB replacement exception handler.
60 * Just needed it declared someplace.
61 */
62unsigned int tlb_44x_index = 0;
63unsigned int tlb_44x_hwater = PPC4XX_TLB_SIZE - 1 - PPC44x_EARLY_TLBS;
64int icache_44x_need_flush;
65
66/*
67 * "Pins" a 256MB TLB entry in AS0 for kernel lowmem
68 */
69static void __init ppc44x_pin_tlb(unsigned int virt, unsigned int phys)
70{
71 __asm__ __volatile__(
72 "tlbwe %2,%3,%4\n"
73 "tlbwe %1,%3,%5\n"
74 "tlbwe %0,%3,%6\n"
75 :
76 : "r" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G),
77 "r" (phys),
78 "r" (virt | PPC44x_TLB_VALID | PPC44x_TLB_256M),
79 "r" (tlb_44x_hwater--), /* slot for this TLB entry */
80 "i" (PPC44x_TLB_PAGEID),
81 "i" (PPC44x_TLB_XLAT),
82 "i" (PPC44x_TLB_ATTRIB));
83}
84
85void __init MMU_init_hw(void)
86{
87 flush_instruction_cache();
88}
89
90unsigned long __init mmu_mapin_ram(void)
91{
92 unsigned long addr;
93
94 /* Pin in enough TLBs to cover any lowmem not covered by the
95 * initial 256M mapping established in head_44x.S */
96 for (addr = PPC_PIN_SIZE; addr < total_lowmem;
97 addr += PPC_PIN_SIZE)
98 ppc44x_pin_tlb(addr + PAGE_OFFSET, addr);
99
100 return total_lowmem;
101}
diff --git a/arch/ppc/mm/4xx_mmu.c b/arch/ppc/mm/4xx_mmu.c
deleted file mode 100644
index ea785dbaac7c..000000000000
--- a/arch/ppc/mm/4xx_mmu.c
+++ /dev/null
@@ -1,135 +0,0 @@
1/*
2 * This file contains the routines for initializing the MMU
3 * on the 4xx series of chips.
4 * -- paulus
5 *
6 * Derived from arch/ppc/mm/init.c:
7 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
8 *
9 * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
10 * and Cort Dougan (PReP) (cort@cs.nmt.edu)
11 * Copyright (C) 1996 Paul Mackerras
12 * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
13 *
14 * Derived from "arch/i386/mm/init.c"
15 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version
20 * 2 of the License, or (at your option) any later version.
21 *
22 */
23
24#include <linux/signal.h>
25#include <linux/sched.h>
26#include <linux/kernel.h>
27#include <linux/errno.h>
28#include <linux/string.h>
29#include <linux/types.h>
30#include <linux/ptrace.h>
31#include <linux/mman.h>
32#include <linux/mm.h>
33#include <linux/swap.h>
34#include <linux/stddef.h>
35#include <linux/vmalloc.h>
36#include <linux/init.h>
37#include <linux/delay.h>
38#include <linux/highmem.h>
39
40#include <asm/pgalloc.h>
41#include <asm/prom.h>
42#include <asm/io.h>
43#include <asm/mmu_context.h>
44#include <asm/pgtable.h>
45#include <asm/mmu.h>
46#include <asm/uaccess.h>
47#include <asm/smp.h>
48#include <asm/bootx.h>
49#include <asm/machdep.h>
50#include <asm/setup.h>
51#include "mmu_decl.h"
52
53extern int __map_without_ltlbs;
54/*
55 * MMU_init_hw does the chip-specific initialization of the MMU hardware.
56 */
57void __init MMU_init_hw(void)
58{
59 /*
60 * The Zone Protection Register (ZPR) defines how protection will
61 * be applied to every page which is a member of a given zone. At
62 * present, we utilize only two of the 4xx's zones.
63 * The zone index bits (of ZSEL) in the PTE are used for software
64 * indicators, except the LSB. For user access, zone 1 is used,
65 * for kernel access, zone 0 is used. We set all but zone 1
66 * to zero, allowing only kernel access as indicated in the PTE.
67 * For zone 1, we set a 01 binary (a value of 10 will not work)
68 * to allow user access as indicated in the PTE. This also allows
69 * kernel access as indicated in the PTE.
70 */
71
72 mtspr(SPRN_ZPR, 0x10000000);
73
74 flush_instruction_cache();
75
76 /*
77 * Set up the real-mode cache parameters for the exception vector
78 * handlers (which are run in real-mode).
79 */
80
81 mtspr(SPRN_DCWR, 0x00000000); /* All caching is write-back */
82
83 /*
84 * Cache instruction and data space where the exception
85 * vectors and the kernel live in real-mode.
86 */
87
88 mtspr(SPRN_DCCR, 0xF0000000); /* 512 MB of data space at 0x0. */
89 mtspr(SPRN_ICCR, 0xF0000000); /* 512 MB of instr. space at 0x0. */
90}
91
92#define LARGE_PAGE_SIZE_16M (1<<24)
93#define LARGE_PAGE_SIZE_4M (1<<22)
94
95unsigned long __init mmu_mapin_ram(void)
96{
97 unsigned long v, s;
98 phys_addr_t p;
99
100 v = KERNELBASE;
101 p = PPC_MEMSTART;
102 s = total_lowmem;
103
104 if (__map_without_ltlbs)
105 return 0;
106
107 while (s >= LARGE_PAGE_SIZE_16M) {
108 pmd_t *pmdp;
109 unsigned long val = p | _PMD_SIZE_16M | _PAGE_HWEXEC | _PAGE_HWWRITE;
110
111 pmdp = pmd_offset(pgd_offset_k(v), v);
112 pmd_val(*pmdp++) = val;
113 pmd_val(*pmdp++) = val;
114 pmd_val(*pmdp++) = val;
115 pmd_val(*pmdp++) = val;
116
117 v += LARGE_PAGE_SIZE_16M;
118 p += LARGE_PAGE_SIZE_16M;
119 s -= LARGE_PAGE_SIZE_16M;
120 }
121
122 while (s >= LARGE_PAGE_SIZE_4M) {
123 pmd_t *pmdp;
124 unsigned long val = p | _PMD_SIZE_4M | _PAGE_HWEXEC | _PAGE_HWWRITE;
125
126 pmdp = pmd_offset(pgd_offset_k(v), v);
127 pmd_val(*pmdp) = val;
128
129 v += LARGE_PAGE_SIZE_4M;
130 p += LARGE_PAGE_SIZE_4M;
131 s -= LARGE_PAGE_SIZE_4M;
132 }
133
134 return total_lowmem - s;
135}
diff --git a/arch/ppc/mm/Makefile b/arch/ppc/mm/Makefile
deleted file mode 100644
index 691ba2bae05d..000000000000
--- a/arch/ppc/mm/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
1#
2# Makefile for the linux ppc-specific parts of the memory manager.
3#
4
5obj-y := fault.o init.o mem_pieces.o \
6 mmu_context.o pgtable.o
7
8obj-$(CONFIG_PPC_STD_MMU) += hashtable.o ppc_mmu.o tlb.o
9obj-$(CONFIG_40x) += 4xx_mmu.o
10obj-$(CONFIG_44x) += 44x_mmu.o
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
deleted file mode 100644
index 36c0e7529edb..000000000000
--- a/arch/ppc/mm/fault.c
+++ /dev/null
@@ -1,436 +0,0 @@
1/*
2 * PowerPC version
3 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
4 *
5 * Derived from "arch/i386/mm/fault.c"
6 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
7 *
8 * Modified by Cort Dougan and Paul Mackerras.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/signal.h>
17#include <linux/sched.h>
18#include <linux/kernel.h>
19#include <linux/errno.h>
20#include <linux/string.h>
21#include <linux/types.h>
22#include <linux/ptrace.h>
23#include <linux/mman.h>
24#include <linux/mm.h>
25#include <linux/interrupt.h>
26#include <linux/highmem.h>
27#include <linux/module.h>
28
29#include <asm/page.h>
30#include <asm/pgtable.h>
31#include <asm/mmu.h>
32#include <asm/mmu_context.h>
33#include <asm/system.h>
34#include <asm/uaccess.h>
35#include <asm/tlbflush.h>
36
37#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
38extern void (*debugger)(struct pt_regs *);
39extern void (*debugger_fault_handler)(struct pt_regs *);
40extern int (*debugger_dabr_match)(struct pt_regs *);
41int debugger_kernel_faults = 1;
42#endif
43
44unsigned long htab_reloads; /* updated by hashtable.S:hash_page() */
45unsigned long htab_evicts; /* updated by hashtable.S:hash_page() */
46unsigned long htab_preloads; /* updated by hashtable.S:add_hash_page() */
47unsigned long pte_misses; /* updated by do_page_fault() */
48unsigned long pte_errors; /* updated by do_page_fault() */
49unsigned int probingmem;
50
51/*
52 * Check whether the instruction at regs->nip is a store using
53 * an update addressing form which will update r1.
54 */
55static int store_updates_sp(struct pt_regs *regs)
56{
57 unsigned int inst;
58
59 if (get_user(inst, (unsigned int __user *)regs->nip))
60 return 0;
61 /* check for 1 in the rA field */
62 if (((inst >> 16) & 0x1f) != 1)
63 return 0;
64 /* check major opcode */
65 switch (inst >> 26) {
66 case 37: /* stwu */
67 case 39: /* stbu */
68 case 45: /* sthu */
69 case 53: /* stfsu */
70 case 55: /* stfdu */
71 return 1;
72 case 31:
73 /* check minor opcode */
74 switch ((inst >> 1) & 0x3ff) {
75 case 183: /* stwux */
76 case 247: /* stbux */
77 case 439: /* sthux */
78 case 695: /* stfsux */
79 case 759: /* stfdux */
80 return 1;
81 }
82 }
83 return 0;
84}
85
86/*
87 * For 600- and 800-family processors, the error_code parameter is DSISR
88 * for a data fault, SRR1 for an instruction fault. For 400-family processors
89 * the error_code parameter is ESR for a data fault, 0 for an instruction
90 * fault.
91 */
92int do_page_fault(struct pt_regs *regs, unsigned long address,
93 unsigned long error_code)
94{
95 struct vm_area_struct * vma;
96 struct mm_struct *mm = current->mm;
97 siginfo_t info;
98 int code = SEGV_MAPERR;
99 int fault;
100#if defined(CONFIG_4xx) || defined (CONFIG_BOOKE)
101 int is_write = error_code & ESR_DST;
102#else
103 int is_write = 0;
104
105 /*
106 * Fortunately the bit assignments in SRR1 for an instruction
107 * fault and DSISR for a data fault are mostly the same for the
108 * bits we are interested in. But there are some bits which
109 * indicate errors in DSISR but can validly be set in SRR1.
110 */
111 if (TRAP(regs) == 0x400)
112 error_code &= 0x48200000;
113 else
114 is_write = error_code & 0x02000000;
115#endif /* CONFIG_4xx || CONFIG_BOOKE */
116
117#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
118 if (debugger_fault_handler && TRAP(regs) == 0x300) {
119 debugger_fault_handler(regs);
120 return 0;
121 }
122#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
123 if (error_code & 0x00400000) {
124 /* DABR match */
125 if (debugger_dabr_match(regs))
126 return 0;
127 }
128#endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
129#endif /* CONFIG_XMON || CONFIG_KGDB */
130
131 if (in_atomic() || mm == NULL)
132 return SIGSEGV;
133
134 down_read(&mm->mmap_sem);
135 vma = find_vma(mm, address);
136 if (!vma)
137 goto bad_area;
138 if (vma->vm_start <= address)
139 goto good_area;
140 if (!(vma->vm_flags & VM_GROWSDOWN))
141 goto bad_area;
142 if (!is_write)
143 goto bad_area;
144
145 /*
146 * N.B. The rs6000/xcoff ABI allows programs to access up to
147 * a few hundred bytes below the stack pointer.
148 * The kernel signal delivery code writes up to about 1.5kB
149 * below the stack pointer (r1) before decrementing it.
150 * The exec code can write slightly over 640kB to the stack
151 * before setting the user r1. Thus we allow the stack to
152 * expand to 1MB without further checks.
153 */
154 if (address + 0x100000 < vma->vm_end) {
155 /* get user regs even if this fault is in kernel mode */
156 struct pt_regs *uregs = current->thread.regs;
157 if (uregs == NULL)
158 goto bad_area;
159
160 /*
161 * A user-mode access to an address a long way below
162 * the stack pointer is only valid if the instruction
163 * is one which would update the stack pointer to the
164 * address accessed if the instruction completed,
165 * i.e. either stwu rs,n(r1) or stwux rs,r1,rb
166 * (or the byte, halfword, float or double forms).
167 *
168 * If we don't check this then any write to the area
169 * between the last mapped region and the stack will
170 * expand the stack rather than segfaulting.
171 */
172 if (address + 2048 < uregs->gpr[1]
173 && (!user_mode(regs) || !store_updates_sp(regs)))
174 goto bad_area;
175 }
176 if (expand_stack(vma, address))
177 goto bad_area;
178
179good_area:
180 code = SEGV_ACCERR;
181#if defined(CONFIG_6xx)
182 if (error_code & 0x95700000)
183 /* an error such as lwarx to I/O controller space,
184 address matching DABR, eciwx, etc. */
185 goto bad_area;
186#endif /* CONFIG_6xx */
187#if defined(CONFIG_8xx)
188 /* The MPC8xx seems to always set 0x80000000, which is
189 * "undefined". Of those that can be set, this is the only
190 * one which seems bad.
191 */
192 if (error_code & 0x10000000)
193 /* Guarded storage error. */
194 goto bad_area;
195#endif /* CONFIG_8xx */
196
197 /* a write */
198 if (is_write) {
199 if (!(vma->vm_flags & VM_WRITE))
200 goto bad_area;
201#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
202 /* an exec - 4xx/Book-E allows for per-page execute permission */
203 } else if (TRAP(regs) == 0x400) {
204 pte_t *ptep;
205 pmd_t *pmdp;
206
207#if 0
208 /* It would be nice to actually enforce the VM execute
209 permission on CPUs which can do so, but far too
210 much stuff in userspace doesn't get the permissions
211 right, so we let any page be executed for now. */
212 if (! (vma->vm_flags & VM_EXEC))
213 goto bad_area;
214#endif
215
216 /* Since 4xx/Book-E supports per-page execute permission,
217 * we lazily flush dcache to icache. */
218 ptep = NULL;
219 if (get_pteptr(mm, address, &ptep, &pmdp)) {
220 spinlock_t *ptl = pte_lockptr(mm, pmdp);
221 spin_lock(ptl);
222 if (pte_present(*ptep)) {
223 struct page *page = pte_page(*ptep);
224
225 if (!test_bit(PG_arch_1, &page->flags)) {
226 flush_dcache_icache_page(page);
227 set_bit(PG_arch_1, &page->flags);
228 }
229 pte_update(ptep, 0, _PAGE_HWEXEC);
230 _tlbie(address, mm->context.id);
231 pte_unmap_unlock(ptep, ptl);
232 up_read(&mm->mmap_sem);
233 return 0;
234 }
235 pte_unmap_unlock(ptep, ptl);
236 }
237#endif
238 /* a read */
239 } else {
240 /* protection fault */
241 if (error_code & 0x08000000)
242 goto bad_area;
243 if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
244 goto bad_area;
245 }
246
247 /*
248 * If for any reason at all we couldn't handle the fault,
249 * make sure we exit gracefully rather than endlessly redo
250 * the fault.
251 */
252 survive:
253 fault = handle_mm_fault(mm, vma, address, is_write);
254 if (unlikely(fault & VM_FAULT_ERROR)) {
255 if (fault & VM_FAULT_OOM)
256 goto out_of_memory;
257 else if (fault & VM_FAULT_SIGBUS)
258 goto do_sigbus;
259 BUG();
260 }
261 if (fault & VM_FAULT_MAJOR)
262 current->maj_flt++;
263 else
264 current->min_flt++;
265
266 up_read(&mm->mmap_sem);
267 /*
268 * keep track of tlb+htab misses that are good addrs but
269 * just need pte's created via handle_mm_fault()
270 * -- Cort
271 */
272 pte_misses++;
273 return 0;
274
275bad_area:
276 up_read(&mm->mmap_sem);
277 pte_errors++;
278
279 /* User mode accesses cause a SIGSEGV */
280 if (user_mode(regs)) {
281 _exception(SIGSEGV, regs, code, address);
282 return 0;
283 }
284
285 return SIGSEGV;
286
287/*
288 * We ran out of memory, or some other thing happened to us that made
289 * us unable to handle the page fault gracefully.
290 */
291out_of_memory:
292 up_read(&mm->mmap_sem);
293 if (is_global_init(current)) {
294 yield();
295 down_read(&mm->mmap_sem);
296 goto survive;
297 }
298 printk("VM: killing process %s\n", current->comm);
299 if (user_mode(regs))
300 do_group_exit(SIGKILL);
301 return SIGKILL;
302
303do_sigbus:
304 up_read(&mm->mmap_sem);
305 info.si_signo = SIGBUS;
306 info.si_errno = 0;
307 info.si_code = BUS_ADRERR;
308 info.si_addr = (void __user *)address;
309 force_sig_info (SIGBUS, &info, current);
310 if (!user_mode(regs))
311 return SIGBUS;
312 return 0;
313}
314
315/*
316 * bad_page_fault is called when we have a bad access from the kernel.
317 * It is called from the DSI and ISI handlers in head.S and from some
318 * of the procedures in traps.c.
319 */
320void
321bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
322{
323 const struct exception_table_entry *entry;
324
325 /* Are we prepared to handle this fault? */
326 if ((entry = search_exception_tables(regs->nip)) != NULL) {
327 regs->nip = entry->fixup;
328 return;
329 }
330
331 /* kernel has accessed a bad area */
332#if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
333 if (debugger_kernel_faults)
334 debugger(regs);
335#endif
336 die("kernel access of bad area", regs, sig);
337}
338
339#ifdef CONFIG_8xx
340
341/* The pgtable.h claims some functions generically exist, but I
342 * can't find them......
343 */
344pte_t *va_to_pte(unsigned long address)
345{
346 pgd_t *dir;
347 pmd_t *pmd;
348 pte_t *pte;
349
350 if (address < TASK_SIZE)
351 return NULL;
352
353 dir = pgd_offset(&init_mm, address);
354 if (dir) {
355 pmd = pmd_offset(dir, address & PAGE_MASK);
356 if (pmd && pmd_present(*pmd)) {
357 pte = pte_offset_kernel(pmd, address & PAGE_MASK);
358 if (pte && pte_present(*pte))
359 return(pte);
360 }
361 }
362 return NULL;
363}
364
365unsigned long va_to_phys(unsigned long address)
366{
367 pte_t *pte;
368
369 pte = va_to_pte(address);
370 if (pte)
371 return(((unsigned long)(pte_val(*pte)) & PAGE_MASK) | (address & ~(PAGE_MASK)));
372 return (0);
373}
374
375void
376print_8xx_pte(struct mm_struct *mm, unsigned long addr)
377{
378 pgd_t * pgd;
379 pmd_t * pmd;
380 pte_t * pte;
381
382 printk(" pte @ 0x%8lx: ", addr);
383 pgd = pgd_offset(mm, addr & PAGE_MASK);
384 if (pgd) {
385 pmd = pmd_offset(pgd, addr & PAGE_MASK);
386 if (pmd && pmd_present(*pmd)) {
387 pte = pte_offset_kernel(pmd, addr & PAGE_MASK);
388 if (pte) {
389 printk(" (0x%08lx)->(0x%08lx)->0x%08lx\n",
390 (long)pgd, (long)pte, (long)pte_val(*pte));
391#define pp ((long)pte_val(*pte))
392 printk(" RPN: %05lx PP: %lx SPS: %lx SH: %lx "
393 "CI: %lx v: %lx\n",
394 pp>>12, /* rpn */
395 (pp>>10)&3, /* pp */
396 (pp>>3)&1, /* small */
397 (pp>>2)&1, /* shared */
398 (pp>>1)&1, /* cache inhibit */
399 pp&1 /* valid */
400 );
401#undef pp
402 }
403 else {
404 printk("no pte\n");
405 }
406 }
407 else {
408 printk("no pmd\n");
409 }
410 }
411 else {
412 printk("no pgd\n");
413 }
414}
415
416int
417get_8xx_pte(struct mm_struct *mm, unsigned long addr)
418{
419 pgd_t * pgd;
420 pmd_t * pmd;
421 pte_t * pte;
422 int retval = 0;
423
424 pgd = pgd_offset(mm, addr & PAGE_MASK);
425 if (pgd) {
426 pmd = pmd_offset(pgd, addr & PAGE_MASK);
427 if (pmd && pmd_present(*pmd)) {
428 pte = pte_offset_kernel(pmd, addr & PAGE_MASK);
429 if (pte) {
430 retval = (int)pte_val(*pte);
431 }
432 }
433 }
434 return(retval);
435}
436#endif /* CONFIG_8xx */
diff --git a/arch/ppc/mm/hashtable.S b/arch/ppc/mm/hashtable.S
deleted file mode 100644
index 5f364dc50154..000000000000
--- a/arch/ppc/mm/hashtable.S
+++ /dev/null
@@ -1,617 +0,0 @@
1/*
2 * $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $
3 *
4 * PowerPC version
5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6 * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
7 * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
8 * Adapted for Power Macintosh by Paul Mackerras.
9 * Low-level exception handlers and MMU support
10 * rewritten by Paul Mackerras.
11 * Copyright (C) 1996 Paul Mackerras.
12 *
13 * This file contains low-level assembler routines for managing
14 * the PowerPC MMU hash table. (PPC 8xx processors don't use a
15 * hash table, so this file is not used on them.)
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version
20 * 2 of the License, or (at your option) any later version.
21 *
22 */
23
24#include <asm/processor.h>
25#include <asm/page.h>
26#include <asm/pgtable.h>
27#include <asm/cputable.h>
28#include <asm/ppc_asm.h>
29#include <asm/thread_info.h>
30#include <asm/asm-offsets.h>
31
32#ifdef CONFIG_SMP
33 .section .bss
34 .align 2
35 .globl mmu_hash_lock
36mmu_hash_lock:
37 .space 4
38#endif /* CONFIG_SMP */
39
40/*
41 * Sync CPUs with hash_page taking & releasing the hash
42 * table lock
43 */
44#ifdef CONFIG_SMP
45 .text
46_GLOBAL(hash_page_sync)
47 lis r8,mmu_hash_lock@h
48 ori r8,r8,mmu_hash_lock@l
49 lis r0,0x0fff
50 b 10f
5111: lwz r6,0(r8)
52 cmpwi 0,r6,0
53 bne 11b
5410: lwarx r6,0,r8
55 cmpwi 0,r6,0
56 bne- 11b
57 stwcx. r0,0,r8
58 bne- 10b
59 isync
60 eieio
61 li r0,0
62 stw r0,0(r8)
63 blr
64#endif
65
66/*
67 * Load a PTE into the hash table, if possible.
68 * The address is in r4, and r3 contains an access flag:
69 * _PAGE_RW (0x400) if a write.
70 * r9 contains the SRR1 value, from which we use the MSR_PR bit.
71 * SPRG3 contains the physical address of the current task's thread.
72 *
73 * Returns to the caller if the access is illegal or there is no
74 * mapping for the address. Otherwise it places an appropriate PTE
75 * in the hash table and returns from the exception.
76 * Uses r0, r3 - r8, ctr, lr.
77 */
78 .text
79_GLOBAL(hash_page)
80 tophys(r7,0) /* gets -KERNELBASE into r7 */
81#ifdef CONFIG_SMP
82 addis r8,r7,mmu_hash_lock@h
83 ori r8,r8,mmu_hash_lock@l
84 lis r0,0x0fff
85 b 10f
8611: lwz r6,0(r8)
87 cmpwi 0,r6,0
88 bne 11b
8910: lwarx r6,0,r8
90 cmpwi 0,r6,0
91 bne- 11b
92 stwcx. r0,0,r8
93 bne- 10b
94 isync
95#endif
96 /* Get PTE (linux-style) and check access */
97 lis r0,KERNELBASE@h /* check if kernel address */
98 cmplw 0,r4,r0
99 mfspr r8,SPRN_SPRG3 /* current task's THREAD (phys) */
100 ori r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */
101 lwz r5,PGDIR(r8) /* virt page-table root */
102 blt+ 112f /* assume user more likely */
103 lis r5,swapper_pg_dir@ha /* if kernel address, use */
104 addi r5,r5,swapper_pg_dir@l /* kernel page table */
105 rlwimi r3,r9,32-12,29,29 /* MSR_PR -> _PAGE_USER */
106112: add r5,r5,r7 /* convert to phys addr */
107 rlwimi r5,r4,12,20,29 /* insert top 10 bits of address */
108 lwz r8,0(r5) /* get pmd entry */
109 rlwinm. r8,r8,0,0,19 /* extract address of pte page */
110#ifdef CONFIG_SMP
111 beq- hash_page_out /* return if no mapping */
112#else
113 /* XXX it seems like the 601 will give a machine fault on the
114 rfi if its alignment is wrong (bottom 4 bits of address are
115 8 or 0xc) and we have had a not-taken conditional branch
116 to the address following the rfi. */
117 beqlr-
118#endif
119 rlwimi r8,r4,22,20,29 /* insert next 10 bits of address */
120 rlwinm r0,r3,32-3,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */
121 ori r0,r0,_PAGE_ACCESSED|_PAGE_HASHPTE
122
123 /*
124 * Update the linux PTE atomically. We do the lwarx up-front
125 * because almost always, there won't be a permission violation
126 * and there won't already be an HPTE, and thus we will have
127 * to update the PTE to set _PAGE_HASHPTE. -- paulus.
128 */
129retry:
130 lwarx r6,0,r8 /* get linux-style pte */
131 andc. r5,r3,r6 /* check access & ~permission */
132#ifdef CONFIG_SMP
133 bne- hash_page_out /* return if access not permitted */
134#else
135 bnelr-
136#endif
137 or r5,r0,r6 /* set accessed/dirty bits */
138 stwcx. r5,0,r8 /* attempt to update PTE */
139 bne- retry /* retry if someone got there first */
140
141 mfsrin r3,r4 /* get segment reg for segment */
142 mfctr r0
143 stw r0,_CTR(r11)
144 bl create_hpte /* add the hash table entry */
145
146/*
147 * htab_reloads counts the number of times we have to fault an
148 * HPTE into the hash table. This should only happen after a
149 * fork (because fork does a flush_tlb_mm) or a vmalloc or ioremap.
150 * Where a page is faulted into a process's address space,
151 * update_mmu_cache gets called to put the HPTE into the hash table
152 * and those are counted as preloads rather than reloads.
153 */
154 addis r8,r7,htab_reloads@ha
155 lwz r3,htab_reloads@l(r8)
156 addi r3,r3,1
157 stw r3,htab_reloads@l(r8)
158
159#ifdef CONFIG_SMP
160 eieio
161 addis r8,r7,mmu_hash_lock@ha
162 li r0,0
163 stw r0,mmu_hash_lock@l(r8)
164#endif
165
166 /* Return from the exception */
167 lwz r5,_CTR(r11)
168 mtctr r5
169 lwz r0,GPR0(r11)
170 lwz r7,GPR7(r11)
171 lwz r8,GPR8(r11)
172 b fast_exception_return
173
174#ifdef CONFIG_SMP
175hash_page_out:
176 eieio
177 addis r8,r7,mmu_hash_lock@ha
178 li r0,0
179 stw r0,mmu_hash_lock@l(r8)
180 blr
181#endif /* CONFIG_SMP */
182
183/*
184 * Add an entry for a particular page to the hash table.
185 *
186 * add_hash_page(unsigned context, unsigned long va, unsigned long pmdval)
187 *
188 * We assume any necessary modifications to the pte (e.g. setting
189 * the accessed bit) have already been done and that there is actually
190 * a hash table in use (i.e. we're not on a 603).
191 */
192_GLOBAL(add_hash_page)
193 mflr r0
194 stw r0,4(r1)
195
196 /* Convert context and va to VSID */
197 mulli r3,r3,897*16 /* multiply context by context skew */
198 rlwinm r0,r4,4,28,31 /* get ESID (top 4 bits of va) */
199 mulli r0,r0,0x111 /* multiply by ESID skew */
200 add r3,r3,r0 /* note create_hpte trims to 24 bits */
201
202#ifdef CONFIG_SMP
203 rlwinm r8,r1,0,0,18 /* use cpu number to make tag */
204 lwz r8,TI_CPU(r8) /* to go in mmu_hash_lock */
205 oris r8,r8,12
206#endif /* CONFIG_SMP */
207
208 /*
209 * We disable interrupts here, even on UP, because we don't
210 * want to race with hash_page, and because we want the
211 * _PAGE_HASHPTE bit to be a reliable indication of whether
212 * the HPTE exists (or at least whether one did once).
213 * We also turn off the MMU for data accesses so that we
214 * we can't take a hash table miss (assuming the code is
215 * covered by a BAT). -- paulus
216 */
217 mfmsr r10
218 SYNC
219 rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
220 rlwinm r0,r0,0,28,26 /* clear MSR_DR */
221 mtmsr r0
222 SYNC_601
223 isync
224
225 tophys(r7,0)
226
227#ifdef CONFIG_SMP
228 addis r9,r7,mmu_hash_lock@ha
229 addi r9,r9,mmu_hash_lock@l
23010: lwarx r0,0,r9 /* take the mmu_hash_lock */
231 cmpi 0,r0,0
232 bne- 11f
233 stwcx. r8,0,r9
234 beq+ 12f
23511: lwz r0,0(r9)
236 cmpi 0,r0,0
237 beq 10b
238 b 11b
23912: isync
240#endif
241
242 /*
243 * Fetch the linux pte and test and set _PAGE_HASHPTE atomically.
244 * If _PAGE_HASHPTE was already set, we don't replace the existing
245 * HPTE, so we just unlock and return.
246 */
247 mr r8,r5
248 rlwimi r8,r4,22,20,29
2491: lwarx r6,0,r8
250 andi. r0,r6,_PAGE_HASHPTE
251 bne 9f /* if HASHPTE already set, done */
252 ori r5,r6,_PAGE_HASHPTE
253 stwcx. r5,0,r8
254 bne- 1b
255
256 bl create_hpte
257
258 addis r8,r7,htab_preloads@ha
259 lwz r3,htab_preloads@l(r8)
260 addi r3,r3,1
261 stw r3,htab_preloads@l(r8)
262
2639:
264#ifdef CONFIG_SMP
265 eieio
266 li r0,0
267 stw r0,0(r9) /* clear mmu_hash_lock */
268#endif
269
270 /* reenable interrupts and DR */
271 mtmsr r10
272 SYNC_601
273 isync
274
275 lwz r0,4(r1)
276 mtlr r0
277 blr
278
279/*
280 * This routine adds a hardware PTE to the hash table.
281 * It is designed to be called with the MMU either on or off.
282 * r3 contains the VSID, r4 contains the virtual address,
283 * r5 contains the linux PTE, r6 contains the old value of the
284 * linux PTE (before setting _PAGE_HASHPTE) and r7 contains the
285 * offset to be added to addresses (0 if the MMU is on,
286 * -KERNELBASE if it is off).
287 * On SMP, the caller should have the mmu_hash_lock held.
288 * We assume that the caller has (or will) set the _PAGE_HASHPTE
289 * bit in the linux PTE in memory. The value passed in r6 should
290 * be the old linux PTE value; if it doesn't have _PAGE_HASHPTE set
291 * this routine will skip the search for an existing HPTE.
292 * This procedure modifies r0, r3 - r6, r8, cr0.
293 * -- paulus.
294 *
295 * For speed, 4 of the instructions get patched once the size and
296 * physical address of the hash table are known. These definitions
297 * of Hash_base and Hash_bits below are just an example.
298 */
299Hash_base = 0xc0180000
300Hash_bits = 12 /* e.g. 256kB hash table */
301Hash_msk = (((1 << Hash_bits) - 1) * 64)
302
303/* defines for the PTE format for 32-bit PPCs */
304#define PTE_SIZE 8
305#define PTEG_SIZE 64
306#define LG_PTEG_SIZE 6
307#define LDPTEu lwzu
308#define STPTE stw
309#define CMPPTE cmpw
310#define PTE_H 0x40
311#define PTE_V 0x80000000
312#define TST_V(r) rlwinm. r,r,0,0,0
313#define SET_V(r) oris r,r,PTE_V@h
314#define CLR_V(r,t) rlwinm r,r,0,1,31
315
316#define HASH_LEFT 31-(LG_PTEG_SIZE+Hash_bits-1)
317#define HASH_RIGHT 31-LG_PTEG_SIZE
318
319_GLOBAL(create_hpte)
320 /* Convert linux-style PTE (r5) to low word of PPC-style PTE (r8) */
321 rlwinm r8,r5,32-10,31,31 /* _PAGE_RW -> PP lsb */
322 rlwinm r0,r5,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */
323 and r8,r8,r0 /* writable if _RW & _DIRTY */
324 rlwimi r5,r5,32-1,30,30 /* _PAGE_USER -> PP msb */
325 rlwimi r5,r5,32-2,31,31 /* _PAGE_USER -> PP lsb */
326 ori r8,r8,0xe14 /* clear out reserved bits and M */
327 andc r8,r5,r8 /* PP = user? (rw&dirty? 2: 3): 0 */
328BEGIN_FTR_SECTION
329 ori r8,r8,_PAGE_COHERENT /* set M (coherence required) */
330END_FTR_SECTION_IFSET(CPU_FTR_NEED_COHERENT)
331
332 /* Construct the high word of the PPC-style PTE (r5) */
333 rlwinm r5,r3,7,1,24 /* put VSID in 0x7fffff80 bits */
334 rlwimi r5,r4,10,26,31 /* put in API (abbrev page index) */
335 SET_V(r5) /* set V (valid) bit */
336
337 /* Get the address of the primary PTE group in the hash table (r3) */
338_GLOBAL(hash_page_patch_A)
339 addis r0,r7,Hash_base@h /* base address of hash table */
340 rlwimi r0,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* VSID -> hash */
341 rlwinm r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
342 xor r3,r3,r0 /* make primary hash */
343 li r0,8 /* PTEs/group */
344
345 /*
346 * Test the _PAGE_HASHPTE bit in the old linux PTE, and skip the search
347 * if it is clear, meaning that the HPTE isn't there already...
348 */
349 andi. r6,r6,_PAGE_HASHPTE
350 beq+ 10f /* no PTE: go look for an empty slot */
351 tlbie r4
352
353 addis r4,r7,htab_hash_searches@ha
354 lwz r6,htab_hash_searches@l(r4)
355 addi r6,r6,1 /* count how many searches we do */
356 stw r6,htab_hash_searches@l(r4)
357
358 /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
359 mtctr r0
360 addi r4,r3,-PTE_SIZE
3611: LDPTEu r6,PTE_SIZE(r4) /* get next PTE */
362 CMPPTE 0,r6,r5
363 bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */
364 beq+ found_slot
365
366 /* Search the secondary PTEG for a matching PTE */
367 ori r5,r5,PTE_H /* set H (secondary hash) bit */
368_GLOBAL(hash_page_patch_B)
369 xoris r4,r3,Hash_msk>>16 /* compute secondary hash */
370 xori r4,r4,(-PTEG_SIZE & 0xffff)
371 addi r4,r4,-PTE_SIZE
372 mtctr r0
3732: LDPTEu r6,PTE_SIZE(r4)
374 CMPPTE 0,r6,r5
375 bdnzf 2,2b
376 beq+ found_slot
377 xori r5,r5,PTE_H /* clear H bit again */
378
379 /* Search the primary PTEG for an empty slot */
38010: mtctr r0
381 addi r4,r3,-PTE_SIZE /* search primary PTEG */
3821: LDPTEu r6,PTE_SIZE(r4) /* get next PTE */
383 TST_V(r6) /* test valid bit */
384 bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */
385 beq+ found_empty
386
387 /* update counter of times that the primary PTEG is full */
388 addis r4,r7,primary_pteg_full@ha
389 lwz r6,primary_pteg_full@l(r4)
390 addi r6,r6,1
391 stw r6,primary_pteg_full@l(r4)
392
393 /* Search the secondary PTEG for an empty slot */
394 ori r5,r5,PTE_H /* set H (secondary hash) bit */
395_GLOBAL(hash_page_patch_C)
396 xoris r4,r3,Hash_msk>>16 /* compute secondary hash */
397 xori r4,r4,(-PTEG_SIZE & 0xffff)
398 addi r4,r4,-PTE_SIZE
399 mtctr r0
4002: LDPTEu r6,PTE_SIZE(r4)
401 TST_V(r6)
402 bdnzf 2,2b
403 beq+ found_empty
404 xori r5,r5,PTE_H /* clear H bit again */
405
406 /*
407 * Choose an arbitrary slot in the primary PTEG to overwrite.
408 * Since both the primary and secondary PTEGs are full, and we
409 * have no information that the PTEs in the primary PTEG are
410 * more important or useful than those in the secondary PTEG,
411 * and we know there is a definite (although small) speed
412 * advantage to putting the PTE in the primary PTEG, we always
413 * put the PTE in the primary PTEG.
414 */
415 addis r4,r7,next_slot@ha
416 lwz r6,next_slot@l(r4)
417 addi r6,r6,PTE_SIZE
418 andi. r6,r6,7*PTE_SIZE
419 stw r6,next_slot@l(r4)
420 add r4,r3,r6
421
422 /* update counter of evicted pages */
423 addis r6,r7,htab_evicts@ha
424 lwz r3,htab_evicts@l(r6)
425 addi r3,r3,1
426 stw r3,htab_evicts@l(r6)
427
428#ifndef CONFIG_SMP
429 /* Store PTE in PTEG */
430found_empty:
431 STPTE r5,0(r4)
432found_slot:
433 STPTE r8,PTE_SIZE/2(r4)
434
435#else /* CONFIG_SMP */
436/*
437 * Between the tlbie above and updating the hash table entry below,
438 * another CPU could read the hash table entry and put it in its TLB.
439 * There are 3 cases:
440 * 1. using an empty slot
441 * 2. updating an earlier entry to change permissions (i.e. enable write)
442 * 3. taking over the PTE for an unrelated address
443 *
444 * In each case it doesn't really matter if the other CPUs have the old
445 * PTE in their TLB. So we don't need to bother with another tlbie here,
446 * which is convenient as we've overwritten the register that had the
447 * address. :-) The tlbie above is mainly to make sure that this CPU comes
448 * and gets the new PTE from the hash table.
449 *
450 * We do however have to make sure that the PTE is never in an invalid
451 * state with the V bit set.
452 */
453found_empty:
454found_slot:
455 CLR_V(r5,r0) /* clear V (valid) bit in PTE */
456 STPTE r5,0(r4)
457 sync
458 TLBSYNC
459 STPTE r8,PTE_SIZE/2(r4) /* put in correct RPN, WIMG, PP bits */
460 sync
461 SET_V(r5)
462 STPTE r5,0(r4) /* finally set V bit in PTE */
463#endif /* CONFIG_SMP */
464
465 sync /* make sure pte updates get to memory */
466 blr
467
468 .section .bss
469 .align 2
470next_slot:
471 .space 4
472 .globl primary_pteg_full
473primary_pteg_full:
474 .space 4
475 .globl htab_hash_searches
476htab_hash_searches:
477 .space 4
478 .previous
479
480/*
481 * Flush the entry for a particular page from the hash table.
482 *
483 * flush_hash_pages(unsigned context, unsigned long va, unsigned long pmdval,
484 * int count)
485 *
486 * We assume that there is a hash table in use (Hash != 0).
487 */
488_GLOBAL(flush_hash_pages)
489 tophys(r7,0)
490
491 /*
492 * We disable interrupts here, even on UP, because we want
493 * the _PAGE_HASHPTE bit to be a reliable indication of
494 * whether the HPTE exists (or at least whether one did once).
495 * We also turn off the MMU for data accesses so that we
496 * we can't take a hash table miss (assuming the code is
497 * covered by a BAT). -- paulus
498 */
499 mfmsr r10
500 SYNC
501 rlwinm r0,r10,0,17,15 /* clear bit 16 (MSR_EE) */
502 rlwinm r0,r0,0,28,26 /* clear MSR_DR */
503 mtmsr r0
504 SYNC_601
505 isync
506
507 /* First find a PTE in the range that has _PAGE_HASHPTE set */
508 rlwimi r5,r4,22,20,29
5091: lwz r0,0(r5)
510 cmpwi cr1,r6,1
511 andi. r0,r0,_PAGE_HASHPTE
512 bne 2f
513 ble cr1,19f
514 addi r4,r4,0x1000
515 addi r5,r5,4
516 addi r6,r6,-1
517 b 1b
518
519 /* Convert context and va to VSID */
5202: mulli r3,r3,897*16 /* multiply context by context skew */
521 rlwinm r0,r4,4,28,31 /* get ESID (top 4 bits of va) */
522 mulli r0,r0,0x111 /* multiply by ESID skew */
523 add r3,r3,r0 /* note code below trims to 24 bits */
524
525 /* Construct the high word of the PPC-style PTE (r11) */
526 rlwinm r11,r3,7,1,24 /* put VSID in 0x7fffff80 bits */
527 rlwimi r11,r4,10,26,31 /* put in API (abbrev page index) */
528 SET_V(r11) /* set V (valid) bit */
529
530#ifdef CONFIG_SMP
531 addis r9,r7,mmu_hash_lock@ha
532 addi r9,r9,mmu_hash_lock@l
533 rlwinm r8,r1,0,0,18
534 add r8,r8,r7
535 lwz r8,TI_CPU(r8)
536 oris r8,r8,9
53710: lwarx r0,0,r9
538 cmpi 0,r0,0
539 bne- 11f
540 stwcx. r8,0,r9
541 beq+ 12f
54211: lwz r0,0(r9)
543 cmpi 0,r0,0
544 beq 10b
545 b 11b
54612: isync
547#endif
548
549 /*
550 * Check the _PAGE_HASHPTE bit in the linux PTE. If it is
551 * already clear, we're done (for this pte). If not,
552 * clear it (atomically) and proceed. -- paulus.
553 */
55433: lwarx r8,0,r5 /* fetch the pte */
555 andi. r0,r8,_PAGE_HASHPTE
556 beq 8f /* done if HASHPTE is already clear */
557 rlwinm r8,r8,0,31,29 /* clear HASHPTE bit */
558 stwcx. r8,0,r5 /* update the pte */
559 bne- 33b
560
561 /* Get the address of the primary PTE group in the hash table (r3) */
562_GLOBAL(flush_hash_patch_A)
563 addis r8,r7,Hash_base@h /* base address of hash table */
564 rlwimi r8,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* VSID -> hash */
565 rlwinm r0,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
566 xor r8,r0,r8 /* make primary hash */
567
568 /* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
569 li r0,8 /* PTEs/group */
570 mtctr r0
571 addi r12,r8,-PTE_SIZE
5721: LDPTEu r0,PTE_SIZE(r12) /* get next PTE */
573 CMPPTE 0,r0,r11
574 bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */
575 beq+ 3f
576
577 /* Search the secondary PTEG for a matching PTE */
578 ori r11,r11,PTE_H /* set H (secondary hash) bit */
579 li r0,8 /* PTEs/group */
580_GLOBAL(flush_hash_patch_B)
581 xoris r12,r8,Hash_msk>>16 /* compute secondary hash */
582 xori r12,r12,(-PTEG_SIZE & 0xffff)
583 addi r12,r12,-PTE_SIZE
584 mtctr r0
5852: LDPTEu r0,PTE_SIZE(r12)
586 CMPPTE 0,r0,r11
587 bdnzf 2,2b
588 xori r11,r11,PTE_H /* clear H again */
589 bne- 4f /* should rarely fail to find it */
590
5913: li r0,0
592 STPTE r0,0(r12) /* invalidate entry */
5934: sync
594 tlbie r4 /* in hw tlb too */
595 sync
596
5978: ble cr1,9f /* if all ptes checked */
59881: addi r6,r6,-1
599 addi r5,r5,4 /* advance to next pte */
600 addi r4,r4,0x1000
601 lwz r0,0(r5) /* check next pte */
602 cmpwi cr1,r6,1
603 andi. r0,r0,_PAGE_HASHPTE
604 bne 33b
605 bgt cr1,81b
606
6079:
608#ifdef CONFIG_SMP
609 TLBSYNC
610 li r0,0
611 stw r0,0(r9) /* clear mmu_hash_lock */
612#endif
613
61419: mtmsr r10
615 SYNC_601
616 isync
617 blr
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
deleted file mode 100644
index 1a63711081b5..000000000000
--- a/arch/ppc/mm/init.c
+++ /dev/null
@@ -1,603 +0,0 @@
1/*
2 * PowerPC version
3 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
4 *
5 * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
6 * and Cort Dougan (PReP) (cort@cs.nmt.edu)
7 * Copyright (C) 1996 Paul Mackerras
8 * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
9 * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com)
10 *
11 * Derived from "arch/i386/mm/init.c"
12 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version
17 * 2 of the License, or (at your option) any later version.
18 *
19 */
20
21#include <linux/module.h>
22#include <linux/sched.h>
23#include <linux/kernel.h>
24#include <linux/errno.h>
25#include <linux/string.h>
26#include <linux/types.h>
27#include <linux/mm.h>
28#include <linux/stddef.h>
29#include <linux/init.h>
30#include <linux/bootmem.h>
31#include <linux/highmem.h>
32#include <linux/initrd.h>
33#include <linux/pagemap.h>
34
35#include <asm/pgalloc.h>
36#include <asm/prom.h>
37#include <asm/io.h>
38#include <asm/mmu_context.h>
39#include <asm/pgtable.h>
40#include <asm/mmu.h>
41#include <asm/smp.h>
42#include <asm/machdep.h>
43#include <asm/btext.h>
44#include <asm/tlb.h>
45#include <asm/bootinfo.h>
46
47#include "mem_pieces.h"
48#include "mmu_decl.h"
49
50#if defined(CONFIG_KERNEL_START_BOOL) || defined(CONFIG_LOWMEM_SIZE_BOOL)
51/* The amount of lowmem must be within 0xF0000000 - KERNELBASE. */
52#if (CONFIG_LOWMEM_SIZE > (0xF0000000 - KERNELBASE))
53#error "You must adjust CONFIG_LOWMEM_SIZE or CONFIG_START_KERNEL"
54#endif
55#endif
56#define MAX_LOW_MEM CONFIG_LOWMEM_SIZE
57
58DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
59
60unsigned long total_memory;
61unsigned long total_lowmem;
62
63unsigned long ppc_memstart;
64unsigned long ppc_memoffset = PAGE_OFFSET;
65
66int mem_init_done;
67int init_bootmem_done;
68int boot_mapsize;
69
70extern char _end[];
71extern char etext[], _stext[];
72extern char __init_begin, __init_end;
73
74#ifdef CONFIG_HIGHMEM
75pte_t *kmap_pte;
76pgprot_t kmap_prot;
77
78EXPORT_SYMBOL(kmap_prot);
79EXPORT_SYMBOL(kmap_pte);
80#endif
81
82void MMU_init(void);
83void set_phys_avail(unsigned long total_ram);
84
85/* XXX should be in current.h -- paulus */
86extern struct task_struct *current_set[NR_CPUS];
87
88char *klimit = _end;
89struct mem_pieces phys_avail;
90
91/*
92 * this tells the system to map all of ram with the segregs
93 * (i.e. page tables) instead of the bats.
94 * -- Cort
95 */
96int __map_without_bats;
97int __map_without_ltlbs;
98
99/* max amount of RAM to use */
100unsigned long __max_memory;
101/* max amount of low RAM to map in */
102unsigned long __max_low_memory = MAX_LOW_MEM;
103
104void show_mem(void)
105{
106 int i,free = 0,total = 0,reserved = 0;
107 int shared = 0, cached = 0;
108 int highmem = 0;
109
110 printk("Mem-info:\n");
111 show_free_areas();
112 i = max_mapnr;
113 while (i-- > 0) {
114 total++;
115 if (PageHighMem(mem_map+i))
116 highmem++;
117 if (PageReserved(mem_map+i))
118 reserved++;
119 else if (PageSwapCache(mem_map+i))
120 cached++;
121 else if (!page_count(mem_map+i))
122 free++;
123 else
124 shared += page_count(mem_map+i) - 1;
125 }
126 printk("%d pages of RAM\n",total);
127 printk("%d pages of HIGHMEM\n", highmem);
128 printk("%d free pages\n",free);
129 printk("%d reserved pages\n",reserved);
130 printk("%d pages shared\n",shared);
131 printk("%d pages swap cached\n",cached);
132}
133
134/* Free up now-unused memory */
135static void free_sec(unsigned long start, unsigned long end, const char *name)
136{
137 unsigned long cnt = 0;
138
139 while (start < end) {
140 ClearPageReserved(virt_to_page(start));
141 init_page_count(virt_to_page(start));
142 free_page(start);
143 cnt++;
144 start += PAGE_SIZE;
145 }
146 if (cnt) {
147 printk(" %ldk %s", cnt << (PAGE_SHIFT - 10), name);
148 totalram_pages += cnt;
149 }
150}
151
152void free_initmem(void)
153{
154#define FREESEC(TYPE) \
155 free_sec((unsigned long)(&__ ## TYPE ## _begin), \
156 (unsigned long)(&__ ## TYPE ## _end), \
157 #TYPE);
158
159 printk ("Freeing unused kernel memory:");
160 FREESEC(init);
161 printk("\n");
162 ppc_md.progress = NULL;
163#undef FREESEC
164}
165
166#ifdef CONFIG_BLK_DEV_INITRD
167void free_initrd_mem(unsigned long start, unsigned long end)
168{
169 printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
170
171 for (; start < end; start += PAGE_SIZE) {
172 ClearPageReserved(virt_to_page(start));
173 init_page_count(virt_to_page(start));
174 free_page(start);
175 totalram_pages++;
176 }
177}
178#endif
179
180/*
181 * Check for command-line options that affect what MMU_init will do.
182 */
183void MMU_setup(void)
184{
185 /* Check for nobats option (used in mapin_ram). */
186 if (strstr(cmd_line, "nobats")) {
187 __map_without_bats = 1;
188 }
189
190 if (strstr(cmd_line, "noltlbs")) {
191 __map_without_ltlbs = 1;
192 }
193
194 /* Look for mem= option on command line */
195 if (strstr(cmd_line, "mem=")) {
196 char *p, *q;
197 unsigned long maxmem = 0;
198
199 for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
200 q = p + 4;
201 if (p > cmd_line && p[-1] != ' ')
202 continue;
203 maxmem = simple_strtoul(q, &q, 0);
204 if (*q == 'k' || *q == 'K') {
205 maxmem <<= 10;
206 ++q;
207 } else if (*q == 'm' || *q == 'M') {
208 maxmem <<= 20;
209 ++q;
210 }
211 }
212 __max_memory = maxmem;
213 }
214}
215
216/*
217 * MMU_init sets up the basic memory mappings for the kernel,
218 * including both RAM and possibly some I/O regions,
219 * and sets up the page tables and the MMU hardware ready to go.
220 */
221void __init MMU_init(void)
222{
223 if (ppc_md.progress)
224 ppc_md.progress("MMU:enter", 0x111);
225
226 /* parse args from command line */
227 MMU_setup();
228
229 /*
230 * Figure out how much memory we have, how much
231 * is lowmem, and how much is highmem. If we were
232 * passed the total memory size from the bootloader,
233 * just use it.
234 */
235 if (boot_mem_size)
236 total_memory = boot_mem_size;
237 else
238 total_memory = ppc_md.find_end_of_memory();
239
240 if (__max_memory && total_memory > __max_memory)
241 total_memory = __max_memory;
242 total_lowmem = total_memory;
243 if (total_lowmem > __max_low_memory) {
244 total_lowmem = __max_low_memory;
245#ifndef CONFIG_HIGHMEM
246 total_memory = total_lowmem;
247#endif /* CONFIG_HIGHMEM */
248 }
249 set_phys_avail(total_lowmem);
250
251 /* Initialize the MMU hardware */
252 if (ppc_md.progress)
253 ppc_md.progress("MMU:hw init", 0x300);
254 MMU_init_hw();
255
256 /* Map in all of RAM starting at KERNELBASE */
257 if (ppc_md.progress)
258 ppc_md.progress("MMU:mapin", 0x301);
259 mapin_ram();
260
261#ifdef CONFIG_HIGHMEM
262 ioremap_base = PKMAP_BASE;
263#else
264 ioremap_base = 0xfe000000UL; /* for now, could be 0xfffff000 */
265#endif /* CONFIG_HIGHMEM */
266 ioremap_bot = ioremap_base;
267
268 /* Map in I/O resources */
269 if (ppc_md.progress)
270 ppc_md.progress("MMU:setio", 0x302);
271 if (ppc_md.setup_io_mappings)
272 ppc_md.setup_io_mappings();
273
274 /* Initialize the context management stuff */
275 mmu_context_init();
276
277 if (ppc_md.progress)
278 ppc_md.progress("MMU:exit", 0x211);
279
280#ifdef CONFIG_BOOTX_TEXT
281 /* By default, we are no longer mapped */
282 boot_text_mapped = 0;
283 /* Must be done last, or ppc_md.progress will die. */
284 map_boot_text();
285#endif
286}
287
288/* This is only called until mem_init is done. */
289void __init *early_get_page(void)
290{
291 void *p;
292
293 if (init_bootmem_done) {
294 p = alloc_bootmem_pages(PAGE_SIZE);
295 } else {
296 p = mem_pieces_find(PAGE_SIZE, PAGE_SIZE);
297 }
298 return p;
299}
300
301/*
302 * Initialize the bootmem system and give it all the memory we
303 * have available.
304 */
305void __init do_init_bootmem(void)
306{
307 unsigned long start, size;
308 int i;
309
310 /*
311 * Find an area to use for the bootmem bitmap.
312 * We look for the first area which is at least
313 * 128kB in length (128kB is enough for a bitmap
314 * for 4GB of memory, using 4kB pages), plus 1 page
315 * (in case the address isn't page-aligned).
316 */
317 start = 0;
318 size = 0;
319 for (i = 0; i < phys_avail.n_regions; ++i) {
320 unsigned long a = phys_avail.regions[i].address;
321 unsigned long s = phys_avail.regions[i].size;
322 if (s <= size)
323 continue;
324 start = a;
325 size = s;
326 if (s >= 33 * PAGE_SIZE)
327 break;
328 }
329 start = PAGE_ALIGN(start);
330
331 min_low_pfn = start >> PAGE_SHIFT;
332 max_low_pfn = (PPC_MEMSTART + total_lowmem) >> PAGE_SHIFT;
333 max_pfn = (PPC_MEMSTART + total_memory) >> PAGE_SHIFT;
334 boot_mapsize = init_bootmem_node(&contig_page_data, min_low_pfn,
335 PPC_MEMSTART >> PAGE_SHIFT,
336 max_low_pfn);
337
338 /* remove the bootmem bitmap from the available memory */
339 mem_pieces_remove(&phys_avail, start, boot_mapsize, 1);
340
341 /* add everything in phys_avail into the bootmem map */
342 for (i = 0; i < phys_avail.n_regions; ++i)
343 free_bootmem(phys_avail.regions[i].address,
344 phys_avail.regions[i].size);
345
346 init_bootmem_done = 1;
347}
348
349/*
350 * paging_init() sets up the page tables - in fact we've already done this.
351 */
352void __init paging_init(void)
353{
354 unsigned long start_pfn, end_pfn;
355 unsigned long max_zone_pfns[MAX_NR_ZONES];
356#ifdef CONFIG_HIGHMEM
357 map_page(PKMAP_BASE, 0, 0); /* XXX gross */
358 pkmap_page_table = pte_offset_kernel(pmd_offset(pgd_offset_k
359 (PKMAP_BASE), PKMAP_BASE), PKMAP_BASE);
360 map_page(KMAP_FIX_BEGIN, 0, 0); /* XXX gross */
361 kmap_pte = pte_offset_kernel(pmd_offset(pgd_offset_k
362 (KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN);
363 kmap_prot = PAGE_KERNEL;
364#endif /* CONFIG_HIGHMEM */
365 /* All pages are DMA-able so we put them all in the DMA zone. */
366 start_pfn = __pa(PAGE_OFFSET) >> PAGE_SHIFT;
367 end_pfn = start_pfn + (total_memory >> PAGE_SHIFT);
368 add_active_range(0, start_pfn, end_pfn);
369
370 memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
371#ifdef CONFIG_HIGHMEM
372 max_zone_pfns[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
373 max_zone_pfns[ZONE_HIGHMEM] = total_memory >> PAGE_SHIFT;
374#else
375 max_zone_pfns[ZONE_DMA] = total_memory >> PAGE_SHIFT;
376#endif /* CONFIG_HIGHMEM */
377 free_area_init_nodes(max_zone_pfns);
378}
379
380void __init mem_init(void)
381{
382 unsigned long addr;
383 int codepages = 0;
384 int datapages = 0;
385 int initpages = 0;
386#ifdef CONFIG_HIGHMEM
387 unsigned long highmem_mapnr;
388
389 highmem_mapnr = total_lowmem >> PAGE_SHIFT;
390#endif /* CONFIG_HIGHMEM */
391 max_mapnr = total_memory >> PAGE_SHIFT;
392
393 high_memory = (void *) __va(PPC_MEMSTART + total_lowmem);
394 num_physpages = max_mapnr; /* RAM is assumed contiguous */
395
396 totalram_pages += free_all_bootmem();
397
398#ifdef CONFIG_BLK_DEV_INITRD
399 /* if we are booted from BootX with an initial ramdisk,
400 make sure the ramdisk pages aren't reserved. */
401 if (initrd_start) {
402 for (addr = initrd_start; addr < initrd_end; addr += PAGE_SIZE)
403 ClearPageReserved(virt_to_page(addr));
404 }
405#endif /* CONFIG_BLK_DEV_INITRD */
406
407 for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory;
408 addr += PAGE_SIZE) {
409 if (!PageReserved(virt_to_page(addr)))
410 continue;
411 if (addr < (ulong) etext)
412 codepages++;
413 else if (addr >= (unsigned long)&__init_begin
414 && addr < (unsigned long)&__init_end)
415 initpages++;
416 else if (addr < (ulong) klimit)
417 datapages++;
418 }
419
420#ifdef CONFIG_HIGHMEM
421 {
422 unsigned long pfn;
423
424 for (pfn = highmem_mapnr; pfn < max_mapnr; ++pfn) {
425 struct page *page = mem_map + pfn;
426
427 ClearPageReserved(page);
428 init_page_count(page);
429 __free_page(page);
430 totalhigh_pages++;
431 }
432 totalram_pages += totalhigh_pages;
433 }
434#endif /* CONFIG_HIGHMEM */
435
436 printk("Memory: %luk available (%dk kernel code, %dk data, %dk init, %ldk highmem)\n",
437 (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10),
438 codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
439 initpages<< (PAGE_SHIFT-10),
440 (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
441
442 mem_init_done = 1;
443}
444
445/*
446 * Set phys_avail to the amount of physical memory,
447 * less the kernel text/data/bss.
448 */
449void __init
450set_phys_avail(unsigned long total_memory)
451{
452 unsigned long kstart, ksize;
453
454 /*
455 * Initially, available physical memory is equivalent to all
456 * physical memory.
457 */
458
459 phys_avail.regions[0].address = PPC_MEMSTART;
460 phys_avail.regions[0].size = total_memory;
461 phys_avail.n_regions = 1;
462
463 /*
464 * Map out the kernel text/data/bss from the available physical
465 * memory.
466 */
467
468 kstart = __pa(_stext); /* should be 0 */
469 ksize = PAGE_ALIGN(klimit - _stext);
470
471 mem_pieces_remove(&phys_avail, kstart, ksize, 0);
472 mem_pieces_remove(&phys_avail, 0, 0x4000, 0);
473
474#if defined(CONFIG_BLK_DEV_INITRD)
475 /* Remove the init RAM disk from the available memory. */
476 if (initrd_start) {
477 mem_pieces_remove(&phys_avail, __pa(initrd_start),
478 initrd_end - initrd_start, 1);
479 }
480#endif /* CONFIG_BLK_DEV_INITRD */
481}
482
483/* Mark some memory as reserved by removing it from phys_avail. */
484void __init reserve_phys_mem(unsigned long start, unsigned long size)
485{
486 mem_pieces_remove(&phys_avail, start, size, 1);
487}
488
489/*
490 * This is called when a page has been modified by the kernel.
491 * It just marks the page as not i-cache clean. We do the i-cache
492 * flush later when the page is given to a user process, if necessary.
493 */
494void flush_dcache_page(struct page *page)
495{
496 clear_bit(PG_arch_1, &page->flags);
497}
498
499void flush_dcache_icache_page(struct page *page)
500{
501#ifdef CONFIG_BOOKE
502 void *start = kmap_atomic(page, KM_PPC_SYNC_ICACHE);
503 __flush_dcache_icache(start);
504 kunmap_atomic(start, KM_PPC_SYNC_ICACHE);
505#elif defined(CONFIG_8xx)
506 /* On 8xx there is no need to kmap since highmem is not supported */
507 __flush_dcache_icache(page_address(page));
508#else
509 __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT);
510#endif
511
512}
513void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
514{
515 clear_page(page);
516 clear_bit(PG_arch_1, &pg->flags);
517}
518
519void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
520 struct page *pg)
521{
522 copy_page(vto, vfrom);
523 clear_bit(PG_arch_1, &pg->flags);
524}
525
526void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
527 unsigned long addr, int len)
528{
529 unsigned long maddr;
530
531 maddr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK);
532 flush_icache_range(maddr, maddr + len);
533 kunmap(page);
534}
535
536/*
537 * This is called at the end of handling a user page fault, when the
538 * fault has been handled by updating a PTE in the linux page tables.
539 * We use it to preload an HPTE into the hash table corresponding to
540 * the updated linux PTE.
541 */
542void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
543 pte_t pte)
544{
545 /* handle i-cache coherency */
546 unsigned long pfn = pte_pfn(pte);
547
548 if (pfn_valid(pfn)) {
549 struct page *page = pfn_to_page(pfn);
550#ifdef CONFIG_8xx
551 /* On 8xx, the TLB handlers work in 2 stages:
552 * First, a zeroed entry is loaded by TLBMiss handler,
553 * which causes the TLBError handler to be triggered.
554 * That means the zeroed TLB has to be invalidated
555 * whenever a page miss occurs.
556 */
557 _tlbie(address, 0 /* 8xx doesn't care about PID */);
558#endif
559 if (!PageReserved(page)
560 && !test_bit(PG_arch_1, &page->flags)) {
561 if (vma->vm_mm == current->active_mm)
562 __flush_dcache_icache((void *) address);
563 else
564 flush_dcache_icache_page(page);
565 set_bit(PG_arch_1, &page->flags);
566 }
567 }
568
569#ifdef CONFIG_PPC_STD_MMU
570 /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */
571 if (Hash != 0 && pte_young(pte)) {
572 struct mm_struct *mm;
573 pmd_t *pmd;
574
575 mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm;
576 pmd = pmd_offset(pgd_offset(mm, address), address);
577 if (!pmd_none(*pmd))
578 add_hash_page(mm->context.id, address, pmd_val(*pmd));
579 }
580#endif
581}
582
583/*
584 * This is called by /dev/mem to know if a given address has to
585 * be mapped non-cacheable or not
586 */
587int page_is_ram(unsigned long pfn)
588{
589 return pfn < max_pfn;
590}
591
592pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
593 unsigned long size, pgprot_t vma_prot)
594{
595 if (ppc_md.phys_mem_access_prot)
596 return ppc_md.phys_mem_access_prot(file, pfn, size, vma_prot);
597
598 if (!page_is_ram(pfn))
599 vma_prot = __pgprot(pgprot_val(vma_prot)
600 | _PAGE_GUARDED | _PAGE_NO_CACHE);
601 return vma_prot;
602}
603EXPORT_SYMBOL(phys_mem_access_prot);
diff --git a/arch/ppc/mm/mem_pieces.c b/arch/ppc/mm/mem_pieces.c
deleted file mode 100644
index 6030a0ddfbb4..000000000000
--- a/arch/ppc/mm/mem_pieces.c
+++ /dev/null
@@ -1,162 +0,0 @@
1/*
2 * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
3 * Changes to accommodate Power Macintoshes.
4 * Cort Dougan <cort@cs.nmt.edu>
5 * Rewrites.
6 * Grant Erickson <grant@lcse.umn.edu>
7 * General rework and split from mm/init.c.
8 *
9 * Module name: mem_pieces.c
10 *
11 * Description:
12 * Routines and data structures for manipulating and representing
13 * phyiscal memory extents (i.e. address/length pairs).
14 *
15 */
16
17#include <linux/kernel.h>
18#include <linux/stddef.h>
19#include <linux/init.h>
20#include <asm/page.h>
21
22#include "mem_pieces.h"
23
24extern struct mem_pieces phys_avail;
25
26static void mem_pieces_print(struct mem_pieces *);
27
28/*
29 * Scan a region for a piece of a given size with the required alignment.
30 */
31void __init *
32mem_pieces_find(unsigned int size, unsigned int align)
33{
34 int i;
35 unsigned a, e;
36 struct mem_pieces *mp = &phys_avail;
37
38 for (i = 0; i < mp->n_regions; ++i) {
39 a = mp->regions[i].address;
40 e = a + mp->regions[i].size;
41 a = (a + align - 1) & -align;
42 if (a + size <= e) {
43 mem_pieces_remove(mp, a, size, 1);
44 return (void *) __va(a);
45 }
46 }
47 panic("Couldn't find %u bytes at %u alignment\n", size, align);
48
49 return NULL;
50}
51
52/*
53 * Remove some memory from an array of pieces
54 */
55void __init
56mem_pieces_remove(struct mem_pieces *mp, unsigned int start, unsigned int size,
57 int must_exist)
58{
59 int i, j;
60 unsigned int end, rs, re;
61 struct reg_property *rp;
62
63 end = start + size;
64 for (i = 0, rp = mp->regions; i < mp->n_regions; ++i, ++rp) {
65 if (end > rp->address && start < rp->address + rp->size)
66 break;
67 }
68 if (i >= mp->n_regions) {
69 if (must_exist)
70 printk("mem_pieces_remove: [%x,%x) not in any region\n",
71 start, end);
72 return;
73 }
74 for (; i < mp->n_regions && end > rp->address; ++i, ++rp) {
75 rs = rp->address;
76 re = rs + rp->size;
77 if (must_exist && (start < rs || end > re)) {
78 printk("mem_pieces_remove: bad overlap [%x,%x) with",
79 start, end);
80 mem_pieces_print(mp);
81 must_exist = 0;
82 }
83 if (start > rs) {
84 rp->size = start - rs;
85 if (end < re) {
86 /* need to split this entry */
87 if (mp->n_regions >= MEM_PIECES_MAX)
88 panic("eek... mem_pieces overflow");
89 for (j = mp->n_regions; j > i + 1; --j)
90 mp->regions[j] = mp->regions[j-1];
91 ++mp->n_regions;
92 rp[1].address = end;
93 rp[1].size = re - end;
94 }
95 } else {
96 if (end < re) {
97 rp->address = end;
98 rp->size = re - end;
99 } else {
100 /* need to delete this entry */
101 for (j = i; j < mp->n_regions - 1; ++j)
102 mp->regions[j] = mp->regions[j+1];
103 --mp->n_regions;
104 --i;
105 --rp;
106 }
107 }
108 }
109}
110
111static void __init
112mem_pieces_print(struct mem_pieces *mp)
113{
114 int i;
115
116 for (i = 0; i < mp->n_regions; ++i)
117 printk(" [%x, %x)", mp->regions[i].address,
118 mp->regions[i].address + mp->regions[i].size);
119 printk("\n");
120}
121
122void __init
123mem_pieces_sort(struct mem_pieces *mp)
124{
125 unsigned long a, s;
126 int i, j;
127
128 for (i = 1; i < mp->n_regions; ++i) {
129 a = mp->regions[i].address;
130 s = mp->regions[i].size;
131 for (j = i - 1; j >= 0; --j) {
132 if (a >= mp->regions[j].address)
133 break;
134 mp->regions[j+1] = mp->regions[j];
135 }
136 mp->regions[j+1].address = a;
137 mp->regions[j+1].size = s;
138 }
139}
140
141void __init
142mem_pieces_coalesce(struct mem_pieces *mp)
143{
144 unsigned long a, s, ns;
145 int i, j, d;
146
147 d = 0;
148 for (i = 0; i < mp->n_regions; i = j) {
149 a = mp->regions[i].address;
150 s = mp->regions[i].size;
151 for (j = i + 1; j < mp->n_regions
152 && mp->regions[j].address - a <= s; ++j) {
153 ns = mp->regions[j].address + mp->regions[j].size - a;
154 if (ns > s)
155 s = ns;
156 }
157 mp->regions[d].address = a;
158 mp->regions[d].size = s;
159 ++d;
160 }
161 mp->n_regions = d;
162}
diff --git a/arch/ppc/mm/mem_pieces.h b/arch/ppc/mm/mem_pieces.h
deleted file mode 100644
index e2b700dc7f18..000000000000
--- a/arch/ppc/mm/mem_pieces.h
+++ /dev/null
@@ -1,48 +0,0 @@
1/*
2 * Copyright (c) 1996 Paul Mackerras <paulus@cs.anu.edu.au>
3 * Changes to accommodate Power Macintoshes.
4 * Cort Dougan <cort@cs.nmt.edu>
5 * Rewrites.
6 * Grant Erickson <grant@lcse.umn.edu>
7 * General rework and split from mm/init.c.
8 *
9 * Module name: mem_pieces.h
10 *
11 * Description:
12 * Routines and data structures for manipulating and representing
13 * phyiscal memory extents (i.e. address/length pairs).
14 *
15 */
16
17#ifndef __MEM_PIECES_H__
18#define __MEM_PIECES_H__
19
20#include <asm/prom.h>
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26
27/* Type Definitions */
28
29#define MEM_PIECES_MAX 32
30
31struct mem_pieces {
32 int n_regions;
33 struct reg_property regions[MEM_PIECES_MAX];
34};
35
36/* Function Prototypes */
37
38extern void *mem_pieces_find(unsigned int size, unsigned int align);
39extern void mem_pieces_remove(struct mem_pieces *mp, unsigned int start,
40 unsigned int size, int must_exist);
41extern void mem_pieces_coalesce(struct mem_pieces *mp);
42extern void mem_pieces_sort(struct mem_pieces *mp);
43
44#ifdef __cplusplus
45}
46#endif
47
48#endif /* __MEM_PIECES_H__ */
diff --git a/arch/ppc/mm/mmu_context.c b/arch/ppc/mm/mmu_context.c
deleted file mode 100644
index dacf45ced473..000000000000
--- a/arch/ppc/mm/mmu_context.c
+++ /dev/null
@@ -1,85 +0,0 @@
1/*
2 * This file contains the routines for handling the MMU on those
3 * PowerPC implementations where the MMU substantially follows the
4 * architecture specification. This includes the 6xx, 7xx, 7xxx,
5 * and 8260 implementations but excludes the 8xx and 4xx.
6 * -- paulus
7 *
8 * Derived from arch/ppc/mm/init.c:
9 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
10 *
11 * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
12 * and Cort Dougan (PReP) (cort@cs.nmt.edu)
13 * Copyright (C) 1996 Paul Mackerras
14 * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
15 *
16 * Derived from "arch/i386/mm/init.c"
17 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
18 *
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version
22 * 2 of the License, or (at your option) any later version.
23 *
24 */
25
26#include <linux/mm.h>
27#include <linux/init.h>
28
29#include <asm/mmu_context.h>
30#include <asm/tlbflush.h>
31
32unsigned long next_mmu_context;
33unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
34#ifdef FEW_CONTEXTS
35atomic_t nr_free_contexts;
36struct mm_struct *context_mm[LAST_CONTEXT+1];
37void steal_context(void);
38#endif /* FEW_CONTEXTS */
39
40/*
41 * Initialize the context management stuff.
42 */
43void __init
44mmu_context_init(void)
45{
46 /*
47 * Some processors have too few contexts to reserve one for
48 * init_mm, and require using context 0 for a normal task.
49 * Other processors reserve the use of context zero for the kernel.
50 * This code assumes FIRST_CONTEXT < 32.
51 */
52 context_map[0] = (1 << FIRST_CONTEXT) - 1;
53 next_mmu_context = FIRST_CONTEXT;
54#ifdef FEW_CONTEXTS
55 atomic_set(&nr_free_contexts, LAST_CONTEXT - FIRST_CONTEXT + 1);
56#endif /* FEW_CONTEXTS */
57}
58
59#ifdef FEW_CONTEXTS
60/*
61 * Steal a context from a task that has one at the moment.
62 * This is only used on 8xx and 4xx and we presently assume that
63 * they don't do SMP. If they do then this will have to check
64 * whether the MM we steal is in use.
65 * We also assume that this is only used on systems that don't
66 * use an MMU hash table - this is true for 8xx and 4xx.
67 * This isn't an LRU system, it just frees up each context in
68 * turn (sort-of pseudo-random replacement :). This would be the
69 * place to implement an LRU scheme if anyone was motivated to do it.
70 * -- paulus
71 */
72void
73steal_context(void)
74{
75 struct mm_struct *mm;
76
77 /* free up context `next_mmu_context' */
78 /* if we shouldn't free context 0, don't... */
79 if (next_mmu_context < FIRST_CONTEXT)
80 next_mmu_context = FIRST_CONTEXT;
81 mm = context_mm[next_mmu_context];
82 flush_tlb_mm(mm);
83 destroy_context(mm);
84}
85#endif /* FEW_CONTEXTS */
diff --git a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h
deleted file mode 100644
index 5f813e386b87..000000000000
--- a/arch/ppc/mm/mmu_decl.h
+++ /dev/null
@@ -1,79 +0,0 @@
1/*
2 * Declarations of procedures and variables shared between files
3 * in arch/ppc/mm/.
4 *
5 * Derived from arch/ppc/mm/init.c:
6 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
7 *
8 * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
9 * and Cort Dougan (PReP) (cort@cs.nmt.edu)
10 * Copyright (C) 1996 Paul Mackerras
11 * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
12 *
13 * Derived from "arch/i386/mm/init.c"
14 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version
19 * 2 of the License, or (at your option) any later version.
20 *
21 */
22#include <asm/tlbflush.h>
23#include <asm/mmu.h>
24
25extern void mapin_ram(void);
26extern int map_page(unsigned long va, phys_addr_t pa, int flags);
27extern void setbat(int index, unsigned long virt, unsigned long phys,
28 unsigned int size, int flags);
29extern void reserve_phys_mem(unsigned long start, unsigned long size);
30extern void settlbcam(int index, unsigned long virt, phys_addr_t phys,
31 unsigned int size, int flags, unsigned int pid);
32extern void invalidate_tlbcam_entry(int index);
33
34extern int __map_without_bats;
35extern unsigned long ioremap_base;
36extern unsigned long ioremap_bot;
37extern unsigned int rtas_data, rtas_size;
38
39extern unsigned long total_memory;
40extern unsigned long total_lowmem;
41extern int mem_init_done;
42
43extern PTE *Hash, *Hash_end;
44extern unsigned long Hash_size, Hash_mask;
45
46extern unsigned int num_tlbcam_entries;
47
48/* ...and now those things that may be slightly different between processor
49 * architectures. -- Dan
50 */
51#if defined(CONFIG_8xx)
52#define flush_HPTE(X, va, pg) _tlbie(va, 0 /* 8xx doesn't care about PID */)
53#define MMU_init_hw() do { } while(0)
54#define mmu_mapin_ram() (0UL)
55
56#elif defined(CONFIG_4xx)
57#define flush_HPTE(pid, va, pg) _tlbie(va, pid)
58extern void MMU_init_hw(void);
59extern unsigned long mmu_mapin_ram(void);
60
61#else
62/* anything except 4xx or 8xx */
63extern void MMU_init_hw(void);
64extern unsigned long mmu_mapin_ram(void);
65
66/* Be careful....this needs to be updated if we ever encounter 603 SMPs,
67 * which includes all new 82xx processors. We need tlbie/tlbsync here
68 * in that case (I think). -- Dan.
69 */
70static inline void flush_HPTE(unsigned context, unsigned long va,
71 unsigned long pdval)
72{
73 if ((Hash != 0) &&
74 cpu_has_feature(CPU_FTR_HPTE_TABLE))
75 flush_hash_pages(0, va, pdval, 1);
76 else
77 _tlbie(va);
78}
79#endif
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
deleted file mode 100644
index 03a79bff1271..000000000000
--- a/arch/ppc/mm/pgtable.c
+++ /dev/null
@@ -1,403 +0,0 @@
1/*
2 * This file contains the routines setting up the linux page tables.
3 * -- paulus
4 *
5 * Derived from arch/ppc/mm/init.c:
6 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
7 *
8 * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
9 * and Cort Dougan (PReP) (cort@cs.nmt.edu)
10 * Copyright (C) 1996 Paul Mackerras
11 * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
12 *
13 * Derived from "arch/i386/mm/init.c"
14 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version
19 * 2 of the License, or (at your option) any later version.
20 *
21 */
22
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/types.h>
26#include <linux/mm.h>
27#include <linux/vmalloc.h>
28#include <linux/init.h>
29#include <linux/highmem.h>
30
31#include <asm/pgtable.h>
32#include <asm/pgalloc.h>
33#include <asm/io.h>
34
35#include "mmu_decl.h"
36
37unsigned long ioremap_base;
38unsigned long ioremap_bot;
39int io_bat_index;
40
41#if defined(CONFIG_6xx)
42#define HAVE_BATS 1
43#endif
44
45extern char etext[], _stext[];
46
47#ifdef CONFIG_SMP
48extern void hash_page_sync(void);
49#endif
50
51#ifdef HAVE_BATS
52extern unsigned long v_mapped_by_bats(unsigned long va);
53extern unsigned long p_mapped_by_bats(unsigned long pa);
54void setbat(int index, unsigned long virt, unsigned long phys,
55 unsigned int size, int flags);
56
57#else /* !HAVE_BATS */
58#define v_mapped_by_bats(x) (0UL)
59#define p_mapped_by_bats(x) (0UL)
60#endif /* HAVE_BATS */
61
62#ifdef CONFIG_PTE_64BIT
63/* 44x uses an 8kB pgdir because it has 8-byte Linux PTEs. */
64#define PGDIR_ORDER 1
65#else
66#define PGDIR_ORDER 0
67#endif
68
69pgd_t *pgd_alloc(struct mm_struct *mm)
70{
71 pgd_t *ret;
72
73 ret = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, PGDIR_ORDER);
74 return ret;
75}
76
77void pgd_free(struct mm_struct *mm, pgd_t *pgd)
78{
79 free_pages((unsigned long)pgd, PGDIR_ORDER);
80}
81
82__init_refok pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
83{
84 pte_t *pte;
85 extern int mem_init_done;
86 extern void *early_get_page(void);
87
88 if (mem_init_done) {
89 pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
90 } else {
91 pte = (pte_t *)early_get_page();
92 if (pte)
93 clear_page(pte);
94 }
95 return pte;
96}
97
98pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address)
99{
100 struct page *ptepage;
101
102#ifdef CONFIG_HIGHPTE
103 gfp_t flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_REPEAT;
104#else
105 gfp_t flags = GFP_KERNEL | __GFP_REPEAT;
106#endif
107
108 ptepage = alloc_pages(flags, 0);
109 if (ptepage) {
110 clear_highpage(ptepage);
111 pgtable_page_ctor(ptepage);
112 }
113 return ptepage;
114}
115
116void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
117{
118#ifdef CONFIG_SMP
119 hash_page_sync();
120#endif
121 free_page((unsigned long)pte);
122}
123
124void pte_free(struct mm_struct *mm, pgtable_t ptepage)
125{
126#ifdef CONFIG_SMP
127 hash_page_sync();
128#endif
129 pgtable_page_dtor(ptepage);
130 __free_page(ptepage);
131}
132
133#ifndef CONFIG_PHYS_64BIT
134void __iomem *
135ioremap(phys_addr_t addr, unsigned long size)
136{
137 return __ioremap(addr, size, _PAGE_NO_CACHE);
138}
139#else /* CONFIG_PHYS_64BIT */
140void __iomem *
141ioremap64(unsigned long long addr, unsigned long size)
142{
143 return __ioremap(addr, size, _PAGE_NO_CACHE);
144}
145
146void __iomem *
147ioremap(phys_addr_t addr, unsigned long size)
148{
149 phys_addr_t addr64 = fixup_bigphys_addr(addr, size);
150
151 return ioremap64(addr64, size);
152}
153#endif /* CONFIG_PHYS_64BIT */
154
155void __iomem *
156__ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
157{
158 unsigned long v, i;
159 phys_addr_t p;
160 int err;
161
162 /*
163 * Choose an address to map it to.
164 * Once the vmalloc system is running, we use it.
165 * Before then, we use space going down from ioremap_base
166 * (ioremap_bot records where we're up to).
167 */
168 p = addr & PAGE_MASK;
169 size = PAGE_ALIGN(addr + size) - p;
170
171 /*
172 * If the address lies within the first 16 MB, assume it's in ISA
173 * memory space
174 */
175 if (p < 16*1024*1024)
176 p += _ISA_MEM_BASE;
177
178 /*
179 * Don't allow anybody to remap normal RAM that we're using.
180 * mem_init() sets high_memory so only do the check after that.
181 */
182 if ( mem_init_done && (p < virt_to_phys(high_memory)) )
183 {
184 printk("__ioremap(): phys addr "PHYS_FMT" is RAM lr %p\n", p,
185 __builtin_return_address(0));
186 return NULL;
187 }
188
189 if (size == 0)
190 return NULL;
191
192 /*
193 * Is it already mapped? Perhaps overlapped by a previous
194 * BAT mapping. If the whole area is mapped then we're done,
195 * otherwise remap it since we want to keep the virt addrs for
196 * each request contiguous.
197 *
198 * We make the assumption here that if the bottom and top
199 * of the range we want are mapped then it's mapped to the
200 * same virt address (and this is contiguous).
201 * -- Cort
202 */
203 if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ )
204 goto out;
205
206 if (mem_init_done) {
207 struct vm_struct *area;
208 area = get_vm_area(size, VM_IOREMAP);
209 if (area == 0)
210 return NULL;
211 v = (unsigned long) area->addr;
212 } else {
213 v = (ioremap_bot -= size);
214 }
215
216 if ((flags & _PAGE_PRESENT) == 0)
217 flags |= _PAGE_KERNEL;
218 if (flags & _PAGE_NO_CACHE)
219 flags |= _PAGE_GUARDED;
220
221 /*
222 * Should check if it is a candidate for a BAT mapping
223 */
224
225 err = 0;
226 for (i = 0; i < size && err == 0; i += PAGE_SIZE)
227 err = map_page(v+i, p+i, flags);
228 if (err) {
229 if (mem_init_done)
230 vunmap((void *)v);
231 return NULL;
232 }
233
234out:
235 return (void __iomem *) (v + ((unsigned long)addr & ~PAGE_MASK));
236}
237
238void iounmap(volatile void __iomem *addr)
239{
240 /*
241 * If mapped by BATs then there is nothing to do.
242 * Calling vfree() generates a benign warning.
243 */
244 if (v_mapped_by_bats((unsigned long)addr)) return;
245
246 if (addr > high_memory && (unsigned long) addr < ioremap_bot)
247 vunmap((void *) (PAGE_MASK & (unsigned long)addr));
248}
249
250void __iomem *ioport_map(unsigned long port, unsigned int len)
251{
252 return (void __iomem *) (port + _IO_BASE);
253}
254
255void ioport_unmap(void __iomem *addr)
256{
257 /* Nothing to do */
258}
259EXPORT_SYMBOL(ioport_map);
260EXPORT_SYMBOL(ioport_unmap);
261
262int
263map_page(unsigned long va, phys_addr_t pa, int flags)
264{
265 pmd_t *pd;
266 pte_t *pg;
267 int err = -ENOMEM;
268
269 /* Use upper 10 bits of VA to index the first level map */
270 pd = pmd_offset(pgd_offset_k(va), va);
271 /* Use middle 10 bits of VA to index the second-level map */
272 pg = pte_alloc_kernel(pd, va);
273 if (pg != 0) {
274 err = 0;
275 set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags)));
276 if (mem_init_done)
277 flush_HPTE(0, va, pmd_val(*pd));
278 }
279 return err;
280}
281
282/*
283 * Map in all of physical memory starting at KERNELBASE.
284 */
285void __init mapin_ram(void)
286{
287 unsigned long v, p, s, f;
288
289 s = mmu_mapin_ram();
290 v = KERNELBASE + s;
291 p = PPC_MEMSTART + s;
292 for (; s < total_lowmem; s += PAGE_SIZE) {
293 if ((char *) v >= _stext && (char *) v < etext)
294 f = _PAGE_RAM_TEXT;
295 else
296 f = _PAGE_RAM;
297 map_page(v, p, f);
298 v += PAGE_SIZE;
299 p += PAGE_SIZE;
300 }
301}
302
303/* is x a power of 4? */
304#define is_power_of_4(x) is_power_of_2(x) && (ffs(x) & 1)
305
306/*
307 * Set up a mapping for a block of I/O.
308 * virt, phys, size must all be page-aligned.
309 * This should only be called before ioremap is called.
310 */
311void __init io_block_mapping(unsigned long virt, phys_addr_t phys,
312 unsigned int size, int flags)
313{
314 int i;
315
316 if (virt > KERNELBASE && virt < ioremap_bot)
317 ioremap_bot = ioremap_base = virt;
318
319#ifdef HAVE_BATS
320 /*
321 * Use a BAT for this if possible...
322 */
323 if (io_bat_index < 2 && is_power_of_2(size)
324 && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) {
325 setbat(io_bat_index, virt, phys, size, flags);
326 ++io_bat_index;
327 return;
328 }
329#endif /* HAVE_BATS */
330
331 /* No BATs available, put it in the page tables. */
332 for (i = 0; i < size; i += PAGE_SIZE)
333 map_page(virt + i, phys + i, flags);
334}
335
336/* Scan the real Linux page tables and return a PTE pointer for
337 * a virtual address in a context.
338 * Returns true (1) if PTE was found, zero otherwise. The pointer to
339 * the PTE pointer is unmodified if PTE is not found.
340 */
341int
342get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp)
343{
344 pgd_t *pgd;
345 pmd_t *pmd;
346 pte_t *pte;
347 int retval = 0;
348
349 pgd = pgd_offset(mm, addr & PAGE_MASK);
350 if (pgd) {
351 pmd = pmd_offset(pgd, addr & PAGE_MASK);
352 if (pmd_present(*pmd)) {
353 pte = pte_offset_map(pmd, addr & PAGE_MASK);
354 if (pte) {
355 retval = 1;
356 *ptep = pte;
357 if (pmdp)
358 *pmdp = pmd;
359 /* XXX caller needs to do pte_unmap, yuck */
360 }
361 }
362 }
363 return(retval);
364}
365
366/* Find physical address for this virtual address. Normally used by
367 * I/O functions, but anyone can call it.
368 */
369unsigned long iopa(unsigned long addr)
370{
371 unsigned long pa;
372
373 /* I don't know why this won't work on PMacs or CHRP. It
374 * appears there is some bug, or there is some implicit
375 * mapping done not properly represented by BATs or in page
376 * tables.......I am actively working on resolving this, but
377 * can't hold up other stuff. -- Dan
378 */
379 pte_t *pte;
380 struct mm_struct *mm;
381
382 /* Check the BATs */
383 pa = v_mapped_by_bats(addr);
384 if (pa)
385 return pa;
386
387 /* Allow mapping of user addresses (within the thread)
388 * for DMA if necessary.
389 */
390 if (addr < TASK_SIZE)
391 mm = current->mm;
392 else
393 mm = &init_mm;
394
395 pa = 0;
396 if (get_pteptr(mm, addr, &pte, NULL)) {
397 pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK);
398 pte_unmap(pte);
399 }
400
401 return(pa);
402}
403
diff --git a/arch/ppc/mm/ppc_mmu.c b/arch/ppc/mm/ppc_mmu.c
deleted file mode 100644
index 0c1dc155996a..000000000000
--- a/arch/ppc/mm/ppc_mmu.c
+++ /dev/null
@@ -1,269 +0,0 @@
1/*
2 * This file contains the routines for handling the MMU on those
3 * PowerPC implementations where the MMU substantially follows the
4 * architecture specification. This includes the 6xx, 7xx, 7xxx,
5 * and 8260 implementations but excludes the 8xx and 4xx.
6 * -- paulus
7 *
8 * Derived from arch/ppc/mm/init.c:
9 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
10 *
11 * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
12 * and Cort Dougan (PReP) (cort@cs.nmt.edu)
13 * Copyright (C) 1996 Paul Mackerras
14 * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
15 *
16 * Derived from "arch/i386/mm/init.c"
17 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
18 *
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version
22 * 2 of the License, or (at your option) any later version.
23 *
24 */
25
26#include <linux/kernel.h>
27#include <linux/mm.h>
28#include <linux/init.h>
29#include <linux/highmem.h>
30
31#include <asm/prom.h>
32#include <asm/mmu.h>
33#include <asm/machdep.h>
34
35#include "mmu_decl.h"
36#include "mem_pieces.h"
37
38PTE *Hash, *Hash_end;
39unsigned long Hash_size, Hash_mask;
40unsigned long _SDR1;
41
42union ubat { /* BAT register values to be loaded */
43 BAT bat;
44 u32 word[2];
45} BATS[4][2]; /* 4 pairs of IBAT, DBAT */
46
47struct batrange { /* stores address ranges mapped by BATs */
48 unsigned long start;
49 unsigned long limit;
50 unsigned long phys;
51} bat_addrs[4];
52
53/*
54 * Return PA for this VA if it is mapped by a BAT, or 0
55 */
56unsigned long v_mapped_by_bats(unsigned long va)
57{
58 int b;
59 for (b = 0; b < 4; ++b)
60 if (va >= bat_addrs[b].start && va < bat_addrs[b].limit)
61 return bat_addrs[b].phys + (va - bat_addrs[b].start);
62 return 0;
63}
64
65/*
66 * Return VA for a given PA or 0 if not mapped
67 */
68unsigned long p_mapped_by_bats(unsigned long pa)
69{
70 int b;
71 for (b = 0; b < 4; ++b)
72 if (pa >= bat_addrs[b].phys
73 && pa < (bat_addrs[b].limit-bat_addrs[b].start)
74 +bat_addrs[b].phys)
75 return bat_addrs[b].start+(pa-bat_addrs[b].phys);
76 return 0;
77}
78
79unsigned long __init mmu_mapin_ram(void)
80{
81 unsigned long tot, bl, done;
82 unsigned long max_size = (256<<20);
83 unsigned long align;
84
85 if (__map_without_bats)
86 return 0;
87
88 /* Set up BAT2 and if necessary BAT3 to cover RAM. */
89
90 /* Make sure we don't map a block larger than the
91 smallest alignment of the physical address. */
92 /* alignment of PPC_MEMSTART */
93 align = ~(PPC_MEMSTART-1) & PPC_MEMSTART;
94 /* set BAT block size to MIN(max_size, align) */
95 if (align && align < max_size)
96 max_size = align;
97
98 tot = total_lowmem;
99 for (bl = 128<<10; bl < max_size; bl <<= 1) {
100 if (bl * 2 > tot)
101 break;
102 }
103
104 setbat(2, KERNELBASE, PPC_MEMSTART, bl, _PAGE_RAM);
105 done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1;
106 if ((done < tot) && !bat_addrs[3].limit) {
107 /* use BAT3 to cover a bit more */
108 tot -= done;
109 for (bl = 128<<10; bl < max_size; bl <<= 1)
110 if (bl * 2 > tot)
111 break;
112 setbat(3, KERNELBASE+done, PPC_MEMSTART+done, bl, _PAGE_RAM);
113 done = (unsigned long)bat_addrs[3].limit - KERNELBASE + 1;
114 }
115
116 return done;
117}
118
119/*
120 * Set up one of the I/D BAT (block address translation) register pairs.
121 * The parameters are not checked; in particular size must be a power
122 * of 2 between 128k and 256M.
123 */
124void __init setbat(int index, unsigned long virt, unsigned long phys,
125 unsigned int size, int flags)
126{
127 unsigned int bl;
128 int wimgxpp;
129 union ubat *bat = BATS[index];
130
131 if (((flags & _PAGE_NO_CACHE) == 0) &&
132 cpu_has_feature(CPU_FTR_NEED_COHERENT))
133 flags |= _PAGE_COHERENT;
134
135 bl = (size >> 17) - 1;
136 if (PVR_VER(mfspr(SPRN_PVR)) != 1) {
137 /* 603, 604, etc. */
138 /* Do DBAT first */
139 wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE
140 | _PAGE_COHERENT | _PAGE_GUARDED);
141 wimgxpp |= (flags & _PAGE_RW)? BPP_RW: BPP_RX;
142 bat[1].word[0] = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */
143 bat[1].word[1] = phys | wimgxpp;
144#ifndef CONFIG_KGDB /* want user access for breakpoints */
145 if (flags & _PAGE_USER)
146#endif
147 bat[1].bat.batu.vp = 1;
148 if (flags & _PAGE_GUARDED) {
149 /* G bit must be zero in IBATs */
150 bat[0].word[0] = bat[0].word[1] = 0;
151 } else {
152 /* make IBAT same as DBAT */
153 bat[0] = bat[1];
154 }
155 } else {
156 /* 601 cpu */
157 if (bl > BL_8M)
158 bl = BL_8M;
159 wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE
160 | _PAGE_COHERENT);
161 wimgxpp |= (flags & _PAGE_RW)?
162 ((flags & _PAGE_USER)? PP_RWRW: PP_RWXX): PP_RXRX;
163 bat->word[0] = virt | wimgxpp | 4; /* Ks=0, Ku=1 */
164 bat->word[1] = phys | bl | 0x40; /* V=1 */
165 }
166
167 bat_addrs[index].start = virt;
168 bat_addrs[index].limit = virt + ((bl + 1) << 17) - 1;
169 bat_addrs[index].phys = phys;
170}
171
172/*
173 * Initialize the hash table and patch the instructions in hashtable.S.
174 */
175void __init MMU_init_hw(void)
176{
177 unsigned int hmask, mb, mb2;
178 unsigned int n_hpteg, lg_n_hpteg;
179
180 extern unsigned int hash_page_patch_A[];
181 extern unsigned int hash_page_patch_B[], hash_page_patch_C[];
182 extern unsigned int hash_page[];
183 extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[];
184
185 if (!cpu_has_feature(CPU_FTR_HPTE_TABLE)) {
186 /*
187 * Put a blr (procedure return) instruction at the
188 * start of hash_page, since we can still get DSI
189 * exceptions on a 603.
190 */
191 hash_page[0] = 0x4e800020;
192 flush_icache_range((unsigned long) &hash_page[0],
193 (unsigned long) &hash_page[1]);
194 return;
195 }
196
197 if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105);
198
199#define LG_HPTEG_SIZE 6 /* 64 bytes per HPTEG */
200#define SDR1_LOW_BITS ((n_hpteg - 1) >> 10)
201#define MIN_N_HPTEG 1024 /* min 64kB hash table */
202
203 /*
204 * Allow 1 HPTE (1/8 HPTEG) for each page of memory.
205 * This is less than the recommended amount, but then
206 * Linux ain't AIX.
207 */
208 n_hpteg = total_memory / (PAGE_SIZE * 8);
209 if (n_hpteg < MIN_N_HPTEG)
210 n_hpteg = MIN_N_HPTEG;
211 lg_n_hpteg = __ilog2(n_hpteg);
212 if (n_hpteg & (n_hpteg - 1)) {
213 ++lg_n_hpteg; /* round up if not power of 2 */
214 n_hpteg = 1 << lg_n_hpteg;
215 }
216 Hash_size = n_hpteg << LG_HPTEG_SIZE;
217
218 /*
219 * Find some memory for the hash table.
220 */
221 if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322);
222 Hash = mem_pieces_find(Hash_size, Hash_size);
223 cacheable_memzero(Hash, Hash_size);
224 _SDR1 = __pa(Hash) | SDR1_LOW_BITS;
225
226 Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
227
228 printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
229 total_memory >> 20, Hash_size >> 10, Hash);
230
231
232 /*
233 * Patch up the instructions in hashtable.S:create_hpte
234 */
235 if ( ppc_md.progress ) ppc_md.progress("hash:patch", 0x345);
236 Hash_mask = n_hpteg - 1;
237 hmask = Hash_mask >> (16 - LG_HPTEG_SIZE);
238 mb2 = mb = 32 - LG_HPTEG_SIZE - lg_n_hpteg;
239 if (lg_n_hpteg > 16)
240 mb2 = 16 - LG_HPTEG_SIZE;
241
242 hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff)
243 | ((unsigned int)(Hash) >> 16);
244 hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0) | (mb << 6);
245 hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0) | (mb2 << 6);
246 hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff) | hmask;
247 hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff) | hmask;
248
249 /*
250 * Ensure that the locations we've patched have been written
251 * out from the data cache and invalidated in the instruction
252 * cache, on those machines with split caches.
253 */
254 flush_icache_range((unsigned long) &hash_page_patch_A[0],
255 (unsigned long) &hash_page_patch_C[1]);
256
257 /*
258 * Patch up the instructions in hashtable.S:flush_hash_page
259 */
260 flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff)
261 | ((unsigned int)(Hash) >> 16);
262 flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0) | (mb << 6);
263 flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0) | (mb2 << 6);
264 flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff) | hmask;
265 flush_icache_range((unsigned long) &flush_hash_patch_A[0],
266 (unsigned long) &flush_hash_patch_B[1]);
267
268 if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
269}
diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c
deleted file mode 100644
index 4ff260bc9dd1..000000000000
--- a/arch/ppc/mm/tlb.c
+++ /dev/null
@@ -1,183 +0,0 @@
1/*
2 * This file contains the routines for TLB flushing.
3 * On machines where the MMU uses a hash table to store virtual to
4 * physical translations, these routines flush entries from the
5 * hash table also.
6 * -- paulus
7 *
8 * Derived from arch/ppc/mm/init.c:
9 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
10 *
11 * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
12 * and Cort Dougan (PReP) (cort@cs.nmt.edu)
13 * Copyright (C) 1996 Paul Mackerras
14 * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
15 *
16 * Derived from "arch/i386/mm/init.c"
17 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
18 *
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
21 * as published by the Free Software Foundation; either version
22 * 2 of the License, or (at your option) any later version.
23 *
24 */
25
26#include <linux/kernel.h>
27#include <linux/mm.h>
28#include <linux/init.h>
29#include <linux/highmem.h>
30#include <linux/pagemap.h>
31#include <asm/tlbflush.h>
32#include <asm/tlb.h>
33
34#include "mmu_decl.h"
35
36/*
37 * Called when unmapping pages to flush entries from the TLB/hash table.
38 */
39void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr)
40{
41 unsigned long ptephys;
42
43 if (Hash != 0) {
44 ptephys = __pa(ptep) & PAGE_MASK;
45 flush_hash_pages(mm->context.id, addr, ptephys, 1);
46 }
47}
48
49/*
50 * Called by ptep_set_access_flags, must flush on CPUs for which the
51 * DSI handler can't just "fixup" the TLB on a write fault
52 */
53void flush_tlb_page_nohash(struct vm_area_struct *vma, unsigned long addr)
54{
55 if (Hash != 0)
56 return;
57 _tlbie(addr);
58}
59
60/*
61 * Called at the end of a mmu_gather operation to make sure the
62 * TLB flush is completely done.
63 */
64void tlb_flush(struct mmu_gather *tlb)
65{
66 if (Hash == 0) {
67 /*
68 * 603 needs to flush the whole TLB here since
69 * it doesn't use a hash table.
70 */
71 _tlbia();
72 }
73}
74
75/*
76 * TLB flushing:
77 *
78 * - flush_tlb_mm(mm) flushes the specified mm context TLB's
79 * - flush_tlb_page(vma, vmaddr) flushes one page
80 * - flush_tlb_range(vma, start, end) flushes a range of pages
81 * - flush_tlb_kernel_range(start, end) flushes kernel pages
82 *
83 * since the hardware hash table functions as an extension of the
84 * tlb as far as the linux tables are concerned, flush it too.
85 * -- Cort
86 */
87
88/*
89 * 750 SMP is a Bad Idea because the 750 doesn't broadcast all
90 * the cache operations on the bus. Hence we need to use an IPI
91 * to get the other CPU(s) to invalidate their TLBs.
92 */
93#ifdef CONFIG_SMP_750
94#define FINISH_FLUSH smp_send_tlb_invalidate(0)
95#else
96#define FINISH_FLUSH do { } while (0)
97#endif
98
99static void flush_range(struct mm_struct *mm, unsigned long start,
100 unsigned long end)
101{
102 pmd_t *pmd;
103 unsigned long pmd_end;
104 int count;
105 unsigned int ctx = mm->context.id;
106
107 if (Hash == 0) {
108 _tlbia();
109 return;
110 }
111 start &= PAGE_MASK;
112 if (start >= end)
113 return;
114 end = (end - 1) | ~PAGE_MASK;
115 pmd = pmd_offset(pgd_offset(mm, start), start);
116 for (;;) {
117 pmd_end = ((start + PGDIR_SIZE) & PGDIR_MASK) - 1;
118 if (pmd_end > end)
119 pmd_end = end;
120 if (!pmd_none(*pmd)) {
121 count = ((pmd_end - start) >> PAGE_SHIFT) + 1;
122 flush_hash_pages(ctx, start, pmd_val(*pmd), count);
123 }
124 if (pmd_end == end)
125 break;
126 start = pmd_end + 1;
127 ++pmd;
128 }
129}
130
131/*
132 * Flush kernel TLB entries in the given range
133 */
134void flush_tlb_kernel_range(unsigned long start, unsigned long end)
135{
136 flush_range(&init_mm, start, end);
137 FINISH_FLUSH;
138}
139
140/*
141 * Flush all the (user) entries for the address space described by mm.
142 */
143void flush_tlb_mm(struct mm_struct *mm)
144{
145 struct vm_area_struct *mp;
146
147 if (Hash == 0) {
148 _tlbia();
149 return;
150 }
151
152 for (mp = mm->mmap; mp != NULL; mp = mp->vm_next)
153 flush_range(mp->vm_mm, mp->vm_start, mp->vm_end);
154 FINISH_FLUSH;
155}
156
157void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
158{
159 struct mm_struct *mm;
160 pmd_t *pmd;
161
162 if (Hash == 0) {
163 _tlbie(vmaddr);
164 return;
165 }
166 mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm;
167 pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr);
168 if (!pmd_none(*pmd))
169 flush_hash_pages(mm->context.id, vmaddr, pmd_val(*pmd), 1);
170 FINISH_FLUSH;
171}
172
173/*
174 * For each address in the range, find the pte for the address
175 * and check _PAGE_HASHPTE bit; if it is set, find and destroy
176 * the corresponding HPTE.
177 */
178void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
179 unsigned long end)
180{
181 flush_range(vma->vm_mm, start, end);
182 FINISH_FLUSH;
183}