| 1 |
|
| 2 | #ifndef _ASM_POWERPC_PGTABLE_H
|
| 3 | #define _ASM_POWERPC_PGTABLE_H
|
| 4 |
|
| 5 | #ifndef __ASSEMBLER__
|
| 6 | #include <linux/mmdebug.h>
|
| 7 | #include <linux/mmzone.h>
|
| 8 | #include <asm/processor.h>
|
| 9 | #include <asm/mmu.h>
|
| 10 | #include <asm/page.h>
|
| 11 | #include <asm/tlbflush.h>
|
| 12 |
|
| 13 | struct mm_struct;
|
| 14 |
|
| 15 | #endif
|
| 16 |
|
| 17 | #ifdef CONFIG_PPC_BOOK3S
|
| 18 | #include <asm/book3s/pgtable.h>
|
| 19 | #else
|
| 20 | #include <asm/nohash/pgtable.h>
|
| 21 | #endif
|
| 22 |
|
| 23 |
|
| 24 | #define PAGE_KERNEL_EXEC PAGE_KERNEL_X
|
| 25 |
|
| 26 |
|
| 27 | #define PAGE_AGP (PAGE_KERNEL_NC)
|
| 28 | #define HAVE_PAGE_AGP
|
| 29 |
|
| 30 | #ifndef __ASSEMBLER__
|
| 31 |
|
| 32 | #define PFN_PTE_SHIFT PTE_RPN_SHIFT
|
| 33 |
|
| 34 | void set_ptes(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
|
| 35 | pte_t pte, unsigned int nr);
|
| 36 | #define set_ptes set_ptes
|
| 37 | void set_pte_at_unchecked(struct mm_struct *mm, unsigned long addr,
|
| 38 | pte_t *ptep, pte_t pte);
|
| 39 | #define update_mmu_cache(vma, addr, ptep) \
|
| 40 | update_mmu_cache_range(NULL, vma, addr, ptep, 1)
|
| 41 |
|
| 42 | #ifndef MAX_PTRS_PER_PGD
|
| 43 | #define MAX_PTRS_PER_PGD PTRS_PER_PGD
|
| 44 | #endif
|
| 45 |
|
| 46 |
|
| 47 | #define pte_page(x) pfn_to_page(pte_pfn(x))
|
| 48 |
|
| 49 | static inline unsigned long pte_pfn(pte_t pte)
|
| 50 | {
|
| 51 | return (pte_val(pte) & PTE_RPN_MASK) >> PTE_RPN_SHIFT;
|
| 52 | }
|
| 53 |
|
| 54 | |
| 55 | * Select all bits except the pfn
|
| 56 |
|
| 57 | #define pte_pgprot pte_pgprot
|
| 58 | static inline pgprot_t pte_pgprot(pte_t pte)
|
| 59 | {
|
| 60 | unsigned long pte_flags;
|
| 61 |
|
| 62 | pte_flags = pte_val(pte) & ~PTE_RPN_MASK;
|
| 63 | return __pgprot(pte_flags);
|
| 64 | }
|
| 65 |
|
| 66 | #ifdef CONFIG_PPC64
|
| 67 | #define pmd_pgprot pmd_pgprot
|
| 68 | static inline pgprot_t pmd_pgprot(pmd_t pmd)
|
| 69 | {
|
| 70 | return pte_pgprot(pmd_pte(pmd));
|
| 71 | }
|
| 72 |
|
| 73 | #define pud_pgprot pud_pgprot
|
| 74 | static inline pgprot_t pud_pgprot(pud_t pud)
|
| 75 | {
|
| 76 | return pte_pgprot(pud_pte(pud));
|
| 77 | }
|
| 78 | #endif
|
| 79 |
|
| 80 | static inline pgprot_t pgprot_nx(pgprot_t prot)
|
| 81 | {
|
| 82 | return pte_pgprot(pte_exprotect(__pte(pgprot_val(prot))));
|
| 83 | }
|
| 84 | #define pgprot_nx pgprot_nx
|
| 85 |
|
| 86 | #ifndef pmd_page_vaddr
|
| 87 | static inline const void *pmd_page_vaddr(pmd_t pmd)
|
| 88 | {
|
| 89 | return __va(pmd_val(pmd) & ~PMD_MASKED_BITS);
|
| 90 | }
|
| 91 | #define pmd_page_vaddr pmd_page_vaddr
|
| 92 | #endif
|
| 93 |
|
| 94 | extern pgd_t swapper_pg_dir[];
|
| 95 |
|
| 96 | extern void paging_init(void);
|
| 97 | void poking_init(void);
|
| 98 |
|
| 99 | extern unsigned long ioremap_bot;
|
| 100 | extern const pgprot_t protection_map[16];
|
| 101 |
|
| 102 |
|
| 103 | unsigned long vmalloc_to_phys(void *vmalloc_addr);
|
| 104 |
|
| 105 | void pgtable_cache_add(unsigned int shift);
|
| 106 |
|
| 107 | #ifdef CONFIG_PPC32
|
| 108 | void __init *early_alloc_pgtable(unsigned long size);
|
| 109 | #endif
|
| 110 | pte_t *early_pte_alloc_kernel(pmd_t *pmdp, unsigned long va);
|
| 111 |
|
| 112 | #if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_PPC32)
|
| 113 | void mark_initmem_nx(void);
|
| 114 | #else
|
| 115 | static inline void mark_initmem_nx(void) { }
|
| 116 | #endif
|
| 117 |
|
| 118 | #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
|
| 119 | int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address,
|
| 120 | pte_t *ptep, pte_t entry, int dirty);
|
| 121 |
|
| 122 | pgprot_t __phys_mem_access_prot(unsigned long pfn, unsigned long size,
|
| 123 | pgprot_t vma_prot);
|
| 124 |
|
| 125 | struct file;
|
| 126 | static inline pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
|
| 127 | unsigned long size, pgprot_t vma_prot)
|
| 128 | {
|
| 129 | return __phys_mem_access_prot(pfn, size, vma_prot);
|
| 130 | }
|
| 131 | #define __HAVE_PHYS_MEM_ACCESS_PROT
|
| 132 |
|
| 133 | void __update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep);
|
| 134 |
|
| 135 | |
| 136 | * This gets called at the end of handling a page fault, when
|
| 137 | * the kernel has put a new PTE into the page table for the process.
|
| 138 | * We use it to ensure coherency between the i-cache and d-cache
|
| 139 | * for the page which has just been mapped in.
|
| 140 | * On machines which use an MMU hash table, we use this to put a
|
| 141 | * corresponding HPTE into the hash table ahead of time, instead of
|
| 142 | * waiting for the inevitable extra hash-table miss exception.
|
| 143 |
|
| 144 | static inline void update_mmu_cache_range(struct vm_fault *vmf,
|
| 145 | struct vm_area_struct *vma, unsigned long address,
|
| 146 | pte_t *ptep, unsigned int nr)
|
| 147 | {
|
| 148 | if ((mmu_has_feature(MMU_FTR_HPTE_TABLE) && !radix_enabled()) ||
|
| 149 | (IS_ENABLED(CONFIG_PPC_E500) && IS_ENABLED(CONFIG_HUGETLB_PAGE)))
|
| 150 | __update_mmu_cache(vma, address, ptep);
|
| 151 | }
|
| 152 |
|
| 153 | |
| 154 | * When used, PTE_FRAG_NR is defined in subarch pgtable.h
|
| 155 | * so we are sure it is included when arriving here.
|
| 156 |
|
| 157 | #ifdef PTE_FRAG_NR
|
| 158 | static inline void *pte_frag_get(mm_context_t *ctx)
|
| 159 | {
|
| 160 | return ctx->pte_frag;
|
| 161 | }
|
| 162 |
|
| 163 | static inline void pte_frag_set(mm_context_t *ctx, void *p)
|
| 164 | {
|
| 165 | ctx->pte_frag = p;
|
| 166 | }
|
| 167 | #else
|
| 168 | #define PTE_FRAG_NR 1
|
| 169 | #define PTE_FRAG_SIZE_SHIFT PAGE_SHIFT
|
| 170 | #define PTE_FRAG_SIZE (1UL << PTE_FRAG_SIZE_SHIFT)
|
| 171 |
|
| 172 | static inline void *pte_frag_get(mm_context_t *ctx)
|
| 173 | {
|
| 174 | return NULL;
|
| 175 | }
|
| 176 |
|
| 177 | static inline void pte_frag_set(mm_context_t *ctx, void *p)
|
| 178 | {
|
| 179 | }
|
| 180 | #endif
|
| 181 |
|
| 182 | #define pmd_pgtable pmd_pgtable
|
| 183 | static inline pgtable_t pmd_pgtable(pmd_t pmd)
|
| 184 | {
|
| 185 | return (pgtable_t)pmd_page_vaddr(pmd);
|
| 186 | }
|
| 187 |
|
| 188 | #ifdef CONFIG_PPC64
|
| 189 | int __meminit vmemmap_populated(unsigned long vmemmap_addr, int vmemmap_map_size);
|
| 190 | bool altmap_cross_boundary(struct vmem_altmap *altmap, unsigned long start,
|
| 191 | unsigned long page_size);
|
| 192 | |
| 193 | * mm/memory_hotplug.c:mhp_supports_memmap_on_memory goes into details
|
| 194 | * some of the restrictions. We don't check for PMD_SIZE because our
|
| 195 | * vmemmap allocation code can fallback correctly. The pageblock
|
| 196 | * alignment requirement is met using altmap->reserve blocks.
|
| 197 |
|
| 198 | #define arch_supports_memmap_on_memory arch_supports_memmap_on_memory
|
| 199 | static inline bool arch_supports_memmap_on_memory(unsigned long vmemmap_size)
|
| 200 | {
|
| 201 | if (!radix_enabled())
|
| 202 | return false;
|
| 203 | |
| 204 | * With 4K page size and 2M PMD_SIZE, we can align
|
| 205 | * things better with memory block size value
|
| 206 | * starting from 128MB. Hence align things with PMD_SIZE.
|
| 207 |
|
| 208 | if (IS_ENABLED(CONFIG_PPC_4K_PAGES))
|
| 209 | return IS_ALIGNED(vmemmap_size, PMD_SIZE);
|
| 210 | return true;
|
| 211 | }
|
| 212 |
|
| 213 | #endif
|
| 214 |
|
| 215 | #ifndef pmd_user_accessible_page
|
| 216 | #define pmd_user_accessible_page(mm, addr, pmd) false
|
| 217 | #endif
|
| 218 |
|
| 219 | #ifndef pud_user_accessible_page
|
| 220 | #define pud_user_accessible_page(mm, addr, pud) false
|
| 221 | #endif
|
| 222 |
|
| 223 | #endif
|
| 224 |
|
| 225 | #endif
|