diff options
| author | Paul Mackerras <paulus@samba.org> | 2007-07-10 23:28:26 -0400 |
|---|---|---|
| committer | Paul Mackerras <paulus@samba.org> | 2007-07-10 23:28:26 -0400 |
| commit | bf22f6fe2d72b4d7e9035be8ceb340414cf490e3 (patch) | |
| tree | 14085d90de0428316479fe6de8a0c6d32e6e65e2 /arch/powerpc/mm | |
| parent | 4eb6bf6bfb580afaf1e1a1d30cba17a078530cf4 (diff) | |
| parent | 93ab471889c6662b42ce7da257f31f24c08d7d9e (diff) | |
Merge branch 'for-2.6.23' into merge
Diffstat (limited to 'arch/powerpc/mm')
| -rw-r--r-- | arch/powerpc/mm/44x_mmu.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/mm/4xx_mmu.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/mm/Makefile | 3 | ||||
| -rw-r--r-- | arch/powerpc/mm/fault.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/mm/fsl_booke_mmu.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/mm/hash_native_64.c | 27 | ||||
| -rw-r--r-- | arch/powerpc/mm/hash_utils_64.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/mm/imalloc.c | 313 | ||||
| -rw-r--r-- | arch/powerpc/mm/init_32.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/mm/init_64.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/mm/mem.c | 3 | ||||
| -rw-r--r-- | arch/powerpc/mm/mmu_context_32.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/mm/mmu_decl.h | 17 | ||||
| -rw-r--r-- | arch/powerpc/mm/pgtable_32.c | 123 | ||||
| -rw-r--r-- | arch/powerpc/mm/pgtable_64.c | 206 | ||||
| -rw-r--r-- | arch/powerpc/mm/ppc_mmu_32.c | 7 | ||||
| -rw-r--r-- | arch/powerpc/mm/stab.c | 4 | ||||
| -rw-r--r-- | arch/powerpc/mm/tlb_32.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/mm/tlb_64.c | 57 |
19 files changed, 128 insertions, 643 deletions
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c index ca4dcb07a939..c3df50476539 100644 --- a/arch/powerpc/mm/44x_mmu.c +++ b/arch/powerpc/mm/44x_mmu.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 12 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 13 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 13 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 14 | * Copyright (C) 1996 Paul Mackerras | 14 | * Copyright (C) 1996 Paul Mackerras |
| 15 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 16 | * | 15 | * |
| 17 | * Derived from "arch/i386/mm/init.c" | 16 | * Derived from "arch/i386/mm/init.c" |
| 18 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 17 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/4xx_mmu.c b/arch/powerpc/mm/4xx_mmu.c index 838e09db71d9..7ff2609b64d1 100644 --- a/arch/powerpc/mm/4xx_mmu.c +++ b/arch/powerpc/mm/4xx_mmu.c | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 9 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 10 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 10 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 11 | * Copyright (C) 1996 Paul Mackerras | 11 | * Copyright (C) 1996 Paul Mackerras |
| 12 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 13 | * | 12 | * |
| 14 | * Derived from "arch/i386/mm/init.c" | 13 | * Derived from "arch/i386/mm/init.c" |
| 15 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 14 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 4f839c6a9768..7e4d27ad3dee 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
| @@ -11,8 +11,7 @@ obj-$(CONFIG_PPC32) += init_32.o pgtable_32.o mmu_context_32.o | |||
| 11 | hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o | 11 | hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o |
| 12 | obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \ | 12 | obj-$(CONFIG_PPC64) += init_64.o pgtable_64.o mmu_context_64.o \ |
| 13 | hash_utils_64.o hash_low_64.o tlb_64.o \ | 13 | hash_utils_64.o hash_low_64.o tlb_64.o \ |
| 14 | slb_low.o slb.o stab.o mmap.o imalloc.o \ | 14 | slb_low.o slb.o stab.o mmap.o $(hash-y) |
| 15 | $(hash-y) | ||
| 16 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o tlb_32.o | 15 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o hash_low_32.o tlb_32.o |
| 17 | obj-$(CONFIG_40x) += 4xx_mmu.o | 16 | obj-$(CONFIG_40x) += 4xx_mmu.o |
| 18 | obj-$(CONFIG_44x) += 44x_mmu.o | 17 | obj-$(CONFIG_44x) += 44x_mmu.o |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 115b25f50bf8..0ece51310bfe 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
| @@ -380,7 +380,7 @@ out_of_memory: | |||
| 380 | } | 380 | } |
| 381 | printk("VM: killing process %s\n", current->comm); | 381 | printk("VM: killing process %s\n", current->comm); |
| 382 | if (user_mode(regs)) | 382 | if (user_mode(regs)) |
| 383 | do_exit(SIGKILL); | 383 | do_group_exit(SIGKILL); |
| 384 | return SIGKILL; | 384 | return SIGKILL; |
| 385 | 385 | ||
| 386 | do_sigbus: | 386 | do_sigbus: |
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index 123da03ab118..afab247d472f 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 14 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 15 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 15 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 16 | * Copyright (C) 1996 Paul Mackerras | 16 | * Copyright (C) 1996 Paul Mackerras |
| 17 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 18 | * | 17 | * |
| 19 | * Derived from "arch/i386/mm/init.c" | 18 | * Derived from "arch/i386/mm/init.c" |
| 20 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 19 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index 4a20d890e2f4..6ba9b47e55af 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
| @@ -104,7 +104,7 @@ static inline void tlbie(unsigned long va, int psize, int local) | |||
| 104 | spin_unlock(&native_tlbie_lock); | 104 | spin_unlock(&native_tlbie_lock); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | static inline void native_lock_hpte(hpte_t *hptep) | 107 | static inline void native_lock_hpte(struct hash_pte *hptep) |
| 108 | { | 108 | { |
| 109 | unsigned long *word = &hptep->v; | 109 | unsigned long *word = &hptep->v; |
| 110 | 110 | ||
| @@ -116,7 +116,7 @@ static inline void native_lock_hpte(hpte_t *hptep) | |||
| 116 | } | 116 | } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | static inline void native_unlock_hpte(hpte_t *hptep) | 119 | static inline void native_unlock_hpte(struct hash_pte *hptep) |
| 120 | { | 120 | { |
| 121 | unsigned long *word = &hptep->v; | 121 | unsigned long *word = &hptep->v; |
| 122 | 122 | ||
| @@ -128,7 +128,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
| 128 | unsigned long pa, unsigned long rflags, | 128 | unsigned long pa, unsigned long rflags, |
| 129 | unsigned long vflags, int psize) | 129 | unsigned long vflags, int psize) |
| 130 | { | 130 | { |
| 131 | hpte_t *hptep = htab_address + hpte_group; | 131 | struct hash_pte *hptep = htab_address + hpte_group; |
| 132 | unsigned long hpte_v, hpte_r; | 132 | unsigned long hpte_v, hpte_r; |
| 133 | int i; | 133 | int i; |
| 134 | 134 | ||
| @@ -163,7 +163,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
| 163 | 163 | ||
| 164 | hptep->r = hpte_r; | 164 | hptep->r = hpte_r; |
| 165 | /* Guarantee the second dword is visible before the valid bit */ | 165 | /* Guarantee the second dword is visible before the valid bit */ |
| 166 | __asm__ __volatile__ ("eieio" : : : "memory"); | 166 | eieio(); |
| 167 | /* | 167 | /* |
| 168 | * Now set the first dword including the valid bit | 168 | * Now set the first dword including the valid bit |
| 169 | * NOTE: this also unlocks the hpte | 169 | * NOTE: this also unlocks the hpte |
| @@ -177,7 +177,7 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long va, | |||
| 177 | 177 | ||
| 178 | static long native_hpte_remove(unsigned long hpte_group) | 178 | static long native_hpte_remove(unsigned long hpte_group) |
| 179 | { | 179 | { |
| 180 | hpte_t *hptep; | 180 | struct hash_pte *hptep; |
| 181 | int i; | 181 | int i; |
| 182 | int slot_offset; | 182 | int slot_offset; |
| 183 | unsigned long hpte_v; | 183 | unsigned long hpte_v; |
| @@ -217,7 +217,7 @@ static long native_hpte_remove(unsigned long hpte_group) | |||
| 217 | static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | 217 | static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, |
| 218 | unsigned long va, int psize, int local) | 218 | unsigned long va, int psize, int local) |
| 219 | { | 219 | { |
| 220 | hpte_t *hptep = htab_address + slot; | 220 | struct hash_pte *hptep = htab_address + slot; |
| 221 | unsigned long hpte_v, want_v; | 221 | unsigned long hpte_v, want_v; |
| 222 | int ret = 0; | 222 | int ret = 0; |
| 223 | 223 | ||
| @@ -233,15 +233,14 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
| 233 | /* Even if we miss, we need to invalidate the TLB */ | 233 | /* Even if we miss, we need to invalidate the TLB */ |
| 234 | if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { | 234 | if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) { |
| 235 | DBG_LOW(" -> miss\n"); | 235 | DBG_LOW(" -> miss\n"); |
| 236 | native_unlock_hpte(hptep); | ||
| 237 | ret = -1; | 236 | ret = -1; |
| 238 | } else { | 237 | } else { |
| 239 | DBG_LOW(" -> hit\n"); | 238 | DBG_LOW(" -> hit\n"); |
| 240 | /* Update the HPTE */ | 239 | /* Update the HPTE */ |
| 241 | hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | | 240 | hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | |
| 242 | (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)); | 241 | (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)); |
| 243 | native_unlock_hpte(hptep); | ||
| 244 | } | 242 | } |
| 243 | native_unlock_hpte(hptep); | ||
| 245 | 244 | ||
| 246 | /* Ensure it is out of the tlb too. */ | 245 | /* Ensure it is out of the tlb too. */ |
| 247 | tlbie(va, psize, local); | 246 | tlbie(va, psize, local); |
| @@ -251,7 +250,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
| 251 | 250 | ||
| 252 | static long native_hpte_find(unsigned long va, int psize) | 251 | static long native_hpte_find(unsigned long va, int psize) |
| 253 | { | 252 | { |
| 254 | hpte_t *hptep; | 253 | struct hash_pte *hptep; |
| 255 | unsigned long hash; | 254 | unsigned long hash; |
| 256 | unsigned long i, j; | 255 | unsigned long i, j; |
| 257 | long slot; | 256 | long slot; |
| @@ -294,7 +293,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | |||
| 294 | { | 293 | { |
| 295 | unsigned long vsid, va; | 294 | unsigned long vsid, va; |
| 296 | long slot; | 295 | long slot; |
| 297 | hpte_t *hptep; | 296 | struct hash_pte *hptep; |
| 298 | 297 | ||
| 299 | vsid = get_kernel_vsid(ea); | 298 | vsid = get_kernel_vsid(ea); |
| 300 | va = (vsid << 28) | (ea & 0x0fffffff); | 299 | va = (vsid << 28) | (ea & 0x0fffffff); |
| @@ -315,7 +314,7 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | |||
| 315 | static void native_hpte_invalidate(unsigned long slot, unsigned long va, | 314 | static void native_hpte_invalidate(unsigned long slot, unsigned long va, |
| 316 | int psize, int local) | 315 | int psize, int local) |
| 317 | { | 316 | { |
| 318 | hpte_t *hptep = htab_address + slot; | 317 | struct hash_pte *hptep = htab_address + slot; |
| 319 | unsigned long hpte_v; | 318 | unsigned long hpte_v; |
| 320 | unsigned long want_v; | 319 | unsigned long want_v; |
| 321 | unsigned long flags; | 320 | unsigned long flags; |
| @@ -345,7 +344,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va, | |||
| 345 | #define LP_BITS 8 | 344 | #define LP_BITS 8 |
| 346 | #define LP_MASK(i) ((0xFF >> (i)) << LP_SHIFT) | 345 | #define LP_MASK(i) ((0xFF >> (i)) << LP_SHIFT) |
| 347 | 346 | ||
| 348 | static void hpte_decode(hpte_t *hpte, unsigned long slot, | 347 | static void hpte_decode(struct hash_pte *hpte, unsigned long slot, |
| 349 | int *psize, unsigned long *va) | 348 | int *psize, unsigned long *va) |
| 350 | { | 349 | { |
| 351 | unsigned long hpte_r = hpte->r; | 350 | unsigned long hpte_r = hpte->r; |
| @@ -415,7 +414,7 @@ static void hpte_decode(hpte_t *hpte, unsigned long slot, | |||
| 415 | static void native_hpte_clear(void) | 414 | static void native_hpte_clear(void) |
| 416 | { | 415 | { |
| 417 | unsigned long slot, slots, flags; | 416 | unsigned long slot, slots, flags; |
| 418 | hpte_t *hptep = htab_address; | 417 | struct hash_pte *hptep = htab_address; |
| 419 | unsigned long hpte_v, va; | 418 | unsigned long hpte_v, va; |
| 420 | unsigned long pteg_count; | 419 | unsigned long pteg_count; |
| 421 | int psize; | 420 | int psize; |
| @@ -462,7 +461,7 @@ static void native_hpte_clear(void) | |||
| 462 | static void native_flush_hash_range(unsigned long number, int local) | 461 | static void native_flush_hash_range(unsigned long number, int local) |
| 463 | { | 462 | { |
| 464 | unsigned long va, hash, index, hidx, shift, slot; | 463 | unsigned long va, hash, index, hidx, shift, slot; |
| 465 | hpte_t *hptep; | 464 | struct hash_pte *hptep; |
| 466 | unsigned long hpte_v; | 465 | unsigned long hpte_v; |
| 467 | unsigned long want_v; | 466 | unsigned long want_v; |
| 468 | unsigned long flags; | 467 | unsigned long flags; |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 4f2f4534a9d8..2ce9491b48d4 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
| @@ -87,7 +87,7 @@ extern unsigned long dart_tablebase; | |||
| 87 | static unsigned long _SDR1; | 87 | static unsigned long _SDR1; |
| 88 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; | 88 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; |
| 89 | 89 | ||
| 90 | hpte_t *htab_address; | 90 | struct hash_pte *htab_address; |
| 91 | unsigned long htab_size_bytes; | 91 | unsigned long htab_size_bytes; |
| 92 | unsigned long htab_hash_mask; | 92 | unsigned long htab_hash_mask; |
| 93 | int mmu_linear_psize = MMU_PAGE_4K; | 93 | int mmu_linear_psize = MMU_PAGE_4K; |
diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c deleted file mode 100644 index c831815c31f0..000000000000 --- a/arch/powerpc/mm/imalloc.c +++ /dev/null | |||
| @@ -1,313 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * c 2001 PPC 64 Team, IBM Corp | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License | ||
| 6 | * as published by the Free Software Foundation; either version | ||
| 7 | * 2 of the License, or (at your option) any later version. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/slab.h> | ||
| 11 | #include <linux/vmalloc.h> | ||
| 12 | |||
| 13 | #include <asm/uaccess.h> | ||
| 14 | #include <asm/pgalloc.h> | ||
| 15 | #include <asm/pgtable.h> | ||
| 16 | #include <linux/mutex.h> | ||
| 17 | #include <asm/cacheflush.h> | ||
| 18 | |||
| 19 | #include "mmu_decl.h" | ||
| 20 | |||
| 21 | static DEFINE_MUTEX(imlist_mutex); | ||
| 22 | struct vm_struct * imlist = NULL; | ||
| 23 | |||
| 24 | static int get_free_im_addr(unsigned long size, unsigned long *im_addr) | ||
| 25 | { | ||
| 26 | unsigned long addr; | ||
| 27 | struct vm_struct **p, *tmp; | ||
| 28 | |||
| 29 | addr = ioremap_bot; | ||
| 30 | for (p = &imlist; (tmp = *p) ; p = &tmp->next) { | ||
| 31 | if (size + addr < (unsigned long) tmp->addr) | ||
| 32 | break; | ||
| 33 | if ((unsigned long)tmp->addr >= ioremap_bot) | ||
| 34 | addr = tmp->size + (unsigned long) tmp->addr; | ||
| 35 | if (addr >= IMALLOC_END-size) | ||
| 36 | return 1; | ||
| 37 | } | ||
| 38 | *im_addr = addr; | ||
| 39 | |||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 43 | /* Return whether the region described by v_addr and size is a subset | ||
| 44 | * of the region described by parent | ||
| 45 | */ | ||
| 46 | static inline int im_region_is_subset(unsigned long v_addr, unsigned long size, | ||
| 47 | struct vm_struct *parent) | ||
| 48 | { | ||
| 49 | return (int) (v_addr >= (unsigned long) parent->addr && | ||
| 50 | v_addr < (unsigned long) parent->addr + parent->size && | ||
| 51 | size < parent->size); | ||
| 52 | } | ||
| 53 | |||
| 54 | /* Return whether the region described by v_addr and size is a superset | ||
| 55 | * of the region described by child | ||
| 56 | */ | ||
| 57 | static int im_region_is_superset(unsigned long v_addr, unsigned long size, | ||
| 58 | struct vm_struct *child) | ||
| 59 | { | ||
| 60 | struct vm_struct parent; | ||
| 61 | |||
| 62 | parent.addr = (void *) v_addr; | ||
| 63 | parent.size = size; | ||
| 64 | |||
| 65 | return im_region_is_subset((unsigned long) child->addr, child->size, | ||
| 66 | &parent); | ||
| 67 | } | ||
| 68 | |||
| 69 | /* Return whether the region described by v_addr and size overlaps | ||
| 70 | * the region described by vm. Overlapping regions meet the | ||
| 71 | * following conditions: | ||
| 72 | * 1) The regions share some part of the address space | ||
| 73 | * 2) The regions aren't identical | ||
| 74 | * 3) Neither region is a subset of the other | ||
| 75 | */ | ||
| 76 | static int im_region_overlaps(unsigned long v_addr, unsigned long size, | ||
| 77 | struct vm_struct *vm) | ||
| 78 | { | ||
| 79 | if (im_region_is_superset(v_addr, size, vm)) | ||
| 80 | return 0; | ||
| 81 | |||
| 82 | return (v_addr + size > (unsigned long) vm->addr + vm->size && | ||
| 83 | v_addr < (unsigned long) vm->addr + vm->size) || | ||
| 84 | (v_addr < (unsigned long) vm->addr && | ||
| 85 | v_addr + size > (unsigned long) vm->addr); | ||
| 86 | } | ||
| 87 | |||
| 88 | /* Determine imalloc status of region described by v_addr and size. | ||
| 89 | * Can return one of the following: | ||
| 90 | * IM_REGION_UNUSED - Entire region is unallocated in imalloc space. | ||
| 91 | * IM_REGION_SUBSET - Region is a subset of a region that is already | ||
| 92 | * allocated in imalloc space. | ||
| 93 | * vm will be assigned to a ptr to the parent region. | ||
| 94 | * IM_REGION_EXISTS - Exact region already allocated in imalloc space. | ||
| 95 | * vm will be assigned to a ptr to the existing imlist | ||
| 96 | * member. | ||
| 97 | * IM_REGION_OVERLAPS - Region overlaps an allocated region in imalloc space. | ||
| 98 | * IM_REGION_SUPERSET - Region is a superset of a region that is already | ||
| 99 | * allocated in imalloc space. | ||
| 100 | */ | ||
| 101 | static int im_region_status(unsigned long v_addr, unsigned long size, | ||
| 102 | struct vm_struct **vm) | ||
| 103 | { | ||
| 104 | struct vm_struct *tmp; | ||
| 105 | |||
| 106 | for (tmp = imlist; tmp; tmp = tmp->next) | ||
| 107 | if (v_addr < (unsigned long) tmp->addr + tmp->size) | ||
| 108 | break; | ||
| 109 | |||
| 110 | *vm = NULL; | ||
| 111 | if (tmp) { | ||
| 112 | if (im_region_overlaps(v_addr, size, tmp)) | ||
| 113 | return IM_REGION_OVERLAP; | ||
| 114 | |||
| 115 | *vm = tmp; | ||
| 116 | if (im_region_is_subset(v_addr, size, tmp)) { | ||
| 117 | /* Return with tmp pointing to superset */ | ||
| 118 | return IM_REGION_SUBSET; | ||
| 119 | } | ||
| 120 | if (im_region_is_superset(v_addr, size, tmp)) { | ||
| 121 | /* Return with tmp pointing to first subset */ | ||
| 122 | return IM_REGION_SUPERSET; | ||
| 123 | } | ||
| 124 | else if (v_addr == (unsigned long) tmp->addr && | ||
| 125 | size == tmp->size) { | ||
| 126 | /* Return with tmp pointing to exact region */ | ||
| 127 | return IM_REGION_EXISTS; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | return IM_REGION_UNUSED; | ||
| 132 | } | ||
| 133 | |||
| 134 | static struct vm_struct * split_im_region(unsigned long v_addr, | ||
| 135 | unsigned long size, struct vm_struct *parent) | ||
| 136 | { | ||
| 137 | struct vm_struct *vm1 = NULL; | ||
| 138 | struct vm_struct *vm2 = NULL; | ||
| 139 | struct vm_struct *new_vm = NULL; | ||
| 140 | |||
| 141 | vm1 = kmalloc(sizeof(*vm1), GFP_KERNEL); | ||
| 142 | if (vm1 == NULL) { | ||
| 143 | printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); | ||
| 144 | return NULL; | ||
| 145 | } | ||
| 146 | |||
| 147 | if (v_addr == (unsigned long) parent->addr) { | ||
| 148 | /* Use existing parent vm_struct to represent child, allocate | ||
| 149 | * new one for the remainder of parent range | ||
| 150 | */ | ||
| 151 | vm1->size = parent->size - size; | ||
| 152 | vm1->addr = (void *) (v_addr + size); | ||
| 153 | vm1->next = parent->next; | ||
| 154 | |||
| 155 | parent->size = size; | ||
| 156 | parent->next = vm1; | ||
| 157 | new_vm = parent; | ||
| 158 | } else if (v_addr + size == (unsigned long) parent->addr + | ||
| 159 | parent->size) { | ||
| 160 | /* Allocate new vm_struct to represent child, use existing | ||
| 161 | * parent one for remainder of parent range | ||
| 162 | */ | ||
| 163 | vm1->size = size; | ||
| 164 | vm1->addr = (void *) v_addr; | ||
| 165 | vm1->next = parent->next; | ||
| 166 | new_vm = vm1; | ||
| 167 | |||
| 168 | parent->size -= size; | ||
| 169 | parent->next = vm1; | ||
| 170 | } else { | ||
| 171 | /* Allocate two new vm_structs for the new child and | ||
| 172 | * uppermost remainder, and use existing parent one for the | ||
| 173 | * lower remainder of parent range | ||
| 174 | */ | ||
| 175 | vm2 = kmalloc(sizeof(*vm2), GFP_KERNEL); | ||
| 176 | if (vm2 == NULL) { | ||
| 177 | printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); | ||
| 178 | kfree(vm1); | ||
| 179 | return NULL; | ||
| 180 | } | ||
| 181 | |||
| 182 | vm1->size = size; | ||
| 183 | vm1->addr = (void *) v_addr; | ||
| 184 | vm1->next = vm2; | ||
| 185 | new_vm = vm1; | ||
| 186 | |||
| 187 | vm2->size = ((unsigned long) parent->addr + parent->size) - | ||
| 188 | (v_addr + size); | ||
| 189 | vm2->addr = (void *) v_addr + size; | ||
| 190 | vm2->next = parent->next; | ||
| 191 | |||
| 192 | parent->size = v_addr - (unsigned long) parent->addr; | ||
| 193 | parent->next = vm1; | ||
| 194 | } | ||
| 195 | |||
| 196 | return new_vm; | ||
| 197 | } | ||
| 198 | |||
| 199 | static struct vm_struct * __add_new_im_area(unsigned long req_addr, | ||
| 200 | unsigned long size) | ||
| 201 | { | ||
| 202 | struct vm_struct **p, *tmp, *area; | ||
| 203 | |||
| 204 | for (p = &imlist; (tmp = *p) ; p = &tmp->next) { | ||
| 205 | if (req_addr + size <= (unsigned long)tmp->addr) | ||
| 206 | break; | ||
| 207 | } | ||
| 208 | |||
| 209 | area = kmalloc(sizeof(*area), GFP_KERNEL); | ||
| 210 | if (!area) | ||
| 211 | return NULL; | ||
| 212 | area->flags = 0; | ||
| 213 | area->addr = (void *)req_addr; | ||
| 214 | area->size = size; | ||
| 215 | area->next = *p; | ||
| 216 | *p = area; | ||
| 217 | |||
| 218 | return area; | ||
| 219 | } | ||
| 220 | |||
| 221 | static struct vm_struct * __im_get_area(unsigned long req_addr, | ||
| 222 | unsigned long size, | ||
| 223 | int criteria) | ||
| 224 | { | ||
| 225 | struct vm_struct *tmp; | ||
| 226 | int status; | ||
| 227 | |||
| 228 | status = im_region_status(req_addr, size, &tmp); | ||
| 229 | if ((criteria & status) == 0) { | ||
| 230 | return NULL; | ||
| 231 | } | ||
| 232 | |||
| 233 | switch (status) { | ||
| 234 | case IM_REGION_UNUSED: | ||
| 235 | tmp = __add_new_im_area(req_addr, size); | ||
| 236 | break; | ||
| 237 | case IM_REGION_SUBSET: | ||
| 238 | tmp = split_im_region(req_addr, size, tmp); | ||
| 239 | break; | ||
| 240 | case IM_REGION_EXISTS: | ||
| 241 | /* Return requested region */ | ||
| 242 | break; | ||
| 243 | case IM_REGION_SUPERSET: | ||
| 244 | /* Return first existing subset of requested region */ | ||
| 245 | break; | ||
| 246 | default: | ||
| 247 | printk(KERN_ERR "%s() unexpected imalloc region status\n", | ||
| 248 | __FUNCTION__); | ||
| 249 | tmp = NULL; | ||
| 250 | } | ||
| 251 | |||
| 252 | return tmp; | ||
| 253 | } | ||
| 254 | |||
| 255 | struct vm_struct * im_get_free_area(unsigned long size) | ||
| 256 | { | ||
| 257 | struct vm_struct *area; | ||
| 258 | unsigned long addr; | ||
| 259 | |||
| 260 | mutex_lock(&imlist_mutex); | ||
| 261 | if (get_free_im_addr(size, &addr)) { | ||
| 262 | printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n", | ||
| 263 | __FUNCTION__, size); | ||
| 264 | area = NULL; | ||
| 265 | goto next_im_done; | ||
| 266 | } | ||
| 267 | |||
| 268 | area = __im_get_area(addr, size, IM_REGION_UNUSED); | ||
| 269 | if (area == NULL) { | ||
| 270 | printk(KERN_ERR | ||
| 271 | "%s() cannot obtain area for addr 0x%lx size 0x%lx\n", | ||
| 272 | __FUNCTION__, addr, size); | ||
| 273 | } | ||
| 274 | next_im_done: | ||
| 275 | mutex_unlock(&imlist_mutex); | ||
| 276 | return area; | ||
| 277 | } | ||
| 278 | |||
| 279 | struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, | ||
| 280 | int criteria) | ||
| 281 | { | ||
| 282 | struct vm_struct *area; | ||
| 283 | |||
| 284 | mutex_lock(&imlist_mutex); | ||
| 285 | area = __im_get_area(v_addr, size, criteria); | ||
| 286 | mutex_unlock(&imlist_mutex); | ||
| 287 | return area; | ||
| 288 | } | ||
| 289 | |||
| 290 | void im_free(void * addr) | ||
| 291 | { | ||
| 292 | struct vm_struct **p, *tmp; | ||
| 293 | |||
| 294 | if (!addr) | ||
| 295 | return; | ||
| 296 | if ((unsigned long) addr & ~PAGE_MASK) { | ||
| 297 | printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr); | ||
| 298 | return; | ||
| 299 | } | ||
| 300 | mutex_lock(&imlist_mutex); | ||
| 301 | for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { | ||
| 302 | if (tmp->addr == addr) { | ||
| 303 | *p = tmp->next; | ||
| 304 | unmap_vm_area(tmp); | ||
| 305 | kfree(tmp); | ||
| 306 | mutex_unlock(&imlist_mutex); | ||
| 307 | return; | ||
| 308 | } | ||
| 309 | } | ||
| 310 | mutex_unlock(&imlist_mutex); | ||
| 311 | printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__, | ||
| 312 | addr); | ||
| 313 | } | ||
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 5fce6ccecb8d..e1f5ded851f6 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 7 | * Copyright (C) 1996 Paul Mackerras | 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) | 8 | * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) |
| 10 | * | 9 | * |
| 11 | * Derived from "arch/i386/mm/init.c" | 10 | * Derived from "arch/i386/mm/init.c" |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 7312a265545f..1d6edf724c85 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 7 | * Copyright (C) 1996 Paul Mackerras | 7 | * Copyright (C) 1996 Paul Mackerras |
| 8 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 9 | * | 8 | * |
| 10 | * Derived from "arch/i386/mm/init.c" | 9 | * Derived from "arch/i386/mm/init.c" |
| 11 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 10 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 0266a94d83b6..f0e7eedb1ba3 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 5 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 6 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 7 | * Copyright (C) 1996 Paul Mackerras | 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) | 8 | * PPC44x/36-bit changes by Matt Porter (mporter@mvista.com) |
| 10 | * | 9 | * |
| 11 | * Derived from "arch/i386/mm/init.c" | 10 | * Derived from "arch/i386/mm/init.c" |
| @@ -129,8 +128,6 @@ int __devinit arch_add_memory(int nid, u64 start, u64 size) | |||
| 129 | zone = pgdata->node_zones; | 128 | zone = pgdata->node_zones; |
| 130 | 129 | ||
| 131 | return __add_pages(zone, start_pfn, nr_pages); | 130 | return __add_pages(zone, start_pfn, nr_pages); |
| 132 | |||
| 133 | return 0; | ||
| 134 | } | 131 | } |
| 135 | 132 | ||
| 136 | /* | 133 | /* |
diff --git a/arch/powerpc/mm/mmu_context_32.c b/arch/powerpc/mm/mmu_context_32.c index 792086b01000..cc32ba41d900 100644 --- a/arch/powerpc/mm/mmu_context_32.c +++ b/arch/powerpc/mm/mmu_context_32.c | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 13 | * Copyright (C) 1996 Paul Mackerras | 13 | * Copyright (C) 1996 Paul Mackerras |
| 14 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 15 | * | 14 | * |
| 16 | * Derived from "arch/i386/mm/init.c" | 15 | * Derived from "arch/i386/mm/init.c" |
| 17 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 16 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index 2558c34eedaa..c94a64fd3c01 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 10 | * Copyright (C) 1996 Paul Mackerras | 10 | * Copyright (C) 1996 Paul Mackerras |
| 11 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 12 | * | 11 | * |
| 13 | * Derived from "arch/i386/mm/init.c" | 12 | * Derived from "arch/i386/mm/init.c" |
| 14 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 13 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
| @@ -40,8 +39,8 @@ extern int __map_without_bats; | |||
| 40 | extern unsigned long ioremap_base; | 39 | extern unsigned long ioremap_base; |
| 41 | extern unsigned int rtas_data, rtas_size; | 40 | extern unsigned int rtas_data, rtas_size; |
| 42 | 41 | ||
| 43 | struct _PTE; | 42 | struct hash_pte; |
| 44 | extern struct _PTE *Hash, *Hash_end; | 43 | extern struct hash_pte *Hash, *Hash_end; |
| 45 | extern unsigned long Hash_size, Hash_mask; | 44 | extern unsigned long Hash_size, Hash_mask; |
| 46 | 45 | ||
| 47 | extern unsigned int num_tlbcam_entries; | 46 | extern unsigned int num_tlbcam_entries; |
| @@ -90,16 +89,4 @@ static inline void flush_HPTE(unsigned context, unsigned long va, | |||
| 90 | else | 89 | else |
| 91 | _tlbie(va); | 90 | _tlbie(va); |
| 92 | } | 91 | } |
| 93 | #else /* CONFIG_PPC64 */ | ||
| 94 | /* imalloc region types */ | ||
| 95 | #define IM_REGION_UNUSED 0x1 | ||
| 96 | #define IM_REGION_SUBSET 0x2 | ||
| 97 | #define IM_REGION_EXISTS 0x4 | ||
| 98 | #define IM_REGION_OVERLAP 0x8 | ||
| 99 | #define IM_REGION_SUPERSET 0x10 | ||
| 100 | |||
| 101 | extern struct vm_struct * im_get_free_area(unsigned long size); | ||
| 102 | extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, | ||
| 103 | int region_type); | ||
| 104 | extern void im_free(void *addr); | ||
| 105 | #endif | 92 | #endif |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index f6ae1a57d652..64488723162a 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 10 | * Copyright (C) 1996 Paul Mackerras | 10 | * Copyright (C) 1996 Paul Mackerras |
| 11 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 12 | * | 11 | * |
| 13 | * Derived from "arch/i386/mm/init.c" | 12 | * Derived from "arch/i386/mm/init.c" |
| 14 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 13 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
| @@ -37,7 +36,6 @@ | |||
| 37 | unsigned long ioremap_base; | 36 | unsigned long ioremap_base; |
| 38 | unsigned long ioremap_bot; | 37 | unsigned long ioremap_bot; |
| 39 | EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ | 38 | EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ |
| 40 | int io_bat_index; | ||
| 41 | 39 | ||
| 42 | #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) | 40 | #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) |
| 43 | #define HAVE_BATS 1 | 41 | #define HAVE_BATS 1 |
| @@ -300,51 +298,6 @@ void __init mapin_ram(void) | |||
| 300 | } | 298 | } |
| 301 | } | 299 | } |
| 302 | 300 | ||
| 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 | */ | ||
| 311 | void __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 | #ifdef HAVE_TLBCAM | ||
| 332 | /* | ||
| 333 | * Use a CAM for this if possible... | ||
| 334 | */ | ||
| 335 | if (tlbcam_index < num_tlbcam_entries && is_power_of_4(size) | ||
| 336 | && (virt & (size - 1)) == 0 && (phys & (size - 1)) == 0) { | ||
| 337 | settlbcam(tlbcam_index, virt, phys, size, flags, 0); | ||
| 338 | ++tlbcam_index; | ||
| 339 | return; | ||
| 340 | } | ||
| 341 | #endif /* HAVE_TLBCAM */ | ||
| 342 | |||
| 343 | /* No BATs available, put it in the page tables. */ | ||
| 344 | for (i = 0; i < size; i += PAGE_SIZE) | ||
| 345 | map_page(virt + i, phys + i, flags); | ||
| 346 | } | ||
| 347 | |||
| 348 | /* Scan the real Linux page tables and return a PTE pointer for | 301 | /* Scan the real Linux page tables and return a PTE pointer for |
| 349 | * a virtual address in a context. | 302 | * a virtual address in a context. |
| 350 | * Returns true (1) if PTE was found, zero otherwise. The pointer to | 303 | * Returns true (1) if PTE was found, zero otherwise. The pointer to |
| @@ -379,82 +332,6 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp) | |||
| 379 | return(retval); | 332 | return(retval); |
| 380 | } | 333 | } |
| 381 | 334 | ||
| 382 | /* Find physical address for this virtual address. Normally used by | ||
| 383 | * I/O functions, but anyone can call it. | ||
| 384 | */ | ||
| 385 | unsigned long iopa(unsigned long addr) | ||
| 386 | { | ||
| 387 | unsigned long pa; | ||
| 388 | |||
| 389 | /* I don't know why this won't work on PMacs or CHRP. It | ||
| 390 | * appears there is some bug, or there is some implicit | ||
| 391 | * mapping done not properly represented by BATs or in page | ||
| 392 | * tables.......I am actively working on resolving this, but | ||
| 393 | * can't hold up other stuff. -- Dan | ||
| 394 | */ | ||
| 395 | pte_t *pte; | ||
| 396 | struct mm_struct *mm; | ||
| 397 | |||
| 398 | /* Check the BATs */ | ||
| 399 | pa = v_mapped_by_bats(addr); | ||
| 400 | if (pa) | ||
| 401 | return pa; | ||
| 402 | |||
| 403 | /* Allow mapping of user addresses (within the thread) | ||
| 404 | * for DMA if necessary. | ||
| 405 | */ | ||
| 406 | if (addr < TASK_SIZE) | ||
| 407 | mm = current->mm; | ||
| 408 | else | ||
| 409 | mm = &init_mm; | ||
| 410 | |||
| 411 | pa = 0; | ||
| 412 | if (get_pteptr(mm, addr, &pte, NULL)) { | ||
| 413 | pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); | ||
| 414 | pte_unmap(pte); | ||
| 415 | } | ||
| 416 | |||
| 417 | return(pa); | ||
| 418 | } | ||
| 419 | |||
| 420 | /* This is will find the virtual address for a physical one.... | ||
| 421 | * Swiped from APUS, could be dangerous :-). | ||
| 422 | * This is only a placeholder until I really find a way to make this | ||
| 423 | * work. -- Dan | ||
| 424 | */ | ||
| 425 | unsigned long | ||
| 426 | mm_ptov (unsigned long paddr) | ||
| 427 | { | ||
| 428 | unsigned long ret; | ||
| 429 | #if 0 | ||
| 430 | if (paddr < 16*1024*1024) | ||
| 431 | ret = ZTWO_VADDR(paddr); | ||
| 432 | else { | ||
| 433 | int i; | ||
| 434 | |||
| 435 | for (i = 0; i < kmap_chunk_count;){ | ||
| 436 | unsigned long phys = kmap_chunks[i++]; | ||
| 437 | unsigned long size = kmap_chunks[i++]; | ||
| 438 | unsigned long virt = kmap_chunks[i++]; | ||
| 439 | if (paddr >= phys | ||
| 440 | && paddr < (phys + size)){ | ||
| 441 | ret = virt + paddr - phys; | ||
| 442 | goto exit; | ||
| 443 | } | ||
| 444 | } | ||
| 445 | |||
| 446 | ret = (unsigned long) __va(paddr); | ||
| 447 | } | ||
| 448 | exit: | ||
| 449 | #ifdef DEBUGPV | ||
| 450 | printk ("PTOV(%lx)=%lx\n", paddr, ret); | ||
| 451 | #endif | ||
| 452 | #else | ||
| 453 | ret = (unsigned long)paddr + KERNELBASE; | ||
| 454 | #endif | ||
| 455 | return ret; | ||
| 456 | } | ||
| 457 | |||
| 458 | #ifdef CONFIG_DEBUG_PAGEALLOC | 335 | #ifdef CONFIG_DEBUG_PAGEALLOC |
| 459 | 336 | ||
| 460 | static int __change_page_attr(struct page *page, pgprot_t prot) | 337 | static int __change_page_attr(struct page *page, pgprot_t prot) |
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index ad6e135bf212..3dfd10db931a 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | * Modifications by Paul Mackerras (PowerMac) (paulus@samba.org) | 7 | * Modifications by Paul Mackerras (PowerMac) (paulus@samba.org) |
| 8 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 8 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 9 | * Copyright (C) 1996 Paul Mackerras | 9 | * Copyright (C) 1996 Paul Mackerras |
| 10 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 11 | * | 10 | * |
| 12 | * Derived from "arch/i386/mm/init.c" | 11 | * Derived from "arch/i386/mm/init.c" |
| 13 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 12 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
| @@ -34,41 +33,27 @@ | |||
| 34 | #include <linux/stddef.h> | 33 | #include <linux/stddef.h> |
| 35 | #include <linux/vmalloc.h> | 34 | #include <linux/vmalloc.h> |
| 36 | #include <linux/init.h> | 35 | #include <linux/init.h> |
| 37 | #include <linux/delay.h> | ||
| 38 | #include <linux/bootmem.h> | ||
| 39 | #include <linux/highmem.h> | ||
| 40 | #include <linux/idr.h> | ||
| 41 | #include <linux/nodemask.h> | ||
| 42 | #include <linux/module.h> | ||
| 43 | 36 | ||
| 44 | #include <asm/pgalloc.h> | 37 | #include <asm/pgalloc.h> |
| 45 | #include <asm/page.h> | 38 | #include <asm/page.h> |
| 46 | #include <asm/prom.h> | 39 | #include <asm/prom.h> |
| 47 | #include <asm/lmb.h> | ||
| 48 | #include <asm/rtas.h> | ||
| 49 | #include <asm/io.h> | 40 | #include <asm/io.h> |
| 50 | #include <asm/mmu_context.h> | 41 | #include <asm/mmu_context.h> |
| 51 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
| 52 | #include <asm/mmu.h> | 43 | #include <asm/mmu.h> |
| 53 | #include <asm/uaccess.h> | ||
| 54 | #include <asm/smp.h> | 44 | #include <asm/smp.h> |
| 55 | #include <asm/machdep.h> | 45 | #include <asm/machdep.h> |
| 56 | #include <asm/tlb.h> | 46 | #include <asm/tlb.h> |
| 57 | #include <asm/eeh.h> | ||
| 58 | #include <asm/processor.h> | 47 | #include <asm/processor.h> |
| 59 | #include <asm/mmzone.h> | ||
| 60 | #include <asm/cputable.h> | 48 | #include <asm/cputable.h> |
| 61 | #include <asm/sections.h> | 49 | #include <asm/sections.h> |
| 62 | #include <asm/system.h> | 50 | #include <asm/system.h> |
| 63 | #include <asm/iommu.h> | ||
| 64 | #include <asm/abs_addr.h> | 51 | #include <asm/abs_addr.h> |
| 65 | #include <asm/vdso.h> | ||
| 66 | #include <asm/firmware.h> | 52 | #include <asm/firmware.h> |
| 67 | 53 | ||
| 68 | #include "mmu_decl.h" | 54 | #include "mmu_decl.h" |
| 69 | 55 | ||
| 70 | unsigned long ioremap_bot = IMALLOC_BASE; | 56 | unsigned long ioremap_bot = IOREMAP_BASE; |
| 71 | static unsigned long phbs_io_bot = PHBS_IO_BASE; | ||
| 72 | 57 | ||
| 73 | /* | 58 | /* |
| 74 | * map_io_page currently only called by __ioremap | 59 | * map_io_page currently only called by __ioremap |
| @@ -102,8 +87,8 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | |||
| 102 | * entry in the hardware page table. | 87 | * entry in the hardware page table. |
| 103 | * | 88 | * |
| 104 | */ | 89 | */ |
| 105 | if (htab_bolt_mapping(ea, ea + PAGE_SIZE, pa, flags, | 90 | if (htab_bolt_mapping(ea, (unsigned long)ea + PAGE_SIZE, |
| 106 | mmu_io_psize)) { | 91 | pa, flags, mmu_io_psize)) { |
| 107 | printk(KERN_ERR "Failed to do bolted mapping IO " | 92 | printk(KERN_ERR "Failed to do bolted mapping IO " |
| 108 | "memory at %016lx !\n", pa); | 93 | "memory at %016lx !\n", pa); |
| 109 | return -ENOMEM; | 94 | return -ENOMEM; |
| @@ -113,8 +98,11 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags) | |||
| 113 | } | 98 | } |
| 114 | 99 | ||
| 115 | 100 | ||
| 116 | static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa, | 101 | /** |
| 117 | unsigned long ea, unsigned long size, | 102 | * __ioremap_at - Low level function to establish the page tables |
| 103 | * for an IO mapping | ||
| 104 | */ | ||
| 105 | void __iomem * __ioremap_at(phys_addr_t pa, void *ea, unsigned long size, | ||
| 118 | unsigned long flags) | 106 | unsigned long flags) |
| 119 | { | 107 | { |
| 120 | unsigned long i; | 108 | unsigned long i; |
| @@ -122,17 +110,35 @@ static void __iomem * __ioremap_com(phys_addr_t addr, unsigned long pa, | |||
| 122 | if ((flags & _PAGE_PRESENT) == 0) | 110 | if ((flags & _PAGE_PRESENT) == 0) |
| 123 | flags |= pgprot_val(PAGE_KERNEL); | 111 | flags |= pgprot_val(PAGE_KERNEL); |
| 124 | 112 | ||
| 113 | WARN_ON(pa & ~PAGE_MASK); | ||
| 114 | WARN_ON(((unsigned long)ea) & ~PAGE_MASK); | ||
| 115 | WARN_ON(size & ~PAGE_MASK); | ||
| 116 | |||
| 125 | for (i = 0; i < size; i += PAGE_SIZE) | 117 | for (i = 0; i < size; i += PAGE_SIZE) |
| 126 | if (map_io_page(ea+i, pa+i, flags)) | 118 | if (map_io_page((unsigned long)ea+i, pa+i, flags)) |
| 127 | return NULL; | 119 | return NULL; |
| 128 | 120 | ||
| 129 | return (void __iomem *) (ea + (addr & ~PAGE_MASK)); | 121 | return (void __iomem *)ea; |
| 122 | } | ||
| 123 | |||
| 124 | /** | ||
| 125 | * __iounmap_from - Low level function to tear down the page tables | ||
| 126 | * for an IO mapping. This is used for mappings that | ||
| 127 | * are manipulated manually, like partial unmapping of | ||
| 128 | * PCI IOs or ISA space. | ||
| 129 | */ | ||
| 130 | void __iounmap_at(void *ea, unsigned long size) | ||
| 131 | { | ||
| 132 | WARN_ON(((unsigned long)ea) & ~PAGE_MASK); | ||
| 133 | WARN_ON(size & ~PAGE_MASK); | ||
| 134 | |||
| 135 | unmap_kernel_range((unsigned long)ea, size); | ||
| 130 | } | 136 | } |
| 131 | 137 | ||
| 132 | void __iomem * __ioremap(phys_addr_t addr, unsigned long size, | 138 | void __iomem * __ioremap(phys_addr_t addr, unsigned long size, |
| 133 | unsigned long flags) | 139 | unsigned long flags) |
| 134 | { | 140 | { |
| 135 | unsigned long pa, ea; | 141 | phys_addr_t paligned; |
| 136 | void __iomem *ret; | 142 | void __iomem *ret; |
| 137 | 143 | ||
| 138 | /* | 144 | /* |
| @@ -144,27 +150,30 @@ void __iomem * __ioremap(phys_addr_t addr, unsigned long size, | |||
| 144 | * IMALLOC_END | 150 | * IMALLOC_END |
| 145 | * | 151 | * |
| 146 | */ | 152 | */ |
| 147 | pa = addr & PAGE_MASK; | 153 | paligned = addr & PAGE_MASK; |
| 148 | size = PAGE_ALIGN(addr + size) - pa; | 154 | size = PAGE_ALIGN(addr + size) - paligned; |
| 149 | 155 | ||
| 150 | if ((size == 0) || (pa == 0)) | 156 | if ((size == 0) || (paligned == 0)) |
| 151 | return NULL; | 157 | return NULL; |
| 152 | 158 | ||
| 153 | if (mem_init_done) { | 159 | if (mem_init_done) { |
| 154 | struct vm_struct *area; | 160 | struct vm_struct *area; |
| 155 | area = im_get_free_area(size); | 161 | |
| 162 | area = __get_vm_area(size, VM_IOREMAP, | ||
| 163 | ioremap_bot, IOREMAP_END); | ||
| 156 | if (area == NULL) | 164 | if (area == NULL) |
| 157 | return NULL; | 165 | return NULL; |
| 158 | ea = (unsigned long)(area->addr); | 166 | ret = __ioremap_at(paligned, area->addr, size, flags); |
| 159 | ret = __ioremap_com(addr, pa, ea, size, flags); | ||
| 160 | if (!ret) | 167 | if (!ret) |
| 161 | im_free(area->addr); | 168 | vunmap(area->addr); |
| 162 | } else { | 169 | } else { |
| 163 | ea = ioremap_bot; | 170 | ret = __ioremap_at(paligned, (void *)ioremap_bot, size, flags); |
| 164 | ret = __ioremap_com(addr, pa, ea, size, flags); | ||
| 165 | if (ret) | 171 | if (ret) |
| 166 | ioremap_bot += size; | 172 | ioremap_bot += size; |
| 167 | } | 173 | } |
| 174 | |||
| 175 | if (ret) | ||
| 176 | ret += addr & ~PAGE_MASK; | ||
| 168 | return ret; | 177 | return ret; |
| 169 | } | 178 | } |
| 170 | 179 | ||
| @@ -187,62 +196,9 @@ void __iomem * ioremap_flags(phys_addr_t addr, unsigned long size, | |||
| 187 | } | 196 | } |
| 188 | 197 | ||
| 189 | 198 | ||
| 190 | #define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) | ||
| 191 | |||
| 192 | int __ioremap_explicit(phys_addr_t pa, unsigned long ea, | ||
| 193 | unsigned long size, unsigned long flags) | ||
| 194 | { | ||
| 195 | struct vm_struct *area; | ||
| 196 | void __iomem *ret; | ||
| 197 | |||
| 198 | /* For now, require page-aligned values for pa, ea, and size */ | ||
| 199 | if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) || | ||
| 200 | !IS_PAGE_ALIGNED(size)) { | ||
| 201 | printk(KERN_ERR "unaligned value in %s\n", __FUNCTION__); | ||
| 202 | return 1; | ||
| 203 | } | ||
| 204 | |||
| 205 | if (!mem_init_done) { | ||
| 206 | /* Two things to consider in this case: | ||
| 207 | * 1) No records will be kept (imalloc, etc) that the region | ||
| 208 | * has been remapped | ||
| 209 | * 2) It won't be easy to iounmap() the region later (because | ||
| 210 | * of 1) | ||
| 211 | */ | ||
| 212 | ; | ||
| 213 | } else { | ||
| 214 | area = im_get_area(ea, size, | ||
| 215 | IM_REGION_UNUSED|IM_REGION_SUBSET|IM_REGION_EXISTS); | ||
| 216 | if (area == NULL) { | ||
| 217 | /* Expected when PHB-dlpar is in play */ | ||
| 218 | return 1; | ||
| 219 | } | ||
| 220 | if (ea != (unsigned long) area->addr) { | ||
| 221 | printk(KERN_ERR "unexpected addr return from " | ||
| 222 | "im_get_area\n"); | ||
| 223 | return 1; | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 227 | ret = __ioremap_com(pa, pa, ea, size, flags); | ||
| 228 | if (ret == NULL) { | ||
| 229 | printk(KERN_ERR "ioremap_explicit() allocation failure !\n"); | ||
| 230 | return 1; | ||
| 231 | } | ||
| 232 | if (ret != (void *) ea) { | ||
| 233 | printk(KERN_ERR "__ioremap_com() returned unexpected addr\n"); | ||
| 234 | return 1; | ||
| 235 | } | ||
| 236 | |||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | /* | 199 | /* |
| 241 | * Unmap an IO region and remove it from imalloc'd list. | 200 | * Unmap an IO region and remove it from imalloc'd list. |
| 242 | * Access to IO memory should be serialized by driver. | 201 | * Access to IO memory should be serialized by driver. |
| 243 | * This code is modeled after vmalloc code - unmap_vm_area() | ||
| 244 | * | ||
| 245 | * XXX what about calls before mem_init_done (ie python_countermeasures()) | ||
| 246 | */ | 202 | */ |
| 247 | void __iounmap(volatile void __iomem *token) | 203 | void __iounmap(volatile void __iomem *token) |
| 248 | { | 204 | { |
| @@ -251,9 +207,14 @@ void __iounmap(volatile void __iomem *token) | |||
| 251 | if (!mem_init_done) | 207 | if (!mem_init_done) |
| 252 | return; | 208 | return; |
| 253 | 209 | ||
| 254 | addr = (void *) ((unsigned long __force) token & PAGE_MASK); | 210 | addr = (void *) ((unsigned long __force) |
| 255 | 211 | PCI_FIX_ADDR(token) & PAGE_MASK); | |
| 256 | im_free(addr); | 212 | if ((unsigned long)addr < ioremap_bot) { |
| 213 | printk(KERN_WARNING "Attempt to iounmap early bolted mapping" | ||
| 214 | " at 0x%p\n", addr); | ||
| 215 | return; | ||
| 216 | } | ||
| 217 | vunmap(addr); | ||
| 257 | } | 218 | } |
| 258 | 219 | ||
| 259 | void iounmap(volatile void __iomem *token) | 220 | void iounmap(volatile void __iomem *token) |
| @@ -264,77 +225,8 @@ void iounmap(volatile void __iomem *token) | |||
| 264 | __iounmap(token); | 225 | __iounmap(token); |
| 265 | } | 226 | } |
| 266 | 227 | ||
| 267 | static int iounmap_subset_regions(unsigned long addr, unsigned long size) | ||
| 268 | { | ||
| 269 | struct vm_struct *area; | ||
| 270 | |||
| 271 | /* Check whether subsets of this region exist */ | ||
| 272 | area = im_get_area(addr, size, IM_REGION_SUPERSET); | ||
| 273 | if (area == NULL) | ||
| 274 | return 1; | ||
| 275 | |||
| 276 | while (area) { | ||
| 277 | iounmap((void __iomem *) area->addr); | ||
| 278 | area = im_get_area(addr, size, | ||
| 279 | IM_REGION_SUPERSET); | ||
| 280 | } | ||
| 281 | |||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | |||
| 285 | int __iounmap_explicit(volatile void __iomem *start, unsigned long size) | ||
| 286 | { | ||
| 287 | struct vm_struct *area; | ||
| 288 | unsigned long addr; | ||
| 289 | int rc; | ||
| 290 | |||
| 291 | addr = (unsigned long __force) start & PAGE_MASK; | ||
| 292 | |||
| 293 | /* Verify that the region either exists or is a subset of an existing | ||
| 294 | * region. In the latter case, split the parent region to create | ||
| 295 | * the exact region | ||
| 296 | */ | ||
| 297 | area = im_get_area(addr, size, | ||
| 298 | IM_REGION_EXISTS | IM_REGION_SUBSET); | ||
| 299 | if (area == NULL) { | ||
| 300 | /* Determine whether subset regions exist. If so, unmap */ | ||
| 301 | rc = iounmap_subset_regions(addr, size); | ||
| 302 | if (rc) { | ||
| 303 | printk(KERN_ERR | ||
| 304 | "%s() cannot unmap nonexistent range 0x%lx\n", | ||
| 305 | __FUNCTION__, addr); | ||
| 306 | return 1; | ||
| 307 | } | ||
| 308 | } else { | ||
| 309 | iounmap((void __iomem *) area->addr); | ||
| 310 | } | ||
| 311 | /* | ||
| 312 | * FIXME! This can't be right: | ||
| 313 | iounmap(area->addr); | ||
| 314 | * Maybe it should be "iounmap(area);" | ||
| 315 | */ | ||
| 316 | return 0; | ||
| 317 | } | ||
| 318 | |||
| 319 | EXPORT_SYMBOL(ioremap); | 228 | EXPORT_SYMBOL(ioremap); |
| 320 | EXPORT_SYMBOL(ioremap_flags); | 229 | EXPORT_SYMBOL(ioremap_flags); |
| 321 | EXPORT_SYMBOL(__ioremap); | 230 | EXPORT_SYMBOL(__ioremap); |
| 322 | EXPORT_SYMBOL(iounmap); | 231 | EXPORT_SYMBOL(iounmap); |
| 323 | EXPORT_SYMBOL(__iounmap); | 232 | EXPORT_SYMBOL(__iounmap); |
| 324 | |||
| 325 | static DEFINE_SPINLOCK(phb_io_lock); | ||
| 326 | |||
| 327 | void __iomem * reserve_phb_iospace(unsigned long size) | ||
| 328 | { | ||
| 329 | void __iomem *virt_addr; | ||
| 330 | |||
| 331 | if (phbs_io_bot >= IMALLOC_BASE) | ||
| 332 | panic("reserve_phb_iospace(): phb io space overflow\n"); | ||
| 333 | |||
| 334 | spin_lock(&phb_io_lock); | ||
| 335 | virt_addr = (void __iomem *) phbs_io_bot; | ||
| 336 | phbs_io_bot += size; | ||
| 337 | spin_unlock(&phb_io_lock); | ||
| 338 | |||
| 339 | return virt_addr; | ||
| 340 | } | ||
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index ec1421a20aaa..5c45d474cfcc 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 13 | * Copyright (C) 1996 Paul Mackerras | 13 | * Copyright (C) 1996 Paul Mackerras |
| 14 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 15 | * | 14 | * |
| 16 | * Derived from "arch/i386/mm/init.c" | 15 | * Derived from "arch/i386/mm/init.c" |
| 17 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 16 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
| @@ -35,12 +34,12 @@ | |||
| 35 | 34 | ||
| 36 | #include "mmu_decl.h" | 35 | #include "mmu_decl.h" |
| 37 | 36 | ||
| 38 | PTE *Hash, *Hash_end; | 37 | struct hash_pte *Hash, *Hash_end; |
| 39 | unsigned long Hash_size, Hash_mask; | 38 | unsigned long Hash_size, Hash_mask; |
| 40 | unsigned long _SDR1; | 39 | unsigned long _SDR1; |
| 41 | 40 | ||
| 42 | union ubat { /* BAT register values to be loaded */ | 41 | union ubat { /* BAT register values to be loaded */ |
| 43 | BAT bat; | 42 | struct ppc_bat bat; |
| 44 | u32 word[2]; | 43 | u32 word[2]; |
| 45 | } BATS[8][2]; /* 8 pairs of IBAT, DBAT */ | 44 | } BATS[8][2]; /* 8 pairs of IBAT, DBAT */ |
| 46 | 45 | ||
| @@ -245,7 +244,7 @@ void __init MMU_init_hw(void) | |||
| 245 | cacheable_memzero(Hash, Hash_size); | 244 | cacheable_memzero(Hash, Hash_size); |
| 246 | _SDR1 = __pa(Hash) | SDR1_LOW_BITS; | 245 | _SDR1 = __pa(Hash) | SDR1_LOW_BITS; |
| 247 | 246 | ||
| 248 | Hash_end = (PTE *) ((unsigned long)Hash + Hash_size); | 247 | Hash_end = (struct hash_pte *) ((unsigned long)Hash + Hash_size); |
| 249 | 248 | ||
| 250 | printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", | 249 | printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n", |
| 251 | total_memory >> 20, Hash_size >> 10, Hash); | 250 | total_memory >> 20, Hash_size >> 10, Hash); |
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index 132c6bc66ce1..28492bbdee8e 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c | |||
| @@ -55,7 +55,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) | |||
| 55 | for (entry = 0; entry < 8; entry++, ste++) { | 55 | for (entry = 0; entry < 8; entry++, ste++) { |
| 56 | if (!(ste->esid_data & STE_ESID_V)) { | 56 | if (!(ste->esid_data & STE_ESID_V)) { |
| 57 | ste->vsid_data = vsid_data; | 57 | ste->vsid_data = vsid_data; |
| 58 | asm volatile("eieio":::"memory"); | 58 | eieio(); |
| 59 | ste->esid_data = esid_data; | 59 | ste->esid_data = esid_data; |
| 60 | return (global_entry | entry); | 60 | return (global_entry | entry); |
| 61 | } | 61 | } |
| @@ -101,7 +101,7 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) | |||
| 101 | asm volatile("sync" : : : "memory"); /* Order update */ | 101 | asm volatile("sync" : : : "memory"); /* Order update */ |
| 102 | 102 | ||
| 103 | castout_ste->vsid_data = vsid_data; | 103 | castout_ste->vsid_data = vsid_data; |
| 104 | asm volatile("eieio" : : : "memory"); /* Order update */ | 104 | eieio(); /* Order update */ |
| 105 | castout_ste->esid_data = esid_data; | 105 | castout_ste->esid_data = esid_data; |
| 106 | 106 | ||
| 107 | asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT)); | 107 | asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT)); |
diff --git a/arch/powerpc/mm/tlb_32.c b/arch/powerpc/mm/tlb_32.c index 6a69417cbc0e..06c7e77e097a 100644 --- a/arch/powerpc/mm/tlb_32.c +++ b/arch/powerpc/mm/tlb_32.c | |||
| @@ -11,7 +11,6 @@ | |||
| 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 11 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 12 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 13 | * Copyright (C) 1996 Paul Mackerras | 13 | * Copyright (C) 1996 Paul Mackerras |
| 14 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 15 | * | 14 | * |
| 16 | * Derived from "arch/i386/mm/init.c" | 15 | * Derived from "arch/i386/mm/init.c" |
| 17 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 16 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index 2bfc4d7e1aa2..cbd34fc813ee 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c | |||
| @@ -8,7 +8,6 @@ | |||
| 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) | 8 | * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au) |
| 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) | 9 | * and Cort Dougan (PReP) (cort@cs.nmt.edu) |
| 10 | * Copyright (C) 1996 Paul Mackerras | 10 | * Copyright (C) 1996 Paul Mackerras |
| 11 | * Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). | ||
| 12 | * | 11 | * |
| 13 | * Derived from "arch/i386/mm/init.c" | 12 | * Derived from "arch/i386/mm/init.c" |
| 14 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds | 13 | * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds |
| @@ -239,3 +238,59 @@ void pte_free_finish(void) | |||
| 239 | pte_free_submit(*batchp); | 238 | pte_free_submit(*batchp); |
| 240 | *batchp = NULL; | 239 | *batchp = NULL; |
| 241 | } | 240 | } |
| 241 | |||
| 242 | /** | ||
| 243 | * __flush_hash_table_range - Flush all HPTEs for a given address range | ||
| 244 | * from the hash table (and the TLB). But keeps | ||
| 245 | * the linux PTEs intact. | ||
| 246 | * | ||
| 247 | * @mm : mm_struct of the target address space (generally init_mm) | ||
| 248 | * @start : starting address | ||
| 249 | * @end : ending address (not included in the flush) | ||
| 250 | * | ||
| 251 | * This function is mostly to be used by some IO hotplug code in order | ||
| 252 | * to remove all hash entries from a given address range used to map IO | ||
| 253 | * space on a removed PCI-PCI bidge without tearing down the full mapping | ||
| 254 | * since 64K pages may overlap with other bridges when using 64K pages | ||
| 255 | * with 4K HW pages on IO space. | ||
| 256 | * | ||
| 257 | * Because of that usage pattern, it's only available with CONFIG_HOTPLUG | ||
| 258 | * and is implemented for small size rather than speed. | ||
| 259 | */ | ||
| 260 | #ifdef CONFIG_HOTPLUG | ||
| 261 | |||
| 262 | void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, | ||
| 263 | unsigned long end) | ||
| 264 | { | ||
| 265 | unsigned long flags; | ||
| 266 | |||
| 267 | start = _ALIGN_DOWN(start, PAGE_SIZE); | ||
| 268 | end = _ALIGN_UP(end, PAGE_SIZE); | ||
| 269 | |||
| 270 | BUG_ON(!mm->pgd); | ||
| 271 | |||
| 272 | /* Note: Normally, we should only ever use a batch within a | ||
| 273 | * PTE locked section. This violates the rule, but will work | ||
| 274 | * since we don't actually modify the PTEs, we just flush the | ||
| 275 | * hash while leaving the PTEs intact (including their reference | ||
| 276 | * to being hashed). This is not the most performance oriented | ||
| 277 | * way to do things but is fine for our needs here. | ||
| 278 | */ | ||
| 279 | local_irq_save(flags); | ||
| 280 | arch_enter_lazy_mmu_mode(); | ||
| 281 | for (; start < end; start += PAGE_SIZE) { | ||
| 282 | pte_t *ptep = find_linux_pte(mm->pgd, start); | ||
| 283 | unsigned long pte; | ||
| 284 | |||
| 285 | if (ptep == NULL) | ||
| 286 | continue; | ||
| 287 | pte = pte_val(*ptep); | ||
| 288 | if (!(pte & _PAGE_HASHPTE)) | ||
| 289 | continue; | ||
| 290 | hpte_need_flush(mm, start, ptep, pte, 0); | ||
| 291 | } | ||
| 292 | arch_leave_lazy_mmu_mode(); | ||
| 293 | local_irq_restore(flags); | ||
| 294 | } | ||
| 295 | |||
| 296 | #endif /* CONFIG_HOTPLUG */ | ||
