| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|---|
| 1 | 2 | #ifndef _ASM_POWERPC_PAGE_H |
|---|
| 2 | 3 | #define _ASM_POWERPC_PAGE_H |
|---|
| 3 | 4 | |
|---|
| 4 | 5 | /* |
|---|
| 5 | 6 | * Copyright (C) 2001,2005 IBM Corporation. |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or |
|---|
| 8 | | - * modify it under the terms of the GNU General Public License |
|---|
| 9 | | - * as published by the Free Software Foundation; either version |
|---|
| 10 | | - * 2 of the License, or (at your option) any later version. |
|---|
| 11 | 7 | */ |
|---|
| 12 | 8 | |
|---|
| 13 | 9 | #ifndef __ASSEMBLY__ |
|---|
| .. | .. |
|---|
| 20 | 16 | |
|---|
| 21 | 17 | /* |
|---|
| 22 | 18 | * On regular PPC32 page size is 4K (but we support 4K/16K/64K/256K pages |
|---|
| 23 | | - * on PPC44x). For PPC64 we support either 4K or 64K software |
|---|
| 19 | + * on PPC44x and 4K/16K on 8xx). For PPC64 we support either 4K or 64K software |
|---|
| 24 | 20 | * page size. When using 64K pages however, whether we are really supporting |
|---|
| 25 | 21 | * 64K pages in HW or not is irrelevant to those definitions. |
|---|
| 26 | 22 | */ |
|---|
| 27 | | -#if defined(CONFIG_PPC_256K_PAGES) |
|---|
| 28 | | -#define PAGE_SHIFT 18 |
|---|
| 29 | | -#elif defined(CONFIG_PPC_64K_PAGES) |
|---|
| 30 | | -#define PAGE_SHIFT 16 |
|---|
| 31 | | -#elif defined(CONFIG_PPC_16K_PAGES) |
|---|
| 32 | | -#define PAGE_SHIFT 14 |
|---|
| 33 | | -#else |
|---|
| 34 | | -#define PAGE_SHIFT 12 |
|---|
| 35 | | -#endif |
|---|
| 36 | | - |
|---|
| 23 | +#define PAGE_SHIFT CONFIG_PPC_PAGE_SHIFT |
|---|
| 37 | 24 | #define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) |
|---|
| 38 | 25 | |
|---|
| 39 | 26 | #ifndef __ASSEMBLY__ |
|---|
| 40 | | -#ifdef CONFIG_HUGETLB_PAGE |
|---|
| 41 | | -extern bool hugetlb_disabled; |
|---|
| 42 | | -extern unsigned int HPAGE_SHIFT; |
|---|
| 43 | | -#else |
|---|
| 27 | +#ifndef CONFIG_HUGETLB_PAGE |
|---|
| 44 | 28 | #define HPAGE_SHIFT PAGE_SHIFT |
|---|
| 29 | +#elif defined(CONFIG_PPC_BOOK3S_64) |
|---|
| 30 | +extern unsigned int hpage_shift; |
|---|
| 31 | +#define HPAGE_SHIFT hpage_shift |
|---|
| 32 | +#elif defined(CONFIG_PPC_8xx) |
|---|
| 33 | +#define HPAGE_SHIFT 19 /* 512k pages */ |
|---|
| 34 | +#elif defined(CONFIG_PPC_FSL_BOOK3E) |
|---|
| 35 | +#define HPAGE_SHIFT 22 /* 4M pages */ |
|---|
| 45 | 36 | #endif |
|---|
| 46 | 37 | #define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) |
|---|
| 47 | 38 | #define HPAGE_MASK (~(HPAGE_SIZE - 1)) |
|---|
| .. | .. |
|---|
| 141 | 132 | #define virt_to_page(kaddr) pfn_to_page(virt_to_pfn(kaddr)) |
|---|
| 142 | 133 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) |
|---|
| 143 | 134 | |
|---|
| 144 | | -#ifdef CONFIG_PPC_BOOK3S_64 |
|---|
| 145 | | -/* |
|---|
| 146 | | - * On hash the vmalloc and other regions alias to the kernel region when passed |
|---|
| 147 | | - * through __pa(), which virt_to_pfn() uses. That means virt_addr_valid() can |
|---|
| 148 | | - * return true for some vmalloc addresses, which is incorrect. So explicitly |
|---|
| 149 | | - * check that the address is in the kernel region. |
|---|
| 150 | | - */ |
|---|
| 151 | | -#define virt_addr_valid(kaddr) (REGION_ID(kaddr) == KERNEL_REGION_ID && \ |
|---|
| 152 | | - pfn_valid(virt_to_pfn(kaddr))) |
|---|
| 153 | | -#else |
|---|
| 154 | | -#define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr)) |
|---|
| 155 | | -#endif |
|---|
| 135 | +#define virt_addr_valid(vaddr) ({ \ |
|---|
| 136 | + unsigned long _addr = (unsigned long)vaddr; \ |
|---|
| 137 | + _addr >= PAGE_OFFSET && _addr < (unsigned long)high_memory && \ |
|---|
| 138 | + pfn_valid(virt_to_pfn(_addr)); \ |
|---|
| 139 | +}) |
|---|
| 156 | 140 | |
|---|
| 157 | 141 | /* |
|---|
| 158 | 142 | * On Book-E parts we need __va to parse the device tree and we can't |
|---|
| .. | .. |
|---|
| 229 | 213 | */ |
|---|
| 230 | 214 | #if defined(CONFIG_PPC32) && defined(CONFIG_BOOKE) |
|---|
| 231 | 215 | #define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + VIRT_PHYS_OFFSET)) |
|---|
| 232 | | -#define __pa(x) ((unsigned long)(x) - VIRT_PHYS_OFFSET) |
|---|
| 216 | +#define __pa(x) ((phys_addr_t)(unsigned long)(x) - VIRT_PHYS_OFFSET) |
|---|
| 233 | 217 | #else |
|---|
| 234 | 218 | #ifdef CONFIG_PPC64 |
|---|
| 219 | + |
|---|
| 220 | +#define VIRTUAL_WARN_ON(x) WARN_ON(IS_ENABLED(CONFIG_DEBUG_VIRTUAL) && (x)) |
|---|
| 221 | + |
|---|
| 235 | 222 | /* |
|---|
| 236 | 223 | * gcc miscompiles (unsigned long)(&static_var) - PAGE_OFFSET |
|---|
| 237 | 224 | * with -mcmodel=medium, so we use & and | instead of - and + on 64-bit. |
|---|
| 225 | + * This also results in better code generation. |
|---|
| 238 | 226 | */ |
|---|
| 239 | | -#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) | PAGE_OFFSET)) |
|---|
| 240 | | -#define __pa(x) ((unsigned long)(x) & 0x0fffffffffffffffUL) |
|---|
| 227 | +#define __va(x) \ |
|---|
| 228 | +({ \ |
|---|
| 229 | + VIRTUAL_WARN_ON((unsigned long)(x) >= PAGE_OFFSET); \ |
|---|
| 230 | + (void *)(unsigned long)((phys_addr_t)(x) | PAGE_OFFSET); \ |
|---|
| 231 | +}) |
|---|
| 232 | + |
|---|
| 233 | +#define __pa(x) \ |
|---|
| 234 | +({ \ |
|---|
| 235 | + VIRTUAL_WARN_ON((unsigned long)(x) < PAGE_OFFSET); \ |
|---|
| 236 | + (unsigned long)(x) & 0x0fffffffffffffffUL; \ |
|---|
| 237 | +}) |
|---|
| 241 | 238 | |
|---|
| 242 | 239 | #else /* 32-bit, non book E */ |
|---|
| 243 | 240 | #define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + PAGE_OFFSET - MEMORY_START)) |
|---|
| .. | .. |
|---|
| 250 | 247 | * and needs to be executable. This means the whole heap ends |
|---|
| 251 | 248 | * up being executable. |
|---|
| 252 | 249 | */ |
|---|
| 253 | | -#define VM_DATA_DEFAULT_FLAGS32 \ |
|---|
| 254 | | - (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \ |
|---|
| 255 | | - VM_READ | VM_WRITE | \ |
|---|
| 256 | | - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
|---|
| 257 | | - |
|---|
| 258 | | -#define VM_DATA_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \ |
|---|
| 259 | | - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
|---|
| 250 | +#define VM_DATA_DEFAULT_FLAGS32 VM_DATA_FLAGS_TSK_EXEC |
|---|
| 251 | +#define VM_DATA_DEFAULT_FLAGS64 VM_DATA_FLAGS_NON_EXEC |
|---|
| 260 | 252 | |
|---|
| 261 | 253 | #ifdef __powerpc64__ |
|---|
| 262 | 254 | #include <asm/page_64.h> |
|---|
| .. | .. |
|---|
| 264 | 256 | #include <asm/page_32.h> |
|---|
| 265 | 257 | #endif |
|---|
| 266 | 258 | |
|---|
| 267 | | -/* align addr on a size boundary - adjust address up/down if needed */ |
|---|
| 268 | | -#define _ALIGN_UP(addr, size) __ALIGN_KERNEL(addr, size) |
|---|
| 269 | | -#define _ALIGN_DOWN(addr, size) ((addr)&(~((typeof(addr))(size)-1))) |
|---|
| 270 | | - |
|---|
| 271 | | -/* align addr on a size boundary - adjust address up if needed */ |
|---|
| 272 | | -#define _ALIGN(addr,size) _ALIGN_UP(addr,size) |
|---|
| 273 | | - |
|---|
| 274 | 259 | /* |
|---|
| 275 | 260 | * Don't compare things with KERNELBASE or PAGE_OFFSET to test for |
|---|
| 276 | 261 | * "kernelness", use is_kernel_addr() - it should do what you want. |
|---|
| 277 | 262 | */ |
|---|
| 278 | 263 | #ifdef CONFIG_PPC_BOOK3E_64 |
|---|
| 279 | 264 | #define is_kernel_addr(x) ((x) >= 0x8000000000000000ul) |
|---|
| 280 | | -#else |
|---|
| 265 | +#elif defined(CONFIG_PPC_BOOK3S_64) |
|---|
| 281 | 266 | #define is_kernel_addr(x) ((x) >= PAGE_OFFSET) |
|---|
| 267 | +#else |
|---|
| 268 | +#define is_kernel_addr(x) ((x) >= TASK_SIZE) |
|---|
| 282 | 269 | #endif |
|---|
| 283 | 270 | |
|---|
| 284 | 271 | #ifndef CONFIG_PPC_BOOK3S_64 |
|---|
| .. | .. |
|---|
| 289 | 276 | * page tables at arbitrary addresses, this breaks and will have to change. |
|---|
| 290 | 277 | */ |
|---|
| 291 | 278 | #ifdef CONFIG_PPC64 |
|---|
| 292 | | -#define PD_HUGE 0x8000000000000000 |
|---|
| 279 | +#define PD_HUGE 0x8000000000000000UL |
|---|
| 293 | 280 | #else |
|---|
| 294 | 281 | #define PD_HUGE 0x80000000 |
|---|
| 295 | 282 | #endif |
|---|
| .. | .. |
|---|
| 305 | 292 | /* |
|---|
| 306 | 293 | * Some number of bits at the level of the page table that points to |
|---|
| 307 | 294 | * a hugepte are used to encode the size. This masks those bits. |
|---|
| 295 | + * On 8xx, HW assistance requires 4k alignment for the hugepte. |
|---|
| 308 | 296 | */ |
|---|
| 297 | +#ifdef CONFIG_PPC_8xx |
|---|
| 298 | +#define HUGEPD_SHIFT_MASK 0xfff |
|---|
| 299 | +#else |
|---|
| 309 | 300 | #define HUGEPD_SHIFT_MASK 0x3f |
|---|
| 301 | +#endif |
|---|
| 310 | 302 | |
|---|
| 311 | 303 | #ifndef __ASSEMBLY__ |
|---|
| 312 | 304 | |
|---|
| .. | .. |
|---|
| 326 | 318 | extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg); |
|---|
| 327 | 319 | extern void copy_user_page(void *to, void *from, unsigned long vaddr, |
|---|
| 328 | 320 | struct page *p); |
|---|
| 329 | | -extern int page_is_ram(unsigned long pfn); |
|---|
| 330 | 321 | extern int devmem_is_allowed(unsigned long pfn); |
|---|
| 331 | 322 | |
|---|
| 332 | 323 | #ifdef CONFIG_PPC_SMLPAR |
|---|
| .. | .. |
|---|
| 335 | 326 | #endif |
|---|
| 336 | 327 | |
|---|
| 337 | 328 | struct vm_area_struct; |
|---|
| 338 | | -#ifdef CONFIG_PPC_BOOK3S_64 |
|---|
| 339 | | -/* |
|---|
| 340 | | - * For BOOK3s 64 with 4k and 64K linux page size |
|---|
| 341 | | - * we want to use pointers, because the page table |
|---|
| 342 | | - * actually store pfn |
|---|
| 343 | | - */ |
|---|
| 344 | | -typedef pte_t *pgtable_t; |
|---|
| 345 | | -#else |
|---|
| 346 | | -#if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC64) |
|---|
| 347 | | -typedef pte_t *pgtable_t; |
|---|
| 348 | | -#else |
|---|
| 349 | | -typedef struct page *pgtable_t; |
|---|
| 350 | | -#endif |
|---|
| 351 | | -#endif |
|---|
| 329 | + |
|---|
| 330 | +extern unsigned long kernstart_virt_addr; |
|---|
| 331 | + |
|---|
| 332 | +static inline unsigned long kaslr_offset(void) |
|---|
| 333 | +{ |
|---|
| 334 | + return kernstart_virt_addr - KERNELBASE; |
|---|
| 335 | +} |
|---|
| 352 | 336 | |
|---|
| 353 | 337 | #include <asm-generic/memory_model.h> |
|---|
| 354 | 338 | #endif /* __ASSEMBLY__ */ |
|---|