diff options
| author | David Gibson <david@gibson.dropbear.id.au> | 2005-05-05 19:15:13 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-05-05 19:36:32 -0400 |
| commit | 1f8d419e291f7f7f7f3ffd4f0ba00834621690c8 (patch) | |
| tree | 833df93032a38bc749458ce8be3a316eae1d5215 | |
| parent | e685752de107201432a055f7c45c396a5b04dc17 (diff) | |
[PATCH] ppc64: pgtable.h and other header cleanups
This patch started as simply removing a few never-used macros from
asm-ppc64/pgtable.h, then kind of grew. It now makes a bunch of
cleanups to the ppc64 low-level header files (with corresponding
changes to .c files where necessary) such as:
- Abolishing never-used macros
- Eliminating multiple #defines with the same purpose
- Removing pointless macros (cases where just expanding the
macro everywhere turns out clearer and more sensible)
- Removing some cases where macros which could be defined in
terms of each other weren't
- Moving imalloc() related definitions from pgtable.h to their
own header file (imalloc.h)
- Re-arranging headers to group things more logically
- Moving all VSID allocation related things to mmu.h, instead
of being split between mmu.h and mmu_context.h
- Removing some reserved space for flags from the PMD - we're
not using it.
- Fix some bugs which broke compile with STRICT_MM_TYPECHECKS.
Signed-off-by: David Gibson <dwg@au1.ibm.com>
Acked-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | arch/ppc64/kernel/pci.c | 2 | ||||
| -rw-r--r-- | arch/ppc64/mm/hash_native.c | 3 | ||||
| -rw-r--r-- | arch/ppc64/mm/hash_utils.c | 11 | ||||
| -rw-r--r-- | arch/ppc64/mm/imalloc.c | 5 | ||||
| -rw-r--r-- | arch/ppc64/mm/init.c | 1 | ||||
| -rw-r--r-- | arch/ppc64/mm/stab.c | 5 | ||||
| -rw-r--r-- | include/asm-ppc64/imalloc.h | 24 | ||||
| -rw-r--r-- | include/asm-ppc64/mmu.h | 193 | ||||
| -rw-r--r-- | include/asm-ppc64/mmu_context.h | 82 | ||||
| -rw-r--r-- | include/asm-ppc64/page.h | 15 | ||||
| -rw-r--r-- | include/asm-ppc64/pgtable.h | 117 |
11 files changed, 219 insertions, 239 deletions
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index be3cc387c1ec..d786d4b6af0b 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c | |||
| @@ -438,7 +438,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file, | |||
| 438 | int i; | 438 | int i; |
| 439 | 439 | ||
| 440 | if (page_is_ram(offset >> PAGE_SHIFT)) | 440 | if (page_is_ram(offset >> PAGE_SHIFT)) |
| 441 | return prot; | 441 | return __pgprot(prot); |
| 442 | 442 | ||
| 443 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; | 443 | prot |= _PAGE_NO_CACHE | _PAGE_GUARDED; |
| 444 | 444 | ||
diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c index 144657e0c3d5..52b6b9305341 100644 --- a/arch/ppc64/mm/hash_native.c +++ b/arch/ppc64/mm/hash_native.c | |||
| @@ -320,8 +320,7 @@ static void native_flush_hash_range(unsigned long context, | |||
| 320 | 320 | ||
| 321 | j = 0; | 321 | j = 0; |
| 322 | for (i = 0; i < number; i++) { | 322 | for (i = 0; i < number; i++) { |
| 323 | if ((batch->addr[i] >= USER_START) && | 323 | if (batch->addr[i] < KERNELBASE) |
| 324 | (batch->addr[i] <= USER_END)) | ||
| 325 | vsid = get_vsid(context, batch->addr[i]); | 324 | vsid = get_vsid(context, batch->addr[i]); |
| 326 | else | 325 | else |
| 327 | vsid = get_kernel_vsid(batch->addr[i]); | 326 | vsid = get_kernel_vsid(batch->addr[i]); |
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c index e48be12f518c..0a0f97008d02 100644 --- a/arch/ppc64/mm/hash_utils.c +++ b/arch/ppc64/mm/hash_utils.c | |||
| @@ -298,24 +298,23 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) | |||
| 298 | int local = 0; | 298 | int local = 0; |
| 299 | cpumask_t tmp; | 299 | cpumask_t tmp; |
| 300 | 300 | ||
| 301 | if ((ea & ~REGION_MASK) > EADDR_MASK) | ||
| 302 | return 1; | ||
| 303 | |||
| 301 | switch (REGION_ID(ea)) { | 304 | switch (REGION_ID(ea)) { |
| 302 | case USER_REGION_ID: | 305 | case USER_REGION_ID: |
| 303 | user_region = 1; | 306 | user_region = 1; |
| 304 | mm = current->mm; | 307 | mm = current->mm; |
| 305 | if ((ea > USER_END) || (! mm)) | 308 | if (! mm) |
| 306 | return 1; | 309 | return 1; |
| 307 | 310 | ||
| 308 | vsid = get_vsid(mm->context.id, ea); | 311 | vsid = get_vsid(mm->context.id, ea); |
| 309 | break; | 312 | break; |
| 310 | case IO_REGION_ID: | 313 | case IO_REGION_ID: |
| 311 | if (ea > IMALLOC_END) | ||
| 312 | return 1; | ||
| 313 | mm = &ioremap_mm; | 314 | mm = &ioremap_mm; |
| 314 | vsid = get_kernel_vsid(ea); | 315 | vsid = get_kernel_vsid(ea); |
| 315 | break; | 316 | break; |
| 316 | case VMALLOC_REGION_ID: | 317 | case VMALLOC_REGION_ID: |
| 317 | if (ea > VMALLOC_END) | ||
| 318 | return 1; | ||
| 319 | mm = &init_mm; | 318 | mm = &init_mm; |
| 320 | vsid = get_kernel_vsid(ea); | 319 | vsid = get_kernel_vsid(ea); |
| 321 | break; | 320 | break; |
| @@ -362,7 +361,7 @@ void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte, | |||
| 362 | unsigned long vsid, vpn, va, hash, secondary, slot; | 361 | unsigned long vsid, vpn, va, hash, secondary, slot; |
| 363 | unsigned long huge = pte_huge(pte); | 362 | unsigned long huge = pte_huge(pte); |
| 364 | 363 | ||
| 365 | if ((ea >= USER_START) && (ea <= USER_END)) | 364 | if (ea < KERNELBASE) |
| 366 | vsid = get_vsid(context, ea); | 365 | vsid = get_vsid(context, ea); |
| 367 | else | 366 | else |
| 368 | vsid = get_kernel_vsid(ea); | 367 | vsid = get_kernel_vsid(ea); |
diff --git a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c index 9d92b0d9cde5..cb8727f3267a 100644 --- a/arch/ppc64/mm/imalloc.c +++ b/arch/ppc64/mm/imalloc.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <asm/pgalloc.h> | 14 | #include <asm/pgalloc.h> |
| 15 | #include <asm/pgtable.h> | 15 | #include <asm/pgtable.h> |
| 16 | #include <asm/semaphore.h> | 16 | #include <asm/semaphore.h> |
| 17 | #include <asm/imalloc.h> | ||
| 17 | 18 | ||
| 18 | static DECLARE_MUTEX(imlist_sem); | 19 | static DECLARE_MUTEX(imlist_sem); |
| 19 | struct vm_struct * imlist = NULL; | 20 | struct vm_struct * imlist = NULL; |
| @@ -23,11 +24,11 @@ static int get_free_im_addr(unsigned long size, unsigned long *im_addr) | |||
| 23 | unsigned long addr; | 24 | unsigned long addr; |
| 24 | struct vm_struct **p, *tmp; | 25 | struct vm_struct **p, *tmp; |
| 25 | 26 | ||
| 26 | addr = IMALLOC_START; | 27 | addr = ioremap_bot; |
| 27 | for (p = &imlist; (tmp = *p) ; p = &tmp->next) { | 28 | for (p = &imlist; (tmp = *p) ; p = &tmp->next) { |
| 28 | if (size + addr < (unsigned long) tmp->addr) | 29 | if (size + addr < (unsigned long) tmp->addr) |
| 29 | break; | 30 | break; |
| 30 | if ((unsigned long)tmp->addr >= IMALLOC_START) | 31 | if ((unsigned long)tmp->addr >= ioremap_bot) |
| 31 | addr = tmp->size + (unsigned long) tmp->addr; | 32 | addr = tmp->size + (unsigned long) tmp->addr; |
| 32 | if (addr > IMALLOC_END-size) | 33 | if (addr > IMALLOC_END-size) |
| 33 | return 1; | 34 | return 1; |
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c index cf33d7ec2e29..afbf25227cb0 100644 --- a/arch/ppc64/mm/init.c +++ b/arch/ppc64/mm/init.c | |||
| @@ -64,6 +64,7 @@ | |||
| 64 | #include <asm/iommu.h> | 64 | #include <asm/iommu.h> |
| 65 | #include <asm/abs_addr.h> | 65 | #include <asm/abs_addr.h> |
| 66 | #include <asm/vdso.h> | 66 | #include <asm/vdso.h> |
| 67 | #include <asm/imalloc.h> | ||
| 67 | 68 | ||
| 68 | int mem_init_done; | 69 | int mem_init_done; |
| 69 | unsigned long ioremap_bot = IMALLOC_BASE; | 70 | unsigned long ioremap_bot = IMALLOC_BASE; |
diff --git a/arch/ppc64/mm/stab.c b/arch/ppc64/mm/stab.c index 31491131d5e4..df4bbe14153c 100644 --- a/arch/ppc64/mm/stab.c +++ b/arch/ppc64/mm/stab.c | |||
| @@ -19,6 +19,11 @@ | |||
| 19 | #include <asm/paca.h> | 19 | #include <asm/paca.h> |
| 20 | #include <asm/cputable.h> | 20 | #include <asm/cputable.h> |
| 21 | 21 | ||
| 22 | struct stab_entry { | ||
| 23 | unsigned long esid_data; | ||
| 24 | unsigned long vsid_data; | ||
| 25 | }; | ||
| 26 | |||
| 22 | /* Both the segment table and SLB code uses the following cache */ | 27 | /* Both the segment table and SLB code uses the following cache */ |
| 23 | #define NR_STAB_CACHE_ENTRIES 8 | 28 | #define NR_STAB_CACHE_ENTRIES 8 |
| 24 | DEFINE_PER_CPU(long, stab_cache_ptr); | 29 | DEFINE_PER_CPU(long, stab_cache_ptr); |
diff --git a/include/asm-ppc64/imalloc.h b/include/asm-ppc64/imalloc.h new file mode 100644 index 000000000000..3a45e918bf16 --- /dev/null +++ b/include/asm-ppc64/imalloc.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | #ifndef _PPC64_IMALLOC_H | ||
| 2 | #define _PPC64_IMALLOC_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | * Define the address range of the imalloc VM area. | ||
| 6 | */ | ||
| 7 | #define PHBS_IO_BASE IOREGIONBASE | ||
| 8 | #define IMALLOC_BASE (IOREGIONBASE + 0x80000000ul) /* Reserve 2 gigs for PHBs */ | ||
| 9 | #define IMALLOC_END (IOREGIONBASE + EADDR_MASK) | ||
| 10 | |||
| 11 | |||
| 12 | /* imalloc region types */ | ||
| 13 | #define IM_REGION_UNUSED 0x1 | ||
| 14 | #define IM_REGION_SUBSET 0x2 | ||
| 15 | #define IM_REGION_EXISTS 0x4 | ||
| 16 | #define IM_REGION_OVERLAP 0x8 | ||
| 17 | #define IM_REGION_SUPERSET 0x10 | ||
| 18 | |||
| 19 | extern struct vm_struct * im_get_free_area(unsigned long size); | ||
| 20 | extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, | ||
| 21 | int region_type); | ||
| 22 | unsigned long im_free(void *addr); | ||
| 23 | |||
| 24 | #endif /* _PPC64_IMALLOC_H */ | ||
diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h index 188987e9d9d4..c78282a67d8e 100644 --- a/include/asm-ppc64/mmu.h +++ b/include/asm-ppc64/mmu.h | |||
| @@ -15,19 +15,10 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/config.h> | 16 | #include <linux/config.h> |
| 17 | #include <asm/page.h> | 17 | #include <asm/page.h> |
| 18 | #include <linux/stringify.h> | ||
| 19 | 18 | ||
| 20 | #ifndef __ASSEMBLY__ | 19 | /* |
| 21 | 20 | * Segment table | |
| 22 | /* Time to allow for more things here */ | 21 | */ |
| 23 | typedef unsigned long mm_context_id_t; | ||
| 24 | typedef struct { | ||
| 25 | mm_context_id_t id; | ||
| 26 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 27 | pgd_t *huge_pgdir; | ||
| 28 | u16 htlb_segs; /* bitmask */ | ||
| 29 | #endif | ||
| 30 | } mm_context_t; | ||
| 31 | 22 | ||
| 32 | #define STE_ESID_V 0x80 | 23 | #define STE_ESID_V 0x80 |
| 33 | #define STE_ESID_KS 0x20 | 24 | #define STE_ESID_KS 0x20 |
| @@ -36,15 +27,48 @@ typedef struct { | |||
| 36 | 27 | ||
| 37 | #define STE_VSID_SHIFT 12 | 28 | #define STE_VSID_SHIFT 12 |
| 38 | 29 | ||
| 39 | struct stab_entry { | 30 | /* Location of cpu0's segment table */ |
| 40 | unsigned long esid_data; | 31 | #define STAB0_PAGE 0x9 |
| 41 | unsigned long vsid_data; | 32 | #define STAB0_PHYS_ADDR (STAB0_PAGE<<PAGE_SHIFT) |
| 42 | }; | 33 | #define STAB0_VIRT_ADDR (KERNELBASE+STAB0_PHYS_ADDR) |
| 34 | |||
| 35 | /* | ||
| 36 | * SLB | ||
| 37 | */ | ||
| 43 | 38 | ||
| 44 | /* Hardware Page Table Entry */ | 39 | #define SLB_NUM_BOLTED 3 |
| 40 | #define SLB_CACHE_ENTRIES 8 | ||
| 41 | |||
| 42 | /* Bits in the SLB ESID word */ | ||
| 43 | #define SLB_ESID_V ASM_CONST(0x0000000008000000) /* valid */ | ||
| 44 | |||
| 45 | /* Bits in the SLB VSID word */ | ||
| 46 | #define SLB_VSID_SHIFT 12 | ||
| 47 | #define SLB_VSID_KS ASM_CONST(0x0000000000000800) | ||
| 48 | #define SLB_VSID_KP ASM_CONST(0x0000000000000400) | ||
| 49 | #define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */ | ||
| 50 | #define SLB_VSID_L ASM_CONST(0x0000000000000100) /* largepage 16M */ | ||
| 51 | #define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */ | ||
| 52 | |||
| 53 | #define SLB_VSID_KERNEL (SLB_VSID_KP|SLB_VSID_C) | ||
| 54 | #define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS) | ||
| 55 | |||
| 56 | /* | ||
| 57 | * Hash table | ||
| 58 | */ | ||
| 45 | 59 | ||
| 46 | #define HPTES_PER_GROUP 8 | 60 | #define HPTES_PER_GROUP 8 |
| 47 | 61 | ||
| 62 | /* Values for PP (assumes Ks=0, Kp=1) */ | ||
| 63 | /* pp0 will always be 0 for linux */ | ||
| 64 | #define PP_RWXX 0 /* Supervisor read/write, User none */ | ||
| 65 | #define PP_RWRX 1 /* Supervisor read/write, User read */ | ||
| 66 | #define PP_RWRW 2 /* Supervisor read/write, User read/write */ | ||
| 67 | #define PP_RXRX 3 /* Supervisor read, User read */ | ||
| 68 | |||
| 69 | #ifndef __ASSEMBLY__ | ||
| 70 | |||
| 71 | /* Hardware Page Table Entry */ | ||
| 48 | typedef struct { | 72 | typedef struct { |
| 49 | unsigned long avpn:57; /* vsid | api == avpn */ | 73 | unsigned long avpn:57; /* vsid | api == avpn */ |
| 50 | unsigned long : 2; /* Software use */ | 74 | unsigned long : 2; /* Software use */ |
| @@ -90,14 +114,6 @@ typedef struct { | |||
| 90 | } dw1; | 114 | } dw1; |
| 91 | } HPTE; | 115 | } HPTE; |
| 92 | 116 | ||
| 93 | /* Values for PP (assumes Ks=0, Kp=1) */ | ||
| 94 | /* pp0 will always be 0 for linux */ | ||
| 95 | #define PP_RWXX 0 /* Supervisor read/write, User none */ | ||
| 96 | #define PP_RWRX 1 /* Supervisor read/write, User read */ | ||
| 97 | #define PP_RWRW 2 /* Supervisor read/write, User read/write */ | ||
| 98 | #define PP_RXRX 3 /* Supervisor read, User read */ | ||
| 99 | |||
| 100 | |||
| 101 | extern HPTE * htab_address; | 117 | extern HPTE * htab_address; |
| 102 | extern unsigned long htab_hash_mask; | 118 | extern unsigned long htab_hash_mask; |
| 103 | 119 | ||
| @@ -174,31 +190,70 @@ extern int __hash_page(unsigned long ea, unsigned long access, | |||
| 174 | 190 | ||
| 175 | extern void htab_finish_init(void); | 191 | extern void htab_finish_init(void); |
| 176 | 192 | ||
| 193 | extern void hpte_init_native(void); | ||
| 194 | extern void hpte_init_lpar(void); | ||
| 195 | extern void hpte_init_iSeries(void); | ||
| 196 | |||
| 197 | extern long pSeries_lpar_hpte_insert(unsigned long hpte_group, | ||
| 198 | unsigned long va, unsigned long prpn, | ||
| 199 | int secondary, unsigned long hpteflags, | ||
| 200 | int bolted, int large); | ||
| 201 | extern long native_hpte_insert(unsigned long hpte_group, unsigned long va, | ||
| 202 | unsigned long prpn, int secondary, | ||
| 203 | unsigned long hpteflags, int bolted, int large); | ||
| 204 | |||
| 177 | #endif /* __ASSEMBLY__ */ | 205 | #endif /* __ASSEMBLY__ */ |
| 178 | 206 | ||
| 179 | /* | 207 | /* |
| 180 | * Location of cpu0's segment table | 208 | * VSID allocation |
| 209 | * | ||
| 210 | * We first generate a 36-bit "proto-VSID". For kernel addresses this | ||
| 211 | * is equal to the ESID, for user addresses it is: | ||
| 212 | * (context << 15) | (esid & 0x7fff) | ||
| 213 | * | ||
| 214 | * The two forms are distinguishable because the top bit is 0 for user | ||
| 215 | * addresses, whereas the top two bits are 1 for kernel addresses. | ||
| 216 | * Proto-VSIDs with the top two bits equal to 0b10 are reserved for | ||
| 217 | * now. | ||
| 218 | * | ||
| 219 | * The proto-VSIDs are then scrambled into real VSIDs with the | ||
| 220 | * multiplicative hash: | ||
| 221 | * | ||
| 222 | * VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS | ||
| 223 | * where VSID_MULTIPLIER = 268435399 = 0xFFFFFC7 | ||
| 224 | * VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF | ||
| 225 | * | ||
| 226 | * This scramble is only well defined for proto-VSIDs below | ||
| 227 | * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are | ||
| 228 | * reserved. VSID_MULTIPLIER is prime, so in particular it is | ||
| 229 | * co-prime to VSID_MODULUS, making this a 1:1 scrambling function. | ||
| 230 | * Because the modulus is 2^n-1 we can compute it efficiently without | ||
| 231 | * a divide or extra multiply (see below). | ||
| 232 | * | ||
| 233 | * This scheme has several advantages over older methods: | ||
| 234 | * | ||
| 235 | * - We have VSIDs allocated for every kernel address | ||
| 236 | * (i.e. everything above 0xC000000000000000), except the very top | ||
| 237 | * segment, which simplifies several things. | ||
| 238 | * | ||
| 239 | * - We allow for 15 significant bits of ESID and 20 bits of | ||
| 240 | * context for user addresses. i.e. 8T (43 bits) of address space for | ||
| 241 | * up to 1M contexts (although the page table structure and context | ||
| 242 | * allocation will need changes to take advantage of this). | ||
| 243 | * | ||
| 244 | * - The scramble function gives robust scattering in the hash | ||
| 245 | * table (at least based on some initial results). The previous | ||
| 246 | * method was more susceptible to pathological cases giving excessive | ||
| 247 | * hash collisions. | ||
| 248 | */ | ||
| 249 | /* | ||
| 250 | * WARNING - If you change these you must make sure the asm | ||
| 251 | * implementations in slb_allocate (slb_low.S), do_stab_bolted | ||
| 252 | * (head.S) and ASM_VSID_SCRAMBLE (below) are changed accordingly. | ||
| 253 | * | ||
| 254 | * You'll also need to change the precomputed VSID values in head.S | ||
| 255 | * which are used by the iSeries firmware. | ||
| 181 | */ | 256 | */ |
| 182 | #define STAB0_PAGE 0x9 | ||
| 183 | #define STAB0_PHYS_ADDR (STAB0_PAGE<<PAGE_SHIFT) | ||
| 184 | #define STAB0_VIRT_ADDR (KERNELBASE+STAB0_PHYS_ADDR) | ||
| 185 | |||
| 186 | #define SLB_NUM_BOLTED 3 | ||
| 187 | #define SLB_CACHE_ENTRIES 8 | ||
| 188 | |||
| 189 | /* Bits in the SLB ESID word */ | ||
| 190 | #define SLB_ESID_V 0x0000000008000000 /* entry is valid */ | ||
| 191 | |||
| 192 | /* Bits in the SLB VSID word */ | ||
| 193 | #define SLB_VSID_SHIFT 12 | ||
| 194 | #define SLB_VSID_KS 0x0000000000000800 | ||
| 195 | #define SLB_VSID_KP 0x0000000000000400 | ||
| 196 | #define SLB_VSID_N 0x0000000000000200 /* no-execute */ | ||
| 197 | #define SLB_VSID_L 0x0000000000000100 /* largepage (4M) */ | ||
| 198 | #define SLB_VSID_C 0x0000000000000080 /* class */ | ||
| 199 | |||
| 200 | #define SLB_VSID_KERNEL (SLB_VSID_KP|SLB_VSID_C) | ||
| 201 | #define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS) | ||
| 202 | 257 | ||
| 203 | #define VSID_MULTIPLIER ASM_CONST(200730139) /* 28-bit prime */ | 258 | #define VSID_MULTIPLIER ASM_CONST(200730139) /* 28-bit prime */ |
| 204 | #define VSID_BITS 36 | 259 | #define VSID_BITS 36 |
| @@ -239,4 +294,50 @@ extern void htab_finish_init(void); | |||
| 239 | srdi rx,rx,VSID_BITS; /* extract 2^36 bit */ \ | 294 | srdi rx,rx,VSID_BITS; /* extract 2^36 bit */ \ |
| 240 | add rt,rt,rx | 295 | add rt,rt,rx |
| 241 | 296 | ||
| 297 | |||
| 298 | #ifndef __ASSEMBLY__ | ||
| 299 | |||
| 300 | typedef unsigned long mm_context_id_t; | ||
| 301 | |||
| 302 | typedef struct { | ||
| 303 | mm_context_id_t id; | ||
| 304 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 305 | pgd_t *huge_pgdir; | ||
| 306 | u16 htlb_segs; /* bitmask */ | ||
| 307 | #endif | ||
| 308 | } mm_context_t; | ||
| 309 | |||
| 310 | |||
| 311 | static inline unsigned long vsid_scramble(unsigned long protovsid) | ||
| 312 | { | ||
| 313 | #if 0 | ||
| 314 | /* The code below is equivalent to this function for arguments | ||
| 315 | * < 2^VSID_BITS, which is all this should ever be called | ||
| 316 | * with. However gcc is not clever enough to compute the | ||
| 317 | * modulus (2^n-1) without a second multiply. */ | ||
| 318 | return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS); | ||
| 319 | #else /* 1 */ | ||
| 320 | unsigned long x; | ||
| 321 | |||
| 322 | x = protovsid * VSID_MULTIPLIER; | ||
| 323 | x = (x >> VSID_BITS) + (x & VSID_MODULUS); | ||
| 324 | return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS; | ||
| 325 | #endif /* 1 */ | ||
| 326 | } | ||
| 327 | |||
| 328 | /* This is only valid for addresses >= KERNELBASE */ | ||
| 329 | static inline unsigned long get_kernel_vsid(unsigned long ea) | ||
| 330 | { | ||
| 331 | return vsid_scramble(ea >> SID_SHIFT); | ||
| 332 | } | ||
| 333 | |||
| 334 | /* This is only valid for user addresses (which are below 2^41) */ | ||
| 335 | static inline unsigned long get_vsid(unsigned long context, unsigned long ea) | ||
| 336 | { | ||
| 337 | return vsid_scramble((context << USER_ESID_BITS) | ||
| 338 | | (ea >> SID_SHIFT)); | ||
| 339 | } | ||
| 340 | |||
| 341 | #endif /* __ASSEMBLY */ | ||
| 342 | |||
| 242 | #endif /* _PPC64_MMU_H_ */ | 343 | #endif /* _PPC64_MMU_H_ */ |
diff --git a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h index c2e8e0466383..77a743402db4 100644 --- a/include/asm-ppc64/mmu_context.h +++ b/include/asm-ppc64/mmu_context.h | |||
| @@ -84,86 +84,4 @@ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) | |||
| 84 | local_irq_restore(flags); | 84 | local_irq_restore(flags); |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | /* VSID allocation | ||
| 88 | * =============== | ||
| 89 | * | ||
| 90 | * We first generate a 36-bit "proto-VSID". For kernel addresses this | ||
| 91 | * is equal to the ESID, for user addresses it is: | ||
| 92 | * (context << 15) | (esid & 0x7fff) | ||
| 93 | * | ||
| 94 | * The two forms are distinguishable because the top bit is 0 for user | ||
| 95 | * addresses, whereas the top two bits are 1 for kernel addresses. | ||
| 96 | * Proto-VSIDs with the top two bits equal to 0b10 are reserved for | ||
| 97 | * now. | ||
| 98 | * | ||
| 99 | * The proto-VSIDs are then scrambled into real VSIDs with the | ||
| 100 | * multiplicative hash: | ||
| 101 | * | ||
| 102 | * VSID = (proto-VSID * VSID_MULTIPLIER) % VSID_MODULUS | ||
| 103 | * where VSID_MULTIPLIER = 268435399 = 0xFFFFFC7 | ||
| 104 | * VSID_MODULUS = 2^36-1 = 0xFFFFFFFFF | ||
| 105 | * | ||
| 106 | * This scramble is only well defined for proto-VSIDs below | ||
| 107 | * 0xFFFFFFFFF, so both proto-VSID and actual VSID 0xFFFFFFFFF are | ||
| 108 | * reserved. VSID_MULTIPLIER is prime, so in particular it is | ||
| 109 | * co-prime to VSID_MODULUS, making this a 1:1 scrambling function. | ||
| 110 | * Because the modulus is 2^n-1 we can compute it efficiently without | ||
| 111 | * a divide or extra multiply (see below). | ||
| 112 | * | ||
| 113 | * This scheme has several advantages over older methods: | ||
| 114 | * | ||
| 115 | * - We have VSIDs allocated for every kernel address | ||
| 116 | * (i.e. everything above 0xC000000000000000), except the very top | ||
| 117 | * segment, which simplifies several things. | ||
| 118 | * | ||
| 119 | * - We allow for 15 significant bits of ESID and 20 bits of | ||
| 120 | * context for user addresses. i.e. 8T (43 bits) of address space for | ||
| 121 | * up to 1M contexts (although the page table structure and context | ||
| 122 | * allocation will need changes to take advantage of this). | ||
| 123 | * | ||
| 124 | * - The scramble function gives robust scattering in the hash | ||
| 125 | * table (at least based on some initial results). The previous | ||
| 126 | * method was more susceptible to pathological cases giving excessive | ||
| 127 | * hash collisions. | ||
| 128 | */ | ||
| 129 | |||
| 130 | /* | ||
| 131 | * WARNING - If you change these you must make sure the asm | ||
| 132 | * implementations in slb_allocate(), do_stab_bolted and mmu.h | ||
| 133 | * (ASM_VSID_SCRAMBLE macro) are changed accordingly. | ||
| 134 | * | ||
| 135 | * You'll also need to change the precomputed VSID values in head.S | ||
| 136 | * which are used by the iSeries firmware. | ||
| 137 | */ | ||
| 138 | |||
| 139 | static inline unsigned long vsid_scramble(unsigned long protovsid) | ||
| 140 | { | ||
| 141 | #if 0 | ||
| 142 | /* The code below is equivalent to this function for arguments | ||
| 143 | * < 2^VSID_BITS, which is all this should ever be called | ||
| 144 | * with. However gcc is not clever enough to compute the | ||
| 145 | * modulus (2^n-1) without a second multiply. */ | ||
| 146 | return ((protovsid * VSID_MULTIPLIER) % VSID_MODULUS); | ||
| 147 | #else /* 1 */ | ||
| 148 | unsigned long x; | ||
| 149 | |||
| 150 | x = protovsid * VSID_MULTIPLIER; | ||
| 151 | x = (x >> VSID_BITS) + (x & VSID_MODULUS); | ||
| 152 | return (x + ((x+1) >> VSID_BITS)) & VSID_MODULUS; | ||
| 153 | #endif /* 1 */ | ||
| 154 | } | ||
| 155 | |||
| 156 | /* This is only valid for addresses >= KERNELBASE */ | ||
| 157 | static inline unsigned long get_kernel_vsid(unsigned long ea) | ||
| 158 | { | ||
| 159 | return vsid_scramble(ea >> SID_SHIFT); | ||
| 160 | } | ||
| 161 | |||
| 162 | /* This is only valid for user addresses (which are below 2^41) */ | ||
| 163 | static inline unsigned long get_vsid(unsigned long context, unsigned long ea) | ||
| 164 | { | ||
| 165 | return vsid_scramble((context << USER_ESID_BITS) | ||
| 166 | | (ea >> SID_SHIFT)); | ||
| 167 | } | ||
| 168 | |||
| 169 | #endif /* __PPC64_MMU_CONTEXT_H */ | 87 | #endif /* __PPC64_MMU_CONTEXT_H */ |
diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h index 86219574c1a5..bcd21789d3b7 100644 --- a/include/asm-ppc64/page.h +++ b/include/asm-ppc64/page.h | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | #define PAGE_SHIFT 12 | 23 | #define PAGE_SHIFT 12 |
| 24 | #define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) | 24 | #define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) |
| 25 | #define PAGE_MASK (~(PAGE_SIZE-1)) | 25 | #define PAGE_MASK (~(PAGE_SIZE-1)) |
| 26 | #define PAGE_OFFSET_MASK (PAGE_SIZE-1) | ||
| 27 | 26 | ||
| 28 | #define SID_SHIFT 28 | 27 | #define SID_SHIFT 28 |
| 29 | #define SID_MASK 0xfffffffffUL | 28 | #define SID_MASK 0xfffffffffUL |
| @@ -85,9 +84,6 @@ | |||
| 85 | /* align addr on a size boundary - adjust address up if needed */ | 84 | /* align addr on a size boundary - adjust address up if needed */ |
| 86 | #define _ALIGN(addr,size) _ALIGN_UP(addr,size) | 85 | #define _ALIGN(addr,size) _ALIGN_UP(addr,size) |
| 87 | 86 | ||
| 88 | /* to align the pointer to the (next) double word boundary */ | ||
| 89 | #define DOUBLEWORD_ALIGN(addr) _ALIGN(addr,sizeof(unsigned long)) | ||
| 90 | |||
| 91 | /* to align the pointer to the (next) page boundary */ | 87 | /* to align the pointer to the (next) page boundary */ |
| 92 | #define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) | 88 | #define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) |
| 93 | 89 | ||
| @@ -100,7 +96,6 @@ | |||
| 100 | #define REGION_SIZE 4UL | 96 | #define REGION_SIZE 4UL |
| 101 | #define REGION_SHIFT 60UL | 97 | #define REGION_SHIFT 60UL |
| 102 | #define REGION_MASK (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT) | 98 | #define REGION_MASK (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT) |
| 103 | #define REGION_STRIDE (1UL << REGION_SHIFT) | ||
| 104 | 99 | ||
| 105 | static __inline__ void clear_page(void *addr) | 100 | static __inline__ void clear_page(void *addr) |
| 106 | { | 101 | { |
| @@ -209,13 +204,13 @@ extern u64 ppc64_pft_size; /* Log 2 of page table size */ | |||
| 209 | #define VMALLOCBASE ASM_CONST(0xD000000000000000) | 204 | #define VMALLOCBASE ASM_CONST(0xD000000000000000) |
| 210 | #define IOREGIONBASE ASM_CONST(0xE000000000000000) | 205 | #define IOREGIONBASE ASM_CONST(0xE000000000000000) |
| 211 | 206 | ||
| 212 | #define IO_REGION_ID (IOREGIONBASE>>REGION_SHIFT) | 207 | #define IO_REGION_ID (IOREGIONBASE >> REGION_SHIFT) |
| 213 | #define VMALLOC_REGION_ID (VMALLOCBASE>>REGION_SHIFT) | 208 | #define VMALLOC_REGION_ID (VMALLOCBASE >> REGION_SHIFT) |
| 214 | #define KERNEL_REGION_ID (KERNELBASE>>REGION_SHIFT) | 209 | #define KERNEL_REGION_ID (KERNELBASE >> REGION_SHIFT) |
| 215 | #define USER_REGION_ID (0UL) | 210 | #define USER_REGION_ID (0UL) |
| 216 | #define REGION_ID(X) (((unsigned long)(X))>>REGION_SHIFT) | 211 | #define REGION_ID(ea) (((unsigned long)(ea)) >> REGION_SHIFT) |
| 217 | 212 | ||
| 218 | #define __bpn_to_ba(x) ((((unsigned long)(x))<<PAGE_SHIFT) + KERNELBASE) | 213 | #define __bpn_to_ba(x) ((((unsigned long)(x)) << PAGE_SHIFT) + KERNELBASE) |
| 219 | #define __ba_to_bpn(x) ((((unsigned long)(x)) & ~REGION_MASK) >> PAGE_SHIFT) | 214 | #define __ba_to_bpn(x) ((((unsigned long)(x)) & ~REGION_MASK) >> PAGE_SHIFT) |
| 220 | 215 | ||
| 221 | #define __va(x) ((void *)((unsigned long)(x) + KERNELBASE)) | 216 | #define __va(x) ((void *)((unsigned long)(x) + KERNELBASE)) |
diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h index b984e2747e0c..264c4f7993be 100644 --- a/include/asm-ppc64/pgtable.h +++ b/include/asm-ppc64/pgtable.h | |||
| @@ -17,16 +17,6 @@ | |||
| 17 | 17 | ||
| 18 | #include <asm-generic/pgtable-nopud.h> | 18 | #include <asm-generic/pgtable-nopud.h> |
| 19 | 19 | ||
| 20 | /* PMD_SHIFT determines what a second-level page table entry can map */ | ||
| 21 | #define PMD_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3) | ||
| 22 | #define PMD_SIZE (1UL << PMD_SHIFT) | ||
| 23 | #define PMD_MASK (~(PMD_SIZE-1)) | ||
| 24 | |||
| 25 | /* PGDIR_SHIFT determines what a third-level page table entry can map */ | ||
| 26 | #define PGDIR_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - 3) + (PAGE_SHIFT - 2)) | ||
| 27 | #define PGDIR_SIZE (1UL << PGDIR_SHIFT) | ||
| 28 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | ||
| 29 | |||
| 30 | /* | 20 | /* |
| 31 | * Entries per page directory level. The PTE level must use a 64b record | 21 | * Entries per page directory level. The PTE level must use a 64b record |
| 32 | * for each page table entry. The PMD and PGD level use a 32b record for | 22 | * for each page table entry. The PMD and PGD level use a 32b record for |
| @@ -40,40 +30,30 @@ | |||
| 40 | #define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) | 30 | #define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) |
| 41 | #define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) | 31 | #define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) |
| 42 | 32 | ||
| 43 | #define USER_PTRS_PER_PGD (1024) | 33 | /* PMD_SHIFT determines what a second-level page table entry can map */ |
| 44 | #define FIRST_USER_ADDRESS 0 | 34 | #define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE) |
| 35 | #define PMD_SIZE (1UL << PMD_SHIFT) | ||
| 36 | #define PMD_MASK (~(PMD_SIZE-1)) | ||
| 45 | 37 | ||
| 46 | #define EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \ | 38 | /* PGDIR_SHIFT determines what a third-level page table entry can map */ |
| 47 | PGD_INDEX_SIZE + PAGE_SHIFT) | 39 | #define PGDIR_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE) |
| 40 | #define PGDIR_SIZE (1UL << PGDIR_SHIFT) | ||
| 41 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | ||
| 42 | |||
| 43 | #define FIRST_USER_ADDRESS 0 | ||
| 48 | 44 | ||
| 49 | /* | 45 | /* |
| 50 | * Size of EA range mapped by our pagetables. | 46 | * Size of EA range mapped by our pagetables. |
| 51 | */ | 47 | */ |
| 52 | #define PGTABLE_EA_BITS 41 | 48 | #define EADDR_SIZE (PTE_INDEX_SIZE + PMD_INDEX_SIZE + \ |
| 53 | #define PGTABLE_EA_MASK ((1UL<<PGTABLE_EA_BITS)-1) | 49 | PGD_INDEX_SIZE + PAGE_SHIFT) |
| 50 | #define EADDR_MASK ((1UL << EADDR_SIZE) - 1) | ||
| 54 | 51 | ||
| 55 | /* | 52 | /* |
| 56 | * Define the address range of the vmalloc VM area. | 53 | * Define the address range of the vmalloc VM area. |
| 57 | */ | 54 | */ |
| 58 | #define VMALLOC_START (0xD000000000000000ul) | 55 | #define VMALLOC_START (0xD000000000000000ul) |
| 59 | #define VMALLOC_END (VMALLOC_START + PGTABLE_EA_MASK) | 56 | #define VMALLOC_END (VMALLOC_START + EADDR_MASK) |
| 60 | |||
| 61 | /* | ||
| 62 | * Define the address range of the imalloc VM area. | ||
| 63 | * (used for ioremap) | ||
| 64 | */ | ||
| 65 | #define IMALLOC_START (ioremap_bot) | ||
| 66 | #define IMALLOC_VMADDR(x) ((unsigned long)(x)) | ||
| 67 | #define PHBS_IO_BASE (0xE000000000000000ul) /* Reserve 2 gigs for PHBs */ | ||
| 68 | #define IMALLOC_BASE (0xE000000080000000ul) | ||
| 69 | #define IMALLOC_END (IMALLOC_BASE + PGTABLE_EA_MASK) | ||
| 70 | |||
| 71 | /* | ||
| 72 | * Define the user address range | ||
| 73 | */ | ||
| 74 | #define USER_START (0UL) | ||
| 75 | #define USER_END (USER_START + PGTABLE_EA_MASK) | ||
| 76 | |||
| 77 | 57 | ||
| 78 | /* | 58 | /* |
| 79 | * Bits in a linux-style PTE. These match the bits in the | 59 | * Bits in a linux-style PTE. These match the bits in the |
| @@ -168,10 +148,6 @@ extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)]; | |||
| 168 | /* shift to put page number into pte */ | 148 | /* shift to put page number into pte */ |
| 169 | #define PTE_SHIFT (17) | 149 | #define PTE_SHIFT (17) |
| 170 | 150 | ||
| 171 | /* We allow 2^41 bytes of real memory, so we need 29 bits in the PMD | ||
| 172 | * to give the PTE page number. The bottom two bits are for flags. */ | ||
| 173 | #define PMD_TO_PTEPAGE_SHIFT (2) | ||
| 174 | |||
| 175 | #ifdef CONFIG_HUGETLB_PAGE | 151 | #ifdef CONFIG_HUGETLB_PAGE |
| 176 | 152 | ||
| 177 | #ifndef __ASSEMBLY__ | 153 | #ifndef __ASSEMBLY__ |
| @@ -200,13 +176,14 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm); | |||
| 200 | */ | 176 | */ |
| 201 | #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) | 177 | #define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) |
| 202 | 178 | ||
| 203 | #define pfn_pte(pfn,pgprot) \ | 179 | static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) |
| 204 | ({ \ | 180 | { |
| 205 | pte_t pte; \ | 181 | pte_t pte; |
| 206 | pte_val(pte) = ((unsigned long)(pfn) << PTE_SHIFT) | \ | 182 | |
| 207 | pgprot_val(pgprot); \ | 183 | |
| 208 | pte; \ | 184 | pte_val(pte) = (pfn << PTE_SHIFT) | pgprot_val(pgprot); |
| 209 | }) | 185 | return pte; |
| 186 | } | ||
| 210 | 187 | ||
| 211 | #define pte_modify(_pte, newprot) \ | 188 | #define pte_modify(_pte, newprot) \ |
| 212 | (__pte((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))) | 189 | (__pte((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))) |
| @@ -220,13 +197,12 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm); | |||
| 220 | #define pte_page(x) pfn_to_page(pte_pfn(x)) | 197 | #define pte_page(x) pfn_to_page(pte_pfn(x)) |
| 221 | 198 | ||
| 222 | #define pmd_set(pmdp, ptep) \ | 199 | #define pmd_set(pmdp, ptep) \ |
| 223 | (pmd_val(*(pmdp)) = (__ba_to_bpn(ptep) << PMD_TO_PTEPAGE_SHIFT)) | 200 | (pmd_val(*(pmdp)) = __ba_to_bpn(ptep)) |
| 224 | #define pmd_none(pmd) (!pmd_val(pmd)) | 201 | #define pmd_none(pmd) (!pmd_val(pmd)) |
| 225 | #define pmd_bad(pmd) (pmd_val(pmd) == 0) | 202 | #define pmd_bad(pmd) (pmd_val(pmd) == 0) |
| 226 | #define pmd_present(pmd) (pmd_val(pmd) != 0) | 203 | #define pmd_present(pmd) (pmd_val(pmd) != 0) |
| 227 | #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0) | 204 | #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0) |
| 228 | #define pmd_page_kernel(pmd) \ | 205 | #define pmd_page_kernel(pmd) (__bpn_to_ba(pmd_val(pmd))) |
| 229 | (__bpn_to_ba(pmd_val(pmd) >> PMD_TO_PTEPAGE_SHIFT)) | ||
| 230 | #define pmd_page(pmd) virt_to_page(pmd_page_kernel(pmd)) | 206 | #define pmd_page(pmd) virt_to_page(pmd_page_kernel(pmd)) |
| 231 | 207 | ||
| 232 | #define pud_set(pudp, pmdp) (pud_val(*(pudp)) = (__ba_to_bpn(pmdp))) | 208 | #define pud_set(pudp, pmdp) (pud_val(*(pudp)) = (__ba_to_bpn(pmdp))) |
| @@ -266,8 +242,6 @@ void hugetlb_mm_free_pgd(struct mm_struct *mm); | |||
| 266 | /* to find an entry in the ioremap page-table-directory */ | 242 | /* to find an entry in the ioremap page-table-directory */ |
| 267 | #define pgd_offset_i(address) (ioremap_pgd + pgd_index(address)) | 243 | #define pgd_offset_i(address) (ioremap_pgd + pgd_index(address)) |
| 268 | 244 | ||
| 269 | #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) | ||
| 270 | |||
| 271 | /* | 245 | /* |
| 272 | * The following only work if pte_present() is true. | 246 | * The following only work if pte_present() is true. |
| 273 | * Undefined behaviour if not.. | 247 | * Undefined behaviour if not.. |
| @@ -442,7 +416,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
| 442 | pte_clear(mm, addr, ptep); | 416 | pte_clear(mm, addr, ptep); |
| 443 | flush_tlb_pending(); | 417 | flush_tlb_pending(); |
| 444 | } | 418 | } |
| 445 | *ptep = __pte(pte_val(pte)) & ~_PAGE_HPTEFLAGS; | 419 | *ptep = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); |
| 446 | } | 420 | } |
| 447 | 421 | ||
| 448 | /* Set the dirty and/or accessed bits atomically in a linux PTE, this | 422 | /* Set the dirty and/or accessed bits atomically in a linux PTE, this |
| @@ -487,18 +461,13 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr, | |||
| 487 | 461 | ||
| 488 | extern unsigned long ioremap_bot, ioremap_base; | 462 | extern unsigned long ioremap_bot, ioremap_base; |
| 489 | 463 | ||
| 490 | #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT) | ||
| 491 | #define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS) | ||
| 492 | |||
| 493 | #define pte_ERROR(e) \ | ||
| 494 | printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e)) | ||
| 495 | #define pmd_ERROR(e) \ | 464 | #define pmd_ERROR(e) \ |
| 496 | printk("%s:%d: bad pmd %08x.\n", __FILE__, __LINE__, pmd_val(e)) | 465 | printk("%s:%d: bad pmd %08x.\n", __FILE__, __LINE__, pmd_val(e)) |
| 497 | #define pgd_ERROR(e) \ | 466 | #define pgd_ERROR(e) \ |
| 498 | printk("%s:%d: bad pgd %08x.\n", __FILE__, __LINE__, pgd_val(e)) | 467 | printk("%s:%d: bad pgd %08x.\n", __FILE__, __LINE__, pgd_val(e)) |
| 499 | 468 | ||
| 500 | extern pgd_t swapper_pg_dir[1024]; | 469 | extern pgd_t swapper_pg_dir[]; |
| 501 | extern pgd_t ioremap_dir[1024]; | 470 | extern pgd_t ioremap_dir[]; |
| 502 | 471 | ||
| 503 | extern void paging_init(void); | 472 | extern void paging_init(void); |
| 504 | 473 | ||
| @@ -540,43 +509,11 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); | |||
| 540 | */ | 509 | */ |
| 541 | #define kern_addr_valid(addr) (1) | 510 | #define kern_addr_valid(addr) (1) |
| 542 | 511 | ||
| 543 | #define io_remap_page_range(vma, vaddr, paddr, size, prot) \ | ||
| 544 | remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot) | ||
| 545 | |||
| 546 | #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ | 512 | #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ |
| 547 | remap_pfn_range(vma, vaddr, pfn, size, prot) | 513 | remap_pfn_range(vma, vaddr, pfn, size, prot) |
| 548 | 514 | ||
| 549 | #define MK_IOSPACE_PFN(space, pfn) (pfn) | ||
| 550 | #define GET_IOSPACE(pfn) 0 | ||
| 551 | #define GET_PFN(pfn) (pfn) | ||
| 552 | |||
| 553 | void pgtable_cache_init(void); | 515 | void pgtable_cache_init(void); |
| 554 | 516 | ||
| 555 | extern void hpte_init_native(void); | ||
| 556 | extern void hpte_init_lpar(void); | ||
| 557 | extern void hpte_init_iSeries(void); | ||
| 558 | |||
| 559 | /* imalloc region types */ | ||
| 560 | #define IM_REGION_UNUSED 0x1 | ||
| 561 | #define IM_REGION_SUBSET 0x2 | ||
| 562 | #define IM_REGION_EXISTS 0x4 | ||
| 563 | #define IM_REGION_OVERLAP 0x8 | ||
| 564 | #define IM_REGION_SUPERSET 0x10 | ||
| 565 | |||
| 566 | extern struct vm_struct * im_get_free_area(unsigned long size); | ||
| 567 | extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, | ||
| 568 | int region_type); | ||
| 569 | unsigned long im_free(void *addr); | ||
| 570 | |||
| 571 | extern long pSeries_lpar_hpte_insert(unsigned long hpte_group, | ||
| 572 | unsigned long va, unsigned long prpn, | ||
| 573 | int secondary, unsigned long hpteflags, | ||
| 574 | int bolted, int large); | ||
| 575 | |||
| 576 | extern long native_hpte_insert(unsigned long hpte_group, unsigned long va, | ||
| 577 | unsigned long prpn, int secondary, | ||
| 578 | unsigned long hpteflags, int bolted, int large); | ||
| 579 | |||
| 580 | /* | 517 | /* |
| 581 | * find_linux_pte returns the address of a linux pte for a given | 518 | * find_linux_pte returns the address of a linux pte for a given |
| 582 | * effective address and directory. If not found, it returns zero. | 519 | * effective address and directory. If not found, it returns zero. |
