0001
0002 #ifndef _ASM_POWERPC_PGTABLE_RADIX_H
0003 #define _ASM_POWERPC_PGTABLE_RADIX_H
0004
0005 #include <asm/asm-const.h>
0006
0007 #ifndef __ASSEMBLY__
0008 #include <asm/cmpxchg.h>
0009 #endif
0010
0011 #ifdef CONFIG_PPC_64K_PAGES
0012 #include <asm/book3s/64/radix-64k.h>
0013 #else
0014 #include <asm/book3s/64/radix-4k.h>
0015 #endif
0016
0017 #ifndef __ASSEMBLY__
0018 #include <asm/book3s/64/tlbflush-radix.h>
0019 #include <asm/cpu_has_feature.h>
0020 #endif
0021
0022
0023 #define RADIX_PTE_NONE_MASK (_PAGE_DIRTY | _PAGE_ACCESSED)
0024
0025
0026 #define RADIX_PMD_VAL_BITS (0x8000000000000000UL | RADIX_PTE_INDEX_SIZE)
0027 #define RADIX_PUD_VAL_BITS (0x8000000000000000UL | RADIX_PMD_INDEX_SIZE)
0028 #define RADIX_PGD_VAL_BITS (0x8000000000000000UL | RADIX_PUD_INDEX_SIZE)
0029
0030
0031 #define RADIX_PMD_BAD_BITS 0x60000000000000e0UL
0032 #define RADIX_PUD_BAD_BITS 0x60000000000000e0UL
0033 #define RADIX_P4D_BAD_BITS 0x60000000000000e0UL
0034
0035 #define RADIX_PMD_SHIFT (PAGE_SHIFT + RADIX_PTE_INDEX_SIZE)
0036 #define RADIX_PUD_SHIFT (RADIX_PMD_SHIFT + RADIX_PMD_INDEX_SIZE)
0037 #define RADIX_PGD_SHIFT (RADIX_PUD_SHIFT + RADIX_PUD_INDEX_SIZE)
0038
0039 #define R_PTRS_PER_PTE (1 << RADIX_PTE_INDEX_SIZE)
0040 #define R_PTRS_PER_PMD (1 << RADIX_PMD_INDEX_SIZE)
0041 #define R_PTRS_PER_PUD (1 << RADIX_PUD_INDEX_SIZE)
0042
0043
0044
0045
0046 #define RADIX_PGTABLE_EADDR_SIZE (RADIX_PTE_INDEX_SIZE + RADIX_PMD_INDEX_SIZE + \
0047 RADIX_PUD_INDEX_SIZE + RADIX_PGD_INDEX_SIZE + PAGE_SHIFT)
0048 #define RADIX_PGTABLE_RANGE (ASM_CONST(1) << RADIX_PGTABLE_EADDR_SIZE)
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110 #if defined(CONFIG_SPARSEMEM_VMEMMAP) && defined(CONFIG_SPARSEMEM_EXTREME)
0111 #define R_MAX_PHYSMEM_BITS 51
0112 #else
0113 #define R_MAX_PHYSMEM_BITS 46
0114 #endif
0115
0116 #define RADIX_KERN_VIRT_START ASM_CONST(0xc008000000000000)
0117
0118
0119
0120
0121 #define RADIX_KERN_MAP_SIZE (1UL << 49)
0122
0123 #define RADIX_VMALLOC_START RADIX_KERN_VIRT_START
0124 #define RADIX_VMALLOC_SIZE RADIX_KERN_MAP_SIZE
0125 #define RADIX_VMALLOC_END (RADIX_VMALLOC_START + RADIX_VMALLOC_SIZE)
0126
0127 #define RADIX_KERN_IO_START RADIX_VMALLOC_END
0128 #define RADIX_KERN_IO_SIZE RADIX_KERN_MAP_SIZE
0129 #define RADIX_KERN_IO_END (RADIX_KERN_IO_START + RADIX_KERN_IO_SIZE)
0130
0131 #define RADIX_VMEMMAP_START RADIX_KERN_IO_END
0132 #define RADIX_VMEMMAP_SIZE RADIX_KERN_MAP_SIZE
0133 #define RADIX_VMEMMAP_END (RADIX_VMEMMAP_START + RADIX_VMEMMAP_SIZE)
0134
0135 #ifndef __ASSEMBLY__
0136 #define RADIX_PTE_TABLE_SIZE (sizeof(pte_t) << RADIX_PTE_INDEX_SIZE)
0137 #define RADIX_PMD_TABLE_SIZE (sizeof(pmd_t) << RADIX_PMD_INDEX_SIZE)
0138 #define RADIX_PUD_TABLE_SIZE (sizeof(pud_t) << RADIX_PUD_INDEX_SIZE)
0139 #define RADIX_PGD_TABLE_SIZE (sizeof(pgd_t) << RADIX_PGD_INDEX_SIZE)
0140
0141 #ifdef CONFIG_STRICT_KERNEL_RWX
0142 extern void radix__mark_rodata_ro(void);
0143 extern void radix__mark_initmem_nx(void);
0144 #endif
0145
0146 extern void radix__ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep,
0147 pte_t entry, unsigned long address,
0148 int psize);
0149
0150 extern void radix__ptep_modify_prot_commit(struct vm_area_struct *vma,
0151 unsigned long addr, pte_t *ptep,
0152 pte_t old_pte, pte_t pte);
0153
0154 static inline unsigned long __radix_pte_update(pte_t *ptep, unsigned long clr,
0155 unsigned long set)
0156 {
0157 __be64 old_be, tmp_be;
0158
0159 __asm__ __volatile__(
0160 "1: ldarx %0,0,%3 # pte_update\n"
0161 " andc %1,%0,%5 \n"
0162 " or %1,%1,%4 \n"
0163 " stdcx. %1,0,%3 \n"
0164 " bne- 1b"
0165 : "=&r" (old_be), "=&r" (tmp_be), "=m" (*ptep)
0166 : "r" (ptep), "r" (cpu_to_be64(set)), "r" (cpu_to_be64(clr))
0167 : "cc" );
0168
0169 return be64_to_cpu(old_be);
0170 }
0171
0172 static inline unsigned long radix__pte_update(struct mm_struct *mm,
0173 unsigned long addr,
0174 pte_t *ptep, unsigned long clr,
0175 unsigned long set,
0176 int huge)
0177 {
0178 unsigned long old_pte;
0179
0180 old_pte = __radix_pte_update(ptep, clr, set);
0181 if (!huge)
0182 assert_pte_locked(mm, addr);
0183
0184 return old_pte;
0185 }
0186
0187 static inline pte_t radix__ptep_get_and_clear_full(struct mm_struct *mm,
0188 unsigned long addr,
0189 pte_t *ptep, int full)
0190 {
0191 unsigned long old_pte;
0192
0193 if (full) {
0194 old_pte = pte_val(*ptep);
0195 *ptep = __pte(0);
0196 } else
0197 old_pte = radix__pte_update(mm, addr, ptep, ~0ul, 0, 0);
0198
0199 return __pte(old_pte);
0200 }
0201
0202 static inline int radix__pte_same(pte_t pte_a, pte_t pte_b)
0203 {
0204 return ((pte_raw(pte_a) ^ pte_raw(pte_b)) == 0);
0205 }
0206
0207 static inline int radix__pte_none(pte_t pte)
0208 {
0209 return (pte_val(pte) & ~RADIX_PTE_NONE_MASK) == 0;
0210 }
0211
0212 static inline void radix__set_pte_at(struct mm_struct *mm, unsigned long addr,
0213 pte_t *ptep, pte_t pte, int percpu)
0214 {
0215 *ptep = pte;
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236 }
0237
0238 static inline int radix__pmd_bad(pmd_t pmd)
0239 {
0240 return !!(pmd_val(pmd) & RADIX_PMD_BAD_BITS);
0241 }
0242
0243 static inline int radix__pmd_same(pmd_t pmd_a, pmd_t pmd_b)
0244 {
0245 return ((pmd_raw(pmd_a) ^ pmd_raw(pmd_b)) == 0);
0246 }
0247
0248 static inline int radix__pud_bad(pud_t pud)
0249 {
0250 return !!(pud_val(pud) & RADIX_PUD_BAD_BITS);
0251 }
0252
0253
0254 static inline int radix__p4d_bad(p4d_t p4d)
0255 {
0256 return !!(p4d_val(p4d) & RADIX_P4D_BAD_BITS);
0257 }
0258
0259 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
0260
0261 static inline int radix__pmd_trans_huge(pmd_t pmd)
0262 {
0263 return (pmd_val(pmd) & (_PAGE_PTE | _PAGE_DEVMAP)) == _PAGE_PTE;
0264 }
0265
0266 static inline pmd_t radix__pmd_mkhuge(pmd_t pmd)
0267 {
0268 return __pmd(pmd_val(pmd) | _PAGE_PTE);
0269 }
0270
0271 extern unsigned long radix__pmd_hugepage_update(struct mm_struct *mm, unsigned long addr,
0272 pmd_t *pmdp, unsigned long clr,
0273 unsigned long set);
0274 extern pmd_t radix__pmdp_collapse_flush(struct vm_area_struct *vma,
0275 unsigned long address, pmd_t *pmdp);
0276 extern void radix__pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
0277 pgtable_t pgtable);
0278 extern pgtable_t radix__pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
0279 extern pmd_t radix__pmdp_huge_get_and_clear(struct mm_struct *mm,
0280 unsigned long addr, pmd_t *pmdp);
0281 static inline int radix__has_transparent_hugepage(void)
0282 {
0283
0284 if (mmu_psize_defs[MMU_PAGE_2M].shift == PMD_SHIFT)
0285 return 1;
0286 return 0;
0287 }
0288 #endif
0289
0290 static inline pmd_t radix__pmd_mkdevmap(pmd_t pmd)
0291 {
0292 return __pmd(pmd_val(pmd) | (_PAGE_PTE | _PAGE_DEVMAP));
0293 }
0294
0295 extern int __meminit radix__vmemmap_create_mapping(unsigned long start,
0296 unsigned long page_size,
0297 unsigned long phys);
0298 extern void radix__vmemmap_remove_mapping(unsigned long start,
0299 unsigned long page_size);
0300
0301 extern int radix__map_kernel_page(unsigned long ea, unsigned long pa,
0302 pgprot_t flags, unsigned int psz);
0303
0304 static inline unsigned long radix__get_tree_size(void)
0305 {
0306 unsigned long rts_field;
0307
0308
0309
0310
0311
0312
0313
0314 rts_field = (0x5UL << 5);
0315 rts_field |= (0x2UL << 61);
0316
0317 return rts_field;
0318 }
0319
0320 #ifdef CONFIG_MEMORY_HOTPLUG
0321 int radix__create_section_mapping(unsigned long start, unsigned long end,
0322 int nid, pgprot_t prot);
0323 int radix__remove_section_mapping(unsigned long start, unsigned long end);
0324 #endif
0325
0326 void radix__kernel_map_pages(struct page *page, int numpages, int enable);
0327
0328 #endif
0329 #endif