18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ 38c2ecf20Sopenharmony_ci#define _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <asm-generic/pgtable-nop4d.h> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 88c2ecf20Sopenharmony_ci#include <linux/mmdebug.h> 98c2ecf20Sopenharmony_ci#include <linux/bug.h> 108c2ecf20Sopenharmony_ci#include <linux/sizes.h> 118c2ecf20Sopenharmony_ci#endif 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci * Common bits between hash and Radix page table 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci#define _PAGE_BIT_SWAP_TYPE 0 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define _PAGE_EXEC 0x00001 /* execute permission */ 198c2ecf20Sopenharmony_ci#define _PAGE_WRITE 0x00002 /* write access allowed */ 208c2ecf20Sopenharmony_ci#define _PAGE_READ 0x00004 /* read access allowed */ 218c2ecf20Sopenharmony_ci#define _PAGE_RW (_PAGE_READ | _PAGE_WRITE) 228c2ecf20Sopenharmony_ci#define _PAGE_RWX (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC) 238c2ecf20Sopenharmony_ci#define _PAGE_PRIVILEGED 0x00008 /* kernel access only */ 248c2ecf20Sopenharmony_ci#define _PAGE_SAO 0x00010 /* Strong access order */ 258c2ecf20Sopenharmony_ci#define _PAGE_NON_IDEMPOTENT 0x00020 /* non idempotent memory */ 268c2ecf20Sopenharmony_ci#define _PAGE_TOLERANT 0x00030 /* tolerant memory, cache inhibited */ 278c2ecf20Sopenharmony_ci#define _PAGE_DIRTY 0x00080 /* C: page changed */ 288c2ecf20Sopenharmony_ci#define _PAGE_ACCESSED 0x00100 /* R: page referenced */ 298c2ecf20Sopenharmony_ci/* 308c2ecf20Sopenharmony_ci * Software bits 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci#define _RPAGE_SW0 0x2000000000000000UL 338c2ecf20Sopenharmony_ci#define _RPAGE_SW1 0x00800 348c2ecf20Sopenharmony_ci#define _RPAGE_SW2 0x00400 358c2ecf20Sopenharmony_ci#define _RPAGE_SW3 0x00200 368c2ecf20Sopenharmony_ci#define _RPAGE_RSV1 0x00040UL 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define _RPAGE_PKEY_BIT4 0x1000000000000000UL 398c2ecf20Sopenharmony_ci#define _RPAGE_PKEY_BIT3 0x0800000000000000UL 408c2ecf20Sopenharmony_ci#define _RPAGE_PKEY_BIT2 0x0400000000000000UL 418c2ecf20Sopenharmony_ci#define _RPAGE_PKEY_BIT1 0x0200000000000000UL 428c2ecf20Sopenharmony_ci#define _RPAGE_PKEY_BIT0 0x0100000000000000UL 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#define _PAGE_PTE 0x4000000000000000UL /* distinguishes PTEs from pointers */ 458c2ecf20Sopenharmony_ci#define _PAGE_PRESENT 0x8000000000000000UL /* pte contains a translation */ 468c2ecf20Sopenharmony_ci/* 478c2ecf20Sopenharmony_ci * We need to mark a pmd pte invalid while splitting. We can do that by clearing 488c2ecf20Sopenharmony_ci * the _PAGE_PRESENT bit. But then that will be taken as a swap pte. In order to 498c2ecf20Sopenharmony_ci * differentiate between two use a SW field when invalidating. 508c2ecf20Sopenharmony_ci * 518c2ecf20Sopenharmony_ci * We do that temporary invalidate for regular pte entry in ptep_set_access_flags 528c2ecf20Sopenharmony_ci * 538c2ecf20Sopenharmony_ci * This is used only when _PAGE_PRESENT is cleared. 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_ci#define _PAGE_INVALID _RPAGE_SW0 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* 588c2ecf20Sopenharmony_ci * Top and bottom bits of RPN which can be used by hash 598c2ecf20Sopenharmony_ci * translation mode, because we expect them to be zero 608c2ecf20Sopenharmony_ci * otherwise. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci#define _RPAGE_RPN0 0x01000 638c2ecf20Sopenharmony_ci#define _RPAGE_RPN1 0x02000 648c2ecf20Sopenharmony_ci#define _RPAGE_RPN43 0x0080000000000000UL 658c2ecf20Sopenharmony_ci#define _RPAGE_RPN42 0x0040000000000000UL 668c2ecf20Sopenharmony_ci#define _RPAGE_RPN41 0x0020000000000000UL 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* Max physical address bit as per radix table */ 698c2ecf20Sopenharmony_ci#define _RPAGE_PA_MAX 56 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/* 728c2ecf20Sopenharmony_ci * Max physical address bit we will use for now. 738c2ecf20Sopenharmony_ci * 748c2ecf20Sopenharmony_ci * This is mostly a hardware limitation and for now Power9 has 758c2ecf20Sopenharmony_ci * a 51 bit limit. 768c2ecf20Sopenharmony_ci * 778c2ecf20Sopenharmony_ci * This is different from the number of physical bit required to address 788c2ecf20Sopenharmony_ci * the last byte of memory. That is defined by MAX_PHYSMEM_BITS. 798c2ecf20Sopenharmony_ci * MAX_PHYSMEM_BITS is a linux limitation imposed by the maximum 808c2ecf20Sopenharmony_ci * number of sections we can support (SECTIONS_SHIFT). 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci * This is different from Radix page table limitation above and 838c2ecf20Sopenharmony_ci * should always be less than that. The limit is done such that 848c2ecf20Sopenharmony_ci * we can overload the bits between _RPAGE_PA_MAX and _PAGE_PA_MAX 858c2ecf20Sopenharmony_ci * for hash linux page table specific bits. 868c2ecf20Sopenharmony_ci * 878c2ecf20Sopenharmony_ci * In order to be compatible with future hardware generations we keep 888c2ecf20Sopenharmony_ci * some offsets and limit this for now to 53 898c2ecf20Sopenharmony_ci */ 908c2ecf20Sopenharmony_ci#define _PAGE_PA_MAX 53 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci#define _PAGE_SOFT_DIRTY _RPAGE_SW3 /* software: software dirty tracking */ 938c2ecf20Sopenharmony_ci#define _PAGE_SPECIAL _RPAGE_SW2 /* software: special page */ 948c2ecf20Sopenharmony_ci#define _PAGE_DEVMAP _RPAGE_SW1 /* software: ZONE_DEVICE page */ 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci/* 978c2ecf20Sopenharmony_ci * Drivers request for cache inhibited pte mapping using _PAGE_NO_CACHE 988c2ecf20Sopenharmony_ci * Instead of fixing all of them, add an alternate define which 998c2ecf20Sopenharmony_ci * maps CI pte mapping. 1008c2ecf20Sopenharmony_ci */ 1018c2ecf20Sopenharmony_ci#define _PAGE_NO_CACHE _PAGE_TOLERANT 1028c2ecf20Sopenharmony_ci/* 1038c2ecf20Sopenharmony_ci * We support _RPAGE_PA_MAX bit real address in pte. On the linux side 1048c2ecf20Sopenharmony_ci * we are limited by _PAGE_PA_MAX. Clear everything above _PAGE_PA_MAX 1058c2ecf20Sopenharmony_ci * and every thing below PAGE_SHIFT; 1068c2ecf20Sopenharmony_ci */ 1078c2ecf20Sopenharmony_ci#define PTE_RPN_MASK (((1UL << _PAGE_PA_MAX) - 1) & (PAGE_MASK)) 1088c2ecf20Sopenharmony_ci/* 1098c2ecf20Sopenharmony_ci * set of bits not changed in pmd_modify. Even though we have hash specific bits 1108c2ecf20Sopenharmony_ci * in here, on radix we expect them to be zero. 1118c2ecf20Sopenharmony_ci */ 1128c2ecf20Sopenharmony_ci#define _HPAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \ 1138c2ecf20Sopenharmony_ci _PAGE_ACCESSED | H_PAGE_THP_HUGE | _PAGE_PTE | \ 1148c2ecf20Sopenharmony_ci _PAGE_SOFT_DIRTY | _PAGE_DEVMAP) 1158c2ecf20Sopenharmony_ci/* 1168c2ecf20Sopenharmony_ci * user access blocked by key 1178c2ecf20Sopenharmony_ci */ 1188c2ecf20Sopenharmony_ci#define _PAGE_KERNEL_RW (_PAGE_PRIVILEGED | _PAGE_RW | _PAGE_DIRTY) 1198c2ecf20Sopenharmony_ci#define _PAGE_KERNEL_RO (_PAGE_PRIVILEGED | _PAGE_READ) 1208c2ecf20Sopenharmony_ci#define _PAGE_KERNEL_RWX (_PAGE_PRIVILEGED | _PAGE_DIRTY | \ 1218c2ecf20Sopenharmony_ci _PAGE_RW | _PAGE_EXEC) 1228c2ecf20Sopenharmony_ci/* 1238c2ecf20Sopenharmony_ci * _PAGE_CHG_MASK masks of bits that are to be preserved across 1248c2ecf20Sopenharmony_ci * pgprot changes 1258c2ecf20Sopenharmony_ci */ 1268c2ecf20Sopenharmony_ci#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \ 1278c2ecf20Sopenharmony_ci _PAGE_ACCESSED | _PAGE_SPECIAL | _PAGE_PTE | \ 1288c2ecf20Sopenharmony_ci _PAGE_SOFT_DIRTY | _PAGE_DEVMAP) 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* 1318c2ecf20Sopenharmony_ci * We define 2 sets of base prot bits, one for basic pages (ie, 1328c2ecf20Sopenharmony_ci * cacheable kernel and user pages) and one for non cacheable 1338c2ecf20Sopenharmony_ci * pages. We always set _PAGE_COHERENT when SMP is enabled or 1348c2ecf20Sopenharmony_ci * the processor might need it for DMA coherency. 1358c2ecf20Sopenharmony_ci */ 1368c2ecf20Sopenharmony_ci#define _PAGE_BASE_NC (_PAGE_PRESENT | _PAGE_ACCESSED) 1378c2ecf20Sopenharmony_ci#define _PAGE_BASE (_PAGE_BASE_NC) 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci/* Permission masks used to generate the __P and __S table, 1408c2ecf20Sopenharmony_ci * 1418c2ecf20Sopenharmony_ci * Note:__pgprot is defined in arch/powerpc/include/asm/page.h 1428c2ecf20Sopenharmony_ci * 1438c2ecf20Sopenharmony_ci * Write permissions imply read permissions for now (we could make write-only 1448c2ecf20Sopenharmony_ci * pages on BookE but we don't bother for now). Execute permission control is 1458c2ecf20Sopenharmony_ci * possible on platforms that define _PAGE_EXEC 1468c2ecf20Sopenharmony_ci */ 1478c2ecf20Sopenharmony_ci#define PAGE_NONE __pgprot(_PAGE_BASE | _PAGE_PRIVILEGED) 1488c2ecf20Sopenharmony_ci#define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_RW) 1498c2ecf20Sopenharmony_ci#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_EXEC) 1508c2ecf20Sopenharmony_ci#define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_READ) 1518c2ecf20Sopenharmony_ci#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC) 1528c2ecf20Sopenharmony_ci#define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_READ) 1538c2ecf20Sopenharmony_ci#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC) 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci/* Permission masks used for kernel mappings */ 1568c2ecf20Sopenharmony_ci#define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) 1578c2ecf20Sopenharmony_ci#define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ 1588c2ecf20Sopenharmony_ci _PAGE_TOLERANT) 1598c2ecf20Sopenharmony_ci#define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | \ 1608c2ecf20Sopenharmony_ci _PAGE_NON_IDEMPOTENT) 1618c2ecf20Sopenharmony_ci#define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RWX) 1628c2ecf20Sopenharmony_ci#define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO) 1638c2ecf20Sopenharmony_ci#define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX) 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci/* 1668c2ecf20Sopenharmony_ci * Protection used for kernel text. We want the debuggers to be able to 1678c2ecf20Sopenharmony_ci * set breakpoints anywhere, so don't write protect the kernel text 1688c2ecf20Sopenharmony_ci * on platforms where such control is possible. 1698c2ecf20Sopenharmony_ci */ 1708c2ecf20Sopenharmony_ci#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) || \ 1718c2ecf20Sopenharmony_ci defined(CONFIG_KPROBES) || defined(CONFIG_DYNAMIC_FTRACE) 1728c2ecf20Sopenharmony_ci#define PAGE_KERNEL_TEXT PAGE_KERNEL_X 1738c2ecf20Sopenharmony_ci#else 1748c2ecf20Sopenharmony_ci#define PAGE_KERNEL_TEXT PAGE_KERNEL_ROX 1758c2ecf20Sopenharmony_ci#endif 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci/* Make modules code happy. We don't set RO yet */ 1788c2ecf20Sopenharmony_ci#define PAGE_KERNEL_EXEC PAGE_KERNEL_X 1798c2ecf20Sopenharmony_ci#define PAGE_AGP (PAGE_KERNEL_NC) 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 1828c2ecf20Sopenharmony_ci/* 1838c2ecf20Sopenharmony_ci * page table defines 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ciextern unsigned long __pte_index_size; 1868c2ecf20Sopenharmony_ciextern unsigned long __pmd_index_size; 1878c2ecf20Sopenharmony_ciextern unsigned long __pud_index_size; 1888c2ecf20Sopenharmony_ciextern unsigned long __pgd_index_size; 1898c2ecf20Sopenharmony_ciextern unsigned long __pud_cache_index; 1908c2ecf20Sopenharmony_ci#define PTE_INDEX_SIZE __pte_index_size 1918c2ecf20Sopenharmony_ci#define PMD_INDEX_SIZE __pmd_index_size 1928c2ecf20Sopenharmony_ci#define PUD_INDEX_SIZE __pud_index_size 1938c2ecf20Sopenharmony_ci#define PGD_INDEX_SIZE __pgd_index_size 1948c2ecf20Sopenharmony_ci/* pmd table use page table fragments */ 1958c2ecf20Sopenharmony_ci#define PMD_CACHE_INDEX 0 1968c2ecf20Sopenharmony_ci#define PUD_CACHE_INDEX __pud_cache_index 1978c2ecf20Sopenharmony_ci/* 1988c2ecf20Sopenharmony_ci * Because of use of pte fragments and THP, size of page table 1998c2ecf20Sopenharmony_ci * are not always derived out of index size above. 2008c2ecf20Sopenharmony_ci */ 2018c2ecf20Sopenharmony_ciextern unsigned long __pte_table_size; 2028c2ecf20Sopenharmony_ciextern unsigned long __pmd_table_size; 2038c2ecf20Sopenharmony_ciextern unsigned long __pud_table_size; 2048c2ecf20Sopenharmony_ciextern unsigned long __pgd_table_size; 2058c2ecf20Sopenharmony_ci#define PTE_TABLE_SIZE __pte_table_size 2068c2ecf20Sopenharmony_ci#define PMD_TABLE_SIZE __pmd_table_size 2078c2ecf20Sopenharmony_ci#define PUD_TABLE_SIZE __pud_table_size 2088c2ecf20Sopenharmony_ci#define PGD_TABLE_SIZE __pgd_table_size 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ciextern unsigned long __pmd_val_bits; 2118c2ecf20Sopenharmony_ciextern unsigned long __pud_val_bits; 2128c2ecf20Sopenharmony_ciextern unsigned long __pgd_val_bits; 2138c2ecf20Sopenharmony_ci#define PMD_VAL_BITS __pmd_val_bits 2148c2ecf20Sopenharmony_ci#define PUD_VAL_BITS __pud_val_bits 2158c2ecf20Sopenharmony_ci#define PGD_VAL_BITS __pgd_val_bits 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ciextern unsigned long __pte_frag_nr; 2188c2ecf20Sopenharmony_ci#define PTE_FRAG_NR __pte_frag_nr 2198c2ecf20Sopenharmony_ciextern unsigned long __pte_frag_size_shift; 2208c2ecf20Sopenharmony_ci#define PTE_FRAG_SIZE_SHIFT __pte_frag_size_shift 2218c2ecf20Sopenharmony_ci#define PTE_FRAG_SIZE (1UL << PTE_FRAG_SIZE_SHIFT) 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ciextern unsigned long __pmd_frag_nr; 2248c2ecf20Sopenharmony_ci#define PMD_FRAG_NR __pmd_frag_nr 2258c2ecf20Sopenharmony_ciextern unsigned long __pmd_frag_size_shift; 2268c2ecf20Sopenharmony_ci#define PMD_FRAG_SIZE_SHIFT __pmd_frag_size_shift 2278c2ecf20Sopenharmony_ci#define PMD_FRAG_SIZE (1UL << PMD_FRAG_SIZE_SHIFT) 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) 2308c2ecf20Sopenharmony_ci#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) 2318c2ecf20Sopenharmony_ci#define PTRS_PER_PUD (1 << PUD_INDEX_SIZE) 2328c2ecf20Sopenharmony_ci#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci/* PMD_SHIFT determines what a second-level page table entry can map */ 2358c2ecf20Sopenharmony_ci#define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE) 2368c2ecf20Sopenharmony_ci#define PMD_SIZE (1UL << PMD_SHIFT) 2378c2ecf20Sopenharmony_ci#define PMD_MASK (~(PMD_SIZE-1)) 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci/* PUD_SHIFT determines what a third-level page table entry can map */ 2408c2ecf20Sopenharmony_ci#define PUD_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE) 2418c2ecf20Sopenharmony_ci#define PUD_SIZE (1UL << PUD_SHIFT) 2428c2ecf20Sopenharmony_ci#define PUD_MASK (~(PUD_SIZE-1)) 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci/* PGDIR_SHIFT determines what a fourth-level page table entry can map */ 2458c2ecf20Sopenharmony_ci#define PGDIR_SHIFT (PUD_SHIFT + PUD_INDEX_SIZE) 2468c2ecf20Sopenharmony_ci#define PGDIR_SIZE (1UL << PGDIR_SHIFT) 2478c2ecf20Sopenharmony_ci#define PGDIR_MASK (~(PGDIR_SIZE-1)) 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci/* Bits to mask out from a PMD to get to the PTE page */ 2508c2ecf20Sopenharmony_ci#define PMD_MASKED_BITS 0xc0000000000000ffUL 2518c2ecf20Sopenharmony_ci/* Bits to mask out from a PUD to get to the PMD page */ 2528c2ecf20Sopenharmony_ci#define PUD_MASKED_BITS 0xc0000000000000ffUL 2538c2ecf20Sopenharmony_ci/* Bits to mask out from a PGD to get to the PUD page */ 2548c2ecf20Sopenharmony_ci#define P4D_MASKED_BITS 0xc0000000000000ffUL 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci/* 2578c2ecf20Sopenharmony_ci * Used as an indicator for rcu callback functions 2588c2ecf20Sopenharmony_ci */ 2598c2ecf20Sopenharmony_cienum pgtable_index { 2608c2ecf20Sopenharmony_ci PTE_INDEX = 0, 2618c2ecf20Sopenharmony_ci PMD_INDEX, 2628c2ecf20Sopenharmony_ci PUD_INDEX, 2638c2ecf20Sopenharmony_ci PGD_INDEX, 2648c2ecf20Sopenharmony_ci /* 2658c2ecf20Sopenharmony_ci * Below are used with 4k page size and hugetlb 2668c2ecf20Sopenharmony_ci */ 2678c2ecf20Sopenharmony_ci HTLB_16M_INDEX, 2688c2ecf20Sopenharmony_ci HTLB_16G_INDEX, 2698c2ecf20Sopenharmony_ci}; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ciextern unsigned long __vmalloc_start; 2728c2ecf20Sopenharmony_ciextern unsigned long __vmalloc_end; 2738c2ecf20Sopenharmony_ci#define VMALLOC_START __vmalloc_start 2748c2ecf20Sopenharmony_ci#define VMALLOC_END __vmalloc_end 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_cistatic inline unsigned int ioremap_max_order(void) 2778c2ecf20Sopenharmony_ci{ 2788c2ecf20Sopenharmony_ci if (radix_enabled()) 2798c2ecf20Sopenharmony_ci return PUD_SHIFT; 2808c2ecf20Sopenharmony_ci return 7 + PAGE_SHIFT; /* default from linux/vmalloc.h */ 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci#define IOREMAP_MAX_ORDER ioremap_max_order() 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ciextern unsigned long __kernel_virt_start; 2858c2ecf20Sopenharmony_ciextern unsigned long __kernel_io_start; 2868c2ecf20Sopenharmony_ciextern unsigned long __kernel_io_end; 2878c2ecf20Sopenharmony_ci#define KERN_VIRT_START __kernel_virt_start 2888c2ecf20Sopenharmony_ci#define KERN_IO_START __kernel_io_start 2898c2ecf20Sopenharmony_ci#define KERN_IO_END __kernel_io_end 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ciextern struct page *vmemmap; 2928c2ecf20Sopenharmony_ciextern unsigned long pci_io_base; 2938c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */ 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci#include <asm/book3s/64/hash.h> 2968c2ecf20Sopenharmony_ci#include <asm/book3s/64/radix.h> 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci#if H_MAX_PHYSMEM_BITS > R_MAX_PHYSMEM_BITS 2998c2ecf20Sopenharmony_ci#define MAX_PHYSMEM_BITS H_MAX_PHYSMEM_BITS 3008c2ecf20Sopenharmony_ci#else 3018c2ecf20Sopenharmony_ci#define MAX_PHYSMEM_BITS R_MAX_PHYSMEM_BITS 3028c2ecf20Sopenharmony_ci#endif 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_64K_PAGES 3068c2ecf20Sopenharmony_ci#include <asm/book3s/64/pgtable-64k.h> 3078c2ecf20Sopenharmony_ci#else 3088c2ecf20Sopenharmony_ci#include <asm/book3s/64/pgtable-4k.h> 3098c2ecf20Sopenharmony_ci#endif 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci#include <asm/barrier.h> 3128c2ecf20Sopenharmony_ci/* 3138c2ecf20Sopenharmony_ci * IO space itself carved into the PIO region (ISA and PHB IO space) and 3148c2ecf20Sopenharmony_ci * the ioremap space 3158c2ecf20Sopenharmony_ci * 3168c2ecf20Sopenharmony_ci * ISA_IO_BASE = KERN_IO_START, 64K reserved area 3178c2ecf20Sopenharmony_ci * PHB_IO_BASE = ISA_IO_BASE + 64K to ISA_IO_BASE + 2G, PHB IO spaces 3188c2ecf20Sopenharmony_ci * IOREMAP_BASE = ISA_IO_BASE + 2G to VMALLOC_START + PGTABLE_RANGE 3198c2ecf20Sopenharmony_ci */ 3208c2ecf20Sopenharmony_ci#define FULL_IO_SIZE 0x80000000ul 3218c2ecf20Sopenharmony_ci#define ISA_IO_BASE (KERN_IO_START) 3228c2ecf20Sopenharmony_ci#define ISA_IO_END (KERN_IO_START + 0x10000ul) 3238c2ecf20Sopenharmony_ci#define PHB_IO_BASE (ISA_IO_END) 3248c2ecf20Sopenharmony_ci#define PHB_IO_END (KERN_IO_START + FULL_IO_SIZE) 3258c2ecf20Sopenharmony_ci#define IOREMAP_BASE (PHB_IO_END) 3268c2ecf20Sopenharmony_ci#define IOREMAP_START (ioremap_bot) 3278c2ecf20Sopenharmony_ci#define IOREMAP_END (KERN_IO_END - FIXADDR_SIZE) 3288c2ecf20Sopenharmony_ci#define FIXADDR_SIZE SZ_32M 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci/* Advertise special mapping type for AGP */ 3318c2ecf20Sopenharmony_ci#define HAVE_PAGE_AGP 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci/* 3368c2ecf20Sopenharmony_ci * This is the default implementation of various PTE accessors, it's 3378c2ecf20Sopenharmony_ci * used in all cases except Book3S with 64K pages where we have a 3388c2ecf20Sopenharmony_ci * concept of sub-pages 3398c2ecf20Sopenharmony_ci */ 3408c2ecf20Sopenharmony_ci#ifndef __real_pte 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci#define __real_pte(e, p, o) ((real_pte_t){(e)}) 3438c2ecf20Sopenharmony_ci#define __rpte_to_pte(r) ((r).pte) 3448c2ecf20Sopenharmony_ci#define __rpte_to_hidx(r,index) (pte_val(__rpte_to_pte(r)) >> H_PAGE_F_GIX_SHIFT) 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift) \ 3478c2ecf20Sopenharmony_ci do { \ 3488c2ecf20Sopenharmony_ci index = 0; \ 3498c2ecf20Sopenharmony_ci shift = mmu_psize_defs[psize].shift; \ 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci#define pte_iterate_hashed_end() } while(0) 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci/* 3548c2ecf20Sopenharmony_ci * We expect this to be called only for user addresses or kernel virtual 3558c2ecf20Sopenharmony_ci * addresses other than the linear mapping. 3568c2ecf20Sopenharmony_ci */ 3578c2ecf20Sopenharmony_ci#define pte_pagesize_index(mm, addr, pte) MMU_PAGE_4K 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci#endif /* __real_pte */ 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic inline unsigned long pte_update(struct mm_struct *mm, unsigned long addr, 3628c2ecf20Sopenharmony_ci pte_t *ptep, unsigned long clr, 3638c2ecf20Sopenharmony_ci unsigned long set, int huge) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci if (radix_enabled()) 3668c2ecf20Sopenharmony_ci return radix__pte_update(mm, addr, ptep, clr, set, huge); 3678c2ecf20Sopenharmony_ci return hash__pte_update(mm, addr, ptep, clr, set, huge); 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci/* 3708c2ecf20Sopenharmony_ci * For hash even if we have _PAGE_ACCESSED = 0, we do a pte_update. 3718c2ecf20Sopenharmony_ci * We currently remove entries from the hashtable regardless of whether 3728c2ecf20Sopenharmony_ci * the entry was young or dirty. 3738c2ecf20Sopenharmony_ci * 3748c2ecf20Sopenharmony_ci * We should be more intelligent about this but for the moment we override 3758c2ecf20Sopenharmony_ci * these functions and force a tlb flush unconditionally 3768c2ecf20Sopenharmony_ci * For radix: H_PAGE_HASHPTE should be zero. Hence we can use the same 3778c2ecf20Sopenharmony_ci * function for both hash and radix. 3788c2ecf20Sopenharmony_ci */ 3798c2ecf20Sopenharmony_cistatic inline int __ptep_test_and_clear_young(struct mm_struct *mm, 3808c2ecf20Sopenharmony_ci unsigned long addr, pte_t *ptep) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci unsigned long old; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci if ((pte_raw(*ptep) & cpu_to_be64(_PAGE_ACCESSED | H_PAGE_HASHPTE)) == 0) 3858c2ecf20Sopenharmony_ci return 0; 3868c2ecf20Sopenharmony_ci old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0); 3878c2ecf20Sopenharmony_ci return (old & _PAGE_ACCESSED) != 0; 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG 3918c2ecf20Sopenharmony_ci#define ptep_test_and_clear_young(__vma, __addr, __ptep) \ 3928c2ecf20Sopenharmony_ci({ \ 3938c2ecf20Sopenharmony_ci int __r; \ 3948c2ecf20Sopenharmony_ci __r = __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \ 3958c2ecf20Sopenharmony_ci __r; \ 3968c2ecf20Sopenharmony_ci}) 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistatic inline int __pte_write(pte_t pte) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci return !!(pte_raw(pte) & cpu_to_be64(_PAGE_WRITE)); 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci#ifdef CONFIG_NUMA_BALANCING 4048c2ecf20Sopenharmony_ci#define pte_savedwrite pte_savedwrite 4058c2ecf20Sopenharmony_cistatic inline bool pte_savedwrite(pte_t pte) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci /* 4088c2ecf20Sopenharmony_ci * Saved write ptes are prot none ptes that doesn't have 4098c2ecf20Sopenharmony_ci * privileged bit sit. We mark prot none as one which has 4108c2ecf20Sopenharmony_ci * present and pviliged bit set and RWX cleared. To mark 4118c2ecf20Sopenharmony_ci * protnone which used to have _PAGE_WRITE set we clear 4128c2ecf20Sopenharmony_ci * the privileged bit. 4138c2ecf20Sopenharmony_ci */ 4148c2ecf20Sopenharmony_ci return !(pte_raw(pte) & cpu_to_be64(_PAGE_RWX | _PAGE_PRIVILEGED)); 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ci#else 4178c2ecf20Sopenharmony_ci#define pte_savedwrite pte_savedwrite 4188c2ecf20Sopenharmony_cistatic inline bool pte_savedwrite(pte_t pte) 4198c2ecf20Sopenharmony_ci{ 4208c2ecf20Sopenharmony_ci return false; 4218c2ecf20Sopenharmony_ci} 4228c2ecf20Sopenharmony_ci#endif 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_cistatic inline int pte_write(pte_t pte) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci return __pte_write(pte) || pte_savedwrite(pte); 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_cistatic inline int pte_read(pte_t pte) 4308c2ecf20Sopenharmony_ci{ 4318c2ecf20Sopenharmony_ci return !!(pte_raw(pte) & cpu_to_be64(_PAGE_READ)); 4328c2ecf20Sopenharmony_ci} 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_SET_WRPROTECT 4358c2ecf20Sopenharmony_cistatic inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, 4368c2ecf20Sopenharmony_ci pte_t *ptep) 4378c2ecf20Sopenharmony_ci{ 4388c2ecf20Sopenharmony_ci if (__pte_write(*ptep)) 4398c2ecf20Sopenharmony_ci pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 0); 4408c2ecf20Sopenharmony_ci else if (unlikely(pte_savedwrite(*ptep))) 4418c2ecf20Sopenharmony_ci pte_update(mm, addr, ptep, 0, _PAGE_PRIVILEGED, 0); 4428c2ecf20Sopenharmony_ci} 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT 4458c2ecf20Sopenharmony_cistatic inline void huge_ptep_set_wrprotect(struct mm_struct *mm, 4468c2ecf20Sopenharmony_ci unsigned long addr, pte_t *ptep) 4478c2ecf20Sopenharmony_ci{ 4488c2ecf20Sopenharmony_ci /* 4498c2ecf20Sopenharmony_ci * We should not find protnone for hugetlb, but this complete the 4508c2ecf20Sopenharmony_ci * interface. 4518c2ecf20Sopenharmony_ci */ 4528c2ecf20Sopenharmony_ci if (__pte_write(*ptep)) 4538c2ecf20Sopenharmony_ci pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 1); 4548c2ecf20Sopenharmony_ci else if (unlikely(pte_savedwrite(*ptep))) 4558c2ecf20Sopenharmony_ci pte_update(mm, addr, ptep, 0, _PAGE_PRIVILEGED, 1); 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_GET_AND_CLEAR 4598c2ecf20Sopenharmony_cistatic inline pte_t ptep_get_and_clear(struct mm_struct *mm, 4608c2ecf20Sopenharmony_ci unsigned long addr, pte_t *ptep) 4618c2ecf20Sopenharmony_ci{ 4628c2ecf20Sopenharmony_ci unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0, 0); 4638c2ecf20Sopenharmony_ci return __pte(old); 4648c2ecf20Sopenharmony_ci} 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL 4678c2ecf20Sopenharmony_cistatic inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, 4688c2ecf20Sopenharmony_ci unsigned long addr, 4698c2ecf20Sopenharmony_ci pte_t *ptep, int full) 4708c2ecf20Sopenharmony_ci{ 4718c2ecf20Sopenharmony_ci if (full && radix_enabled()) { 4728c2ecf20Sopenharmony_ci /* 4738c2ecf20Sopenharmony_ci * We know that this is a full mm pte clear and 4748c2ecf20Sopenharmony_ci * hence can be sure there is no parallel set_pte. 4758c2ecf20Sopenharmony_ci */ 4768c2ecf20Sopenharmony_ci return radix__ptep_get_and_clear_full(mm, addr, ptep, full); 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci return ptep_get_and_clear(mm, addr, ptep); 4798c2ecf20Sopenharmony_ci} 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_cistatic inline void pte_clear(struct mm_struct *mm, unsigned long addr, 4838c2ecf20Sopenharmony_ci pte_t * ptep) 4848c2ecf20Sopenharmony_ci{ 4858c2ecf20Sopenharmony_ci pte_update(mm, addr, ptep, ~0UL, 0, 0); 4868c2ecf20Sopenharmony_ci} 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_cistatic inline int pte_dirty(pte_t pte) 4898c2ecf20Sopenharmony_ci{ 4908c2ecf20Sopenharmony_ci return !!(pte_raw(pte) & cpu_to_be64(_PAGE_DIRTY)); 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cistatic inline int pte_young(pte_t pte) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci return !!(pte_raw(pte) & cpu_to_be64(_PAGE_ACCESSED)); 4968c2ecf20Sopenharmony_ci} 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_cistatic inline int pte_special(pte_t pte) 4998c2ecf20Sopenharmony_ci{ 5008c2ecf20Sopenharmony_ci return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SPECIAL)); 5018c2ecf20Sopenharmony_ci} 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_cistatic inline bool pte_exec(pte_t pte) 5048c2ecf20Sopenharmony_ci{ 5058c2ecf20Sopenharmony_ci return !!(pte_raw(pte) & cpu_to_be64(_PAGE_EXEC)); 5068c2ecf20Sopenharmony_ci} 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY 5108c2ecf20Sopenharmony_cistatic inline bool pte_soft_dirty(pte_t pte) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SOFT_DIRTY)); 5138c2ecf20Sopenharmony_ci} 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_cistatic inline pte_t pte_mksoft_dirty(pte_t pte) 5168c2ecf20Sopenharmony_ci{ 5178c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SOFT_DIRTY)); 5188c2ecf20Sopenharmony_ci} 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_cistatic inline pte_t pte_clear_soft_dirty(pte_t pte) 5218c2ecf20Sopenharmony_ci{ 5228c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_SOFT_DIRTY)); 5238c2ecf20Sopenharmony_ci} 5248c2ecf20Sopenharmony_ci#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci#ifdef CONFIG_NUMA_BALANCING 5278c2ecf20Sopenharmony_cistatic inline int pte_protnone(pte_t pte) 5288c2ecf20Sopenharmony_ci{ 5298c2ecf20Sopenharmony_ci return (pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_PTE | _PAGE_RWX)) == 5308c2ecf20Sopenharmony_ci cpu_to_be64(_PAGE_PRESENT | _PAGE_PTE); 5318c2ecf20Sopenharmony_ci} 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci#define pte_mk_savedwrite pte_mk_savedwrite 5348c2ecf20Sopenharmony_cistatic inline pte_t pte_mk_savedwrite(pte_t pte) 5358c2ecf20Sopenharmony_ci{ 5368c2ecf20Sopenharmony_ci /* 5378c2ecf20Sopenharmony_ci * Used by Autonuma subsystem to preserve the write bit 5388c2ecf20Sopenharmony_ci * while marking the pte PROT_NONE. Only allow this 5398c2ecf20Sopenharmony_ci * on PROT_NONE pte 5408c2ecf20Sopenharmony_ci */ 5418c2ecf20Sopenharmony_ci VM_BUG_ON((pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_RWX | _PAGE_PRIVILEGED)) != 5428c2ecf20Sopenharmony_ci cpu_to_be64(_PAGE_PRESENT | _PAGE_PRIVILEGED)); 5438c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_PRIVILEGED)); 5448c2ecf20Sopenharmony_ci} 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci#define pte_clear_savedwrite pte_clear_savedwrite 5478c2ecf20Sopenharmony_cistatic inline pte_t pte_clear_savedwrite(pte_t pte) 5488c2ecf20Sopenharmony_ci{ 5498c2ecf20Sopenharmony_ci /* 5508c2ecf20Sopenharmony_ci * Used by KSM subsystem to make a protnone pte readonly. 5518c2ecf20Sopenharmony_ci */ 5528c2ecf20Sopenharmony_ci VM_BUG_ON(!pte_protnone(pte)); 5538c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_PRIVILEGED)); 5548c2ecf20Sopenharmony_ci} 5558c2ecf20Sopenharmony_ci#else 5568c2ecf20Sopenharmony_ci#define pte_clear_savedwrite pte_clear_savedwrite 5578c2ecf20Sopenharmony_cistatic inline pte_t pte_clear_savedwrite(pte_t pte) 5588c2ecf20Sopenharmony_ci{ 5598c2ecf20Sopenharmony_ci VM_WARN_ON(1); 5608c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_WRITE)); 5618c2ecf20Sopenharmony_ci} 5628c2ecf20Sopenharmony_ci#endif /* CONFIG_NUMA_BALANCING */ 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_cistatic inline bool pte_hw_valid(pte_t pte) 5658c2ecf20Sopenharmony_ci{ 5668c2ecf20Sopenharmony_ci return (pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_PTE)) == 5678c2ecf20Sopenharmony_ci cpu_to_be64(_PAGE_PRESENT | _PAGE_PTE); 5688c2ecf20Sopenharmony_ci} 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_cistatic inline int pte_present(pte_t pte) 5718c2ecf20Sopenharmony_ci{ 5728c2ecf20Sopenharmony_ci /* 5738c2ecf20Sopenharmony_ci * A pte is considerent present if _PAGE_PRESENT is set. 5748c2ecf20Sopenharmony_ci * We also need to consider the pte present which is marked 5758c2ecf20Sopenharmony_ci * invalid during ptep_set_access_flags. Hence we look for _PAGE_INVALID 5768c2ecf20Sopenharmony_ci * if we find _PAGE_PRESENT cleared. 5778c2ecf20Sopenharmony_ci */ 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci if (pte_hw_valid(pte)) 5808c2ecf20Sopenharmony_ci return true; 5818c2ecf20Sopenharmony_ci return (pte_raw(pte) & cpu_to_be64(_PAGE_INVALID | _PAGE_PTE)) == 5828c2ecf20Sopenharmony_ci cpu_to_be64(_PAGE_INVALID | _PAGE_PTE); 5838c2ecf20Sopenharmony_ci} 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_MEM_KEYS 5868c2ecf20Sopenharmony_ciextern bool arch_pte_access_permitted(u64 pte, bool write, bool execute); 5878c2ecf20Sopenharmony_ci#else 5888c2ecf20Sopenharmony_cistatic inline bool arch_pte_access_permitted(u64 pte, bool write, bool execute) 5898c2ecf20Sopenharmony_ci{ 5908c2ecf20Sopenharmony_ci return true; 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_MEM_KEYS */ 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_cistatic inline bool pte_user(pte_t pte) 5958c2ecf20Sopenharmony_ci{ 5968c2ecf20Sopenharmony_ci return !(pte_raw(pte) & cpu_to_be64(_PAGE_PRIVILEGED)); 5978c2ecf20Sopenharmony_ci} 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci#define pte_access_permitted pte_access_permitted 6008c2ecf20Sopenharmony_cistatic inline bool pte_access_permitted(pte_t pte, bool write) 6018c2ecf20Sopenharmony_ci{ 6028c2ecf20Sopenharmony_ci /* 6038c2ecf20Sopenharmony_ci * _PAGE_READ is needed for any access and will be 6048c2ecf20Sopenharmony_ci * cleared for PROT_NONE 6058c2ecf20Sopenharmony_ci */ 6068c2ecf20Sopenharmony_ci if (!pte_present(pte) || !pte_user(pte) || !pte_read(pte)) 6078c2ecf20Sopenharmony_ci return false; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci if (write && !pte_write(pte)) 6108c2ecf20Sopenharmony_ci return false; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci return arch_pte_access_permitted(pte_val(pte), write, 0); 6138c2ecf20Sopenharmony_ci} 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci/* 6168c2ecf20Sopenharmony_ci * Conversion functions: convert a page and protection to a page entry, 6178c2ecf20Sopenharmony_ci * and a page entry and page directory to the page they refer to. 6188c2ecf20Sopenharmony_ci * 6198c2ecf20Sopenharmony_ci * Even if PTEs can be unsigned long long, a PFN is always an unsigned 6208c2ecf20Sopenharmony_ci * long for now. 6218c2ecf20Sopenharmony_ci */ 6228c2ecf20Sopenharmony_cistatic inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci VM_BUG_ON(pfn >> (64 - PAGE_SHIFT)); 6258c2ecf20Sopenharmony_ci VM_BUG_ON((pfn << PAGE_SHIFT) & ~PTE_RPN_MASK); 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci return __pte(((pte_basic_t)pfn << PAGE_SHIFT) | pgprot_val(pgprot) | _PAGE_PTE); 6288c2ecf20Sopenharmony_ci} 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_cistatic inline unsigned long pte_pfn(pte_t pte) 6318c2ecf20Sopenharmony_ci{ 6328c2ecf20Sopenharmony_ci return (pte_val(pte) & PTE_RPN_MASK) >> PAGE_SHIFT; 6338c2ecf20Sopenharmony_ci} 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci/* Generic modifiers for PTE bits */ 6368c2ecf20Sopenharmony_cistatic inline pte_t pte_wrprotect(pte_t pte) 6378c2ecf20Sopenharmony_ci{ 6388c2ecf20Sopenharmony_ci if (unlikely(pte_savedwrite(pte))) 6398c2ecf20Sopenharmony_ci return pte_clear_savedwrite(pte); 6408c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_WRITE)); 6418c2ecf20Sopenharmony_ci} 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_cistatic inline pte_t pte_exprotect(pte_t pte) 6448c2ecf20Sopenharmony_ci{ 6458c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_EXEC)); 6468c2ecf20Sopenharmony_ci} 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_cistatic inline pte_t pte_mkclean(pte_t pte) 6498c2ecf20Sopenharmony_ci{ 6508c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_DIRTY)); 6518c2ecf20Sopenharmony_ci} 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_cistatic inline pte_t pte_mkold(pte_t pte) 6548c2ecf20Sopenharmony_ci{ 6558c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_ACCESSED)); 6568c2ecf20Sopenharmony_ci} 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_cistatic inline pte_t pte_mkexec(pte_t pte) 6598c2ecf20Sopenharmony_ci{ 6608c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_EXEC)); 6618c2ecf20Sopenharmony_ci} 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_cistatic inline pte_t pte_mkwrite(pte_t pte) 6648c2ecf20Sopenharmony_ci{ 6658c2ecf20Sopenharmony_ci /* 6668c2ecf20Sopenharmony_ci * write implies read, hence set both 6678c2ecf20Sopenharmony_ci */ 6688c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_RW)); 6698c2ecf20Sopenharmony_ci} 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_cistatic inline pte_t pte_mkdirty(pte_t pte) 6728c2ecf20Sopenharmony_ci{ 6738c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_DIRTY | _PAGE_SOFT_DIRTY)); 6748c2ecf20Sopenharmony_ci} 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_cistatic inline pte_t pte_mkyoung(pte_t pte) 6778c2ecf20Sopenharmony_ci{ 6788c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_ACCESSED)); 6798c2ecf20Sopenharmony_ci} 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_cistatic inline pte_t pte_mkspecial(pte_t pte) 6828c2ecf20Sopenharmony_ci{ 6838c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SPECIAL)); 6848c2ecf20Sopenharmony_ci} 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_cistatic inline pte_t pte_mkhuge(pte_t pte) 6878c2ecf20Sopenharmony_ci{ 6888c2ecf20Sopenharmony_ci return pte; 6898c2ecf20Sopenharmony_ci} 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_cistatic inline pte_t pte_mkdevmap(pte_t pte) 6928c2ecf20Sopenharmony_ci{ 6938c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SPECIAL | _PAGE_DEVMAP)); 6948c2ecf20Sopenharmony_ci} 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_cistatic inline pte_t pte_mkprivileged(pte_t pte) 6978c2ecf20Sopenharmony_ci{ 6988c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_PRIVILEGED)); 6998c2ecf20Sopenharmony_ci} 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_cistatic inline pte_t pte_mkuser(pte_t pte) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_PRIVILEGED)); 7048c2ecf20Sopenharmony_ci} 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci/* 7078c2ecf20Sopenharmony_ci * This is potentially called with a pmd as the argument, in which case it's not 7088c2ecf20Sopenharmony_ci * safe to check _PAGE_DEVMAP unless we also confirm that _PAGE_PTE is set. 7098c2ecf20Sopenharmony_ci * That's because the bit we use for _PAGE_DEVMAP is not reserved for software 7108c2ecf20Sopenharmony_ci * use in page directory entries (ie. non-ptes). 7118c2ecf20Sopenharmony_ci */ 7128c2ecf20Sopenharmony_cistatic inline int pte_devmap(pte_t pte) 7138c2ecf20Sopenharmony_ci{ 7148c2ecf20Sopenharmony_ci u64 mask = cpu_to_be64(_PAGE_DEVMAP | _PAGE_PTE); 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci return (pte_raw(pte) & mask) == mask; 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_cistatic inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 7208c2ecf20Sopenharmony_ci{ 7218c2ecf20Sopenharmony_ci /* FIXME!! check whether this need to be a conditional */ 7228c2ecf20Sopenharmony_ci return __pte_raw((pte_raw(pte) & cpu_to_be64(_PAGE_CHG_MASK)) | 7238c2ecf20Sopenharmony_ci cpu_to_be64(pgprot_val(newprot))); 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci/* Encode and de-code a swap entry */ 7278c2ecf20Sopenharmony_ci#define MAX_SWAPFILES_CHECK() do { \ 7288c2ecf20Sopenharmony_ci BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS); \ 7298c2ecf20Sopenharmony_ci /* \ 7308c2ecf20Sopenharmony_ci * Don't have overlapping bits with _PAGE_HPTEFLAGS \ 7318c2ecf20Sopenharmony_ci * We filter HPTEFLAGS on set_pte. \ 7328c2ecf20Sopenharmony_ci */ \ 7338c2ecf20Sopenharmony_ci BUILD_BUG_ON(_PAGE_HPTEFLAGS & (0x1f << _PAGE_BIT_SWAP_TYPE)); \ 7348c2ecf20Sopenharmony_ci BUILD_BUG_ON(_PAGE_HPTEFLAGS & _PAGE_SWP_SOFT_DIRTY); \ 7358c2ecf20Sopenharmony_ci } while (0) 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci#define SWP_TYPE_BITS 5 7388c2ecf20Sopenharmony_ci#define __swp_type(x) (((x).val >> _PAGE_BIT_SWAP_TYPE) \ 7398c2ecf20Sopenharmony_ci & ((1UL << SWP_TYPE_BITS) - 1)) 7408c2ecf20Sopenharmony_ci#define __swp_offset(x) (((x).val & PTE_RPN_MASK) >> PAGE_SHIFT) 7418c2ecf20Sopenharmony_ci#define __swp_entry(type, offset) ((swp_entry_t) { \ 7428c2ecf20Sopenharmony_ci ((type) << _PAGE_BIT_SWAP_TYPE) \ 7438c2ecf20Sopenharmony_ci | (((offset) << PAGE_SHIFT) & PTE_RPN_MASK)}) 7448c2ecf20Sopenharmony_ci/* 7458c2ecf20Sopenharmony_ci * swp_entry_t must be independent of pte bits. We build a swp_entry_t from 7468c2ecf20Sopenharmony_ci * swap type and offset we get from swap and convert that to pte to find a 7478c2ecf20Sopenharmony_ci * matching pte in linux page table. 7488c2ecf20Sopenharmony_ci * Clear bits not found in swap entries here. 7498c2ecf20Sopenharmony_ci */ 7508c2ecf20Sopenharmony_ci#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) & ~_PAGE_PTE }) 7518c2ecf20Sopenharmony_ci#define __swp_entry_to_pte(x) __pte((x).val | _PAGE_PTE) 7528c2ecf20Sopenharmony_ci#define __pmd_to_swp_entry(pmd) (__pte_to_swp_entry(pmd_pte(pmd))) 7538c2ecf20Sopenharmony_ci#define __swp_entry_to_pmd(x) (pte_pmd(__swp_entry_to_pte(x))) 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci#ifdef CONFIG_MEM_SOFT_DIRTY 7568c2ecf20Sopenharmony_ci#define _PAGE_SWP_SOFT_DIRTY (1UL << (SWP_TYPE_BITS + _PAGE_BIT_SWAP_TYPE)) 7578c2ecf20Sopenharmony_ci#else 7588c2ecf20Sopenharmony_ci#define _PAGE_SWP_SOFT_DIRTY 0UL 7598c2ecf20Sopenharmony_ci#endif /* CONFIG_MEM_SOFT_DIRTY */ 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY 7628c2ecf20Sopenharmony_cistatic inline pte_t pte_swp_mksoft_dirty(pte_t pte) 7638c2ecf20Sopenharmony_ci{ 7648c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SWP_SOFT_DIRTY)); 7658c2ecf20Sopenharmony_ci} 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_cistatic inline bool pte_swp_soft_dirty(pte_t pte) 7688c2ecf20Sopenharmony_ci{ 7698c2ecf20Sopenharmony_ci return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SWP_SOFT_DIRTY)); 7708c2ecf20Sopenharmony_ci} 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_cistatic inline pte_t pte_swp_clear_soft_dirty(pte_t pte) 7738c2ecf20Sopenharmony_ci{ 7748c2ecf20Sopenharmony_ci return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_SWP_SOFT_DIRTY)); 7758c2ecf20Sopenharmony_ci} 7768c2ecf20Sopenharmony_ci#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_cistatic inline bool check_pte_access(unsigned long access, unsigned long ptev) 7798c2ecf20Sopenharmony_ci{ 7808c2ecf20Sopenharmony_ci /* 7818c2ecf20Sopenharmony_ci * This check for _PAGE_RWX and _PAGE_PRESENT bits 7828c2ecf20Sopenharmony_ci */ 7838c2ecf20Sopenharmony_ci if (access & ~ptev) 7848c2ecf20Sopenharmony_ci return false; 7858c2ecf20Sopenharmony_ci /* 7868c2ecf20Sopenharmony_ci * This check for access to privilege space 7878c2ecf20Sopenharmony_ci */ 7888c2ecf20Sopenharmony_ci if ((access & _PAGE_PRIVILEGED) != (ptev & _PAGE_PRIVILEGED)) 7898c2ecf20Sopenharmony_ci return false; 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci return true; 7928c2ecf20Sopenharmony_ci} 7938c2ecf20Sopenharmony_ci/* 7948c2ecf20Sopenharmony_ci * Generic functions with hash/radix callbacks 7958c2ecf20Sopenharmony_ci */ 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_cistatic inline void __ptep_set_access_flags(struct vm_area_struct *vma, 7988c2ecf20Sopenharmony_ci pte_t *ptep, pte_t entry, 7998c2ecf20Sopenharmony_ci unsigned long address, 8008c2ecf20Sopenharmony_ci int psize) 8018c2ecf20Sopenharmony_ci{ 8028c2ecf20Sopenharmony_ci if (radix_enabled()) 8038c2ecf20Sopenharmony_ci return radix__ptep_set_access_flags(vma, ptep, entry, 8048c2ecf20Sopenharmony_ci address, psize); 8058c2ecf20Sopenharmony_ci return hash__ptep_set_access_flags(ptep, entry); 8068c2ecf20Sopenharmony_ci} 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTE_SAME 8098c2ecf20Sopenharmony_cistatic inline int pte_same(pte_t pte_a, pte_t pte_b) 8108c2ecf20Sopenharmony_ci{ 8118c2ecf20Sopenharmony_ci if (radix_enabled()) 8128c2ecf20Sopenharmony_ci return radix__pte_same(pte_a, pte_b); 8138c2ecf20Sopenharmony_ci return hash__pte_same(pte_a, pte_b); 8148c2ecf20Sopenharmony_ci} 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_cistatic inline int pte_none(pte_t pte) 8178c2ecf20Sopenharmony_ci{ 8188c2ecf20Sopenharmony_ci if (radix_enabled()) 8198c2ecf20Sopenharmony_ci return radix__pte_none(pte); 8208c2ecf20Sopenharmony_ci return hash__pte_none(pte); 8218c2ecf20Sopenharmony_ci} 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_cistatic inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, 8248c2ecf20Sopenharmony_ci pte_t *ptep, pte_t pte, int percpu) 8258c2ecf20Sopenharmony_ci{ 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci VM_WARN_ON(!(pte_raw(pte) & cpu_to_be64(_PAGE_PTE))); 8288c2ecf20Sopenharmony_ci /* 8298c2ecf20Sopenharmony_ci * Keep the _PAGE_PTE added till we are sure we handle _PAGE_PTE 8308c2ecf20Sopenharmony_ci * in all the callers. 8318c2ecf20Sopenharmony_ci */ 8328c2ecf20Sopenharmony_ci pte = __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_PTE)); 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci if (radix_enabled()) 8358c2ecf20Sopenharmony_ci return radix__set_pte_at(mm, addr, ptep, pte, percpu); 8368c2ecf20Sopenharmony_ci return hash__set_pte_at(mm, addr, ptep, pte, percpu); 8378c2ecf20Sopenharmony_ci} 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci#define _PAGE_CACHE_CTL (_PAGE_SAO | _PAGE_NON_IDEMPOTENT | _PAGE_TOLERANT) 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci#define pgprot_noncached pgprot_noncached 8428c2ecf20Sopenharmony_cistatic inline pgprot_t pgprot_noncached(pgprot_t prot) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | 8458c2ecf20Sopenharmony_ci _PAGE_NON_IDEMPOTENT); 8468c2ecf20Sopenharmony_ci} 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci#define pgprot_noncached_wc pgprot_noncached_wc 8498c2ecf20Sopenharmony_cistatic inline pgprot_t pgprot_noncached_wc(pgprot_t prot) 8508c2ecf20Sopenharmony_ci{ 8518c2ecf20Sopenharmony_ci return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | 8528c2ecf20Sopenharmony_ci _PAGE_TOLERANT); 8538c2ecf20Sopenharmony_ci} 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci#define pgprot_cached pgprot_cached 8568c2ecf20Sopenharmony_cistatic inline pgprot_t pgprot_cached(pgprot_t prot) 8578c2ecf20Sopenharmony_ci{ 8588c2ecf20Sopenharmony_ci return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL)); 8598c2ecf20Sopenharmony_ci} 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci#define pgprot_writecombine pgprot_writecombine 8628c2ecf20Sopenharmony_cistatic inline pgprot_t pgprot_writecombine(pgprot_t prot) 8638c2ecf20Sopenharmony_ci{ 8648c2ecf20Sopenharmony_ci return pgprot_noncached_wc(prot); 8658c2ecf20Sopenharmony_ci} 8668c2ecf20Sopenharmony_ci/* 8678c2ecf20Sopenharmony_ci * check a pte mapping have cache inhibited property 8688c2ecf20Sopenharmony_ci */ 8698c2ecf20Sopenharmony_cistatic inline bool pte_ci(pte_t pte) 8708c2ecf20Sopenharmony_ci{ 8718c2ecf20Sopenharmony_ci __be64 pte_v = pte_raw(pte); 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci if (((pte_v & cpu_to_be64(_PAGE_CACHE_CTL)) == cpu_to_be64(_PAGE_TOLERANT)) || 8748c2ecf20Sopenharmony_ci ((pte_v & cpu_to_be64(_PAGE_CACHE_CTL)) == cpu_to_be64(_PAGE_NON_IDEMPOTENT))) 8758c2ecf20Sopenharmony_ci return true; 8768c2ecf20Sopenharmony_ci return false; 8778c2ecf20Sopenharmony_ci} 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_cistatic inline void pmd_clear(pmd_t *pmdp) 8808c2ecf20Sopenharmony_ci{ 8818c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_DEBUG_VM) && !radix_enabled()) { 8828c2ecf20Sopenharmony_ci /* 8838c2ecf20Sopenharmony_ci * Don't use this if we can possibly have a hash page table 8848c2ecf20Sopenharmony_ci * entry mapping this. 8858c2ecf20Sopenharmony_ci */ 8868c2ecf20Sopenharmony_ci WARN_ON((pmd_val(*pmdp) & (H_PAGE_HASHPTE | _PAGE_PTE)) == (H_PAGE_HASHPTE | _PAGE_PTE)); 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci *pmdp = __pmd(0); 8898c2ecf20Sopenharmony_ci} 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_cistatic inline int pmd_none(pmd_t pmd) 8928c2ecf20Sopenharmony_ci{ 8938c2ecf20Sopenharmony_ci return !pmd_raw(pmd); 8948c2ecf20Sopenharmony_ci} 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_cistatic inline int pmd_present(pmd_t pmd) 8978c2ecf20Sopenharmony_ci{ 8988c2ecf20Sopenharmony_ci /* 8998c2ecf20Sopenharmony_ci * A pmd is considerent present if _PAGE_PRESENT is set. 9008c2ecf20Sopenharmony_ci * We also need to consider the pmd present which is marked 9018c2ecf20Sopenharmony_ci * invalid during a split. Hence we look for _PAGE_INVALID 9028c2ecf20Sopenharmony_ci * if we find _PAGE_PRESENT cleared. 9038c2ecf20Sopenharmony_ci */ 9048c2ecf20Sopenharmony_ci if (pmd_raw(pmd) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID)) 9058c2ecf20Sopenharmony_ci return true; 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci return false; 9088c2ecf20Sopenharmony_ci} 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_cistatic inline int pmd_is_serializing(pmd_t pmd) 9118c2ecf20Sopenharmony_ci{ 9128c2ecf20Sopenharmony_ci /* 9138c2ecf20Sopenharmony_ci * If the pmd is undergoing a split, the _PAGE_PRESENT bit is clear 9148c2ecf20Sopenharmony_ci * and _PAGE_INVALID is set (see pmd_present, pmdp_invalidate). 9158c2ecf20Sopenharmony_ci * 9168c2ecf20Sopenharmony_ci * This condition may also occur when flushing a pmd while flushing 9178c2ecf20Sopenharmony_ci * it (see ptep_modify_prot_start), so callers must ensure this 9188c2ecf20Sopenharmony_ci * case is fine as well. 9198c2ecf20Sopenharmony_ci */ 9208c2ecf20Sopenharmony_ci if ((pmd_raw(pmd) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID)) == 9218c2ecf20Sopenharmony_ci cpu_to_be64(_PAGE_INVALID)) 9228c2ecf20Sopenharmony_ci return true; 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci return false; 9258c2ecf20Sopenharmony_ci} 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_cistatic inline int pmd_bad(pmd_t pmd) 9288c2ecf20Sopenharmony_ci{ 9298c2ecf20Sopenharmony_ci if (radix_enabled()) 9308c2ecf20Sopenharmony_ci return radix__pmd_bad(pmd); 9318c2ecf20Sopenharmony_ci return hash__pmd_bad(pmd); 9328c2ecf20Sopenharmony_ci} 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_cistatic inline void pud_clear(pud_t *pudp) 9358c2ecf20Sopenharmony_ci{ 9368c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_DEBUG_VM) && !radix_enabled()) { 9378c2ecf20Sopenharmony_ci /* 9388c2ecf20Sopenharmony_ci * Don't use this if we can possibly have a hash page table 9398c2ecf20Sopenharmony_ci * entry mapping this. 9408c2ecf20Sopenharmony_ci */ 9418c2ecf20Sopenharmony_ci WARN_ON((pud_val(*pudp) & (H_PAGE_HASHPTE | _PAGE_PTE)) == (H_PAGE_HASHPTE | _PAGE_PTE)); 9428c2ecf20Sopenharmony_ci } 9438c2ecf20Sopenharmony_ci *pudp = __pud(0); 9448c2ecf20Sopenharmony_ci} 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_cistatic inline int pud_none(pud_t pud) 9478c2ecf20Sopenharmony_ci{ 9488c2ecf20Sopenharmony_ci return !pud_raw(pud); 9498c2ecf20Sopenharmony_ci} 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_cistatic inline int pud_present(pud_t pud) 9528c2ecf20Sopenharmony_ci{ 9538c2ecf20Sopenharmony_ci return !!(pud_raw(pud) & cpu_to_be64(_PAGE_PRESENT)); 9548c2ecf20Sopenharmony_ci} 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ciextern struct page *pud_page(pud_t pud); 9578c2ecf20Sopenharmony_ciextern struct page *pmd_page(pmd_t pmd); 9588c2ecf20Sopenharmony_cistatic inline pte_t pud_pte(pud_t pud) 9598c2ecf20Sopenharmony_ci{ 9608c2ecf20Sopenharmony_ci return __pte_raw(pud_raw(pud)); 9618c2ecf20Sopenharmony_ci} 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_cistatic inline pud_t pte_pud(pte_t pte) 9648c2ecf20Sopenharmony_ci{ 9658c2ecf20Sopenharmony_ci return __pud_raw(pte_raw(pte)); 9668c2ecf20Sopenharmony_ci} 9678c2ecf20Sopenharmony_ci#define pud_write(pud) pte_write(pud_pte(pud)) 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_cistatic inline int pud_bad(pud_t pud) 9708c2ecf20Sopenharmony_ci{ 9718c2ecf20Sopenharmony_ci if (radix_enabled()) 9728c2ecf20Sopenharmony_ci return radix__pud_bad(pud); 9738c2ecf20Sopenharmony_ci return hash__pud_bad(pud); 9748c2ecf20Sopenharmony_ci} 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci#define pud_access_permitted pud_access_permitted 9778c2ecf20Sopenharmony_cistatic inline bool pud_access_permitted(pud_t pud, bool write) 9788c2ecf20Sopenharmony_ci{ 9798c2ecf20Sopenharmony_ci return pte_access_permitted(pud_pte(pud), write); 9808c2ecf20Sopenharmony_ci} 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci#define __p4d_raw(x) ((p4d_t) { __pgd_raw(x) }) 9838c2ecf20Sopenharmony_cistatic inline __be64 p4d_raw(p4d_t x) 9848c2ecf20Sopenharmony_ci{ 9858c2ecf20Sopenharmony_ci return pgd_raw(x.pgd); 9868c2ecf20Sopenharmony_ci} 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci#define p4d_write(p4d) pte_write(p4d_pte(p4d)) 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_cistatic inline void p4d_clear(p4d_t *p4dp) 9918c2ecf20Sopenharmony_ci{ 9928c2ecf20Sopenharmony_ci *p4dp = __p4d(0); 9938c2ecf20Sopenharmony_ci} 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_cistatic inline int p4d_none(p4d_t p4d) 9968c2ecf20Sopenharmony_ci{ 9978c2ecf20Sopenharmony_ci return !p4d_raw(p4d); 9988c2ecf20Sopenharmony_ci} 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_cistatic inline int p4d_present(p4d_t p4d) 10018c2ecf20Sopenharmony_ci{ 10028c2ecf20Sopenharmony_ci return !!(p4d_raw(p4d) & cpu_to_be64(_PAGE_PRESENT)); 10038c2ecf20Sopenharmony_ci} 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_cistatic inline pte_t p4d_pte(p4d_t p4d) 10068c2ecf20Sopenharmony_ci{ 10078c2ecf20Sopenharmony_ci return __pte_raw(p4d_raw(p4d)); 10088c2ecf20Sopenharmony_ci} 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_cistatic inline p4d_t pte_p4d(pte_t pte) 10118c2ecf20Sopenharmony_ci{ 10128c2ecf20Sopenharmony_ci return __p4d_raw(pte_raw(pte)); 10138c2ecf20Sopenharmony_ci} 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_cistatic inline int p4d_bad(p4d_t p4d) 10168c2ecf20Sopenharmony_ci{ 10178c2ecf20Sopenharmony_ci if (radix_enabled()) 10188c2ecf20Sopenharmony_ci return radix__p4d_bad(p4d); 10198c2ecf20Sopenharmony_ci return hash__p4d_bad(p4d); 10208c2ecf20Sopenharmony_ci} 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci#define p4d_access_permitted p4d_access_permitted 10238c2ecf20Sopenharmony_cistatic inline bool p4d_access_permitted(p4d_t p4d, bool write) 10248c2ecf20Sopenharmony_ci{ 10258c2ecf20Sopenharmony_ci return pte_access_permitted(p4d_pte(p4d), write); 10268c2ecf20Sopenharmony_ci} 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ciextern struct page *p4d_page(p4d_t p4d); 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci/* Pointers in the page table tree are physical addresses */ 10318c2ecf20Sopenharmony_ci#define __pgtable_ptr_val(ptr) __pa(ptr) 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_cistatic inline pud_t *p4d_pgtable(p4d_t p4d) 10348c2ecf20Sopenharmony_ci{ 10358c2ecf20Sopenharmony_ci return (pud_t *)__va(p4d_val(p4d) & ~P4D_MASKED_BITS); 10368c2ecf20Sopenharmony_ci} 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_cistatic inline pmd_t *pud_pgtable(pud_t pud) 10398c2ecf20Sopenharmony_ci{ 10408c2ecf20Sopenharmony_ci return (pmd_t *)__va(pud_val(pud) & ~PUD_MASKED_BITS); 10418c2ecf20Sopenharmony_ci} 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci#define pte_ERROR(e) \ 10448c2ecf20Sopenharmony_ci pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) 10458c2ecf20Sopenharmony_ci#define pmd_ERROR(e) \ 10468c2ecf20Sopenharmony_ci pr_err("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) 10478c2ecf20Sopenharmony_ci#define pud_ERROR(e) \ 10488c2ecf20Sopenharmony_ci pr_err("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e)) 10498c2ecf20Sopenharmony_ci#define pgd_ERROR(e) \ 10508c2ecf20Sopenharmony_ci pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_cistatic inline int map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot) 10538c2ecf20Sopenharmony_ci{ 10548c2ecf20Sopenharmony_ci if (radix_enabled()) { 10558c2ecf20Sopenharmony_ci#if defined(CONFIG_PPC_RADIX_MMU) && defined(DEBUG_VM) 10568c2ecf20Sopenharmony_ci unsigned long page_size = 1 << mmu_psize_defs[mmu_io_psize].shift; 10578c2ecf20Sopenharmony_ci WARN((page_size != PAGE_SIZE), "I/O page size != PAGE_SIZE"); 10588c2ecf20Sopenharmony_ci#endif 10598c2ecf20Sopenharmony_ci return radix__map_kernel_page(ea, pa, prot, PAGE_SIZE); 10608c2ecf20Sopenharmony_ci } 10618c2ecf20Sopenharmony_ci return hash__map_kernel_page(ea, pa, prot); 10628c2ecf20Sopenharmony_ci} 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_civoid unmap_kernel_page(unsigned long va); 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_cistatic inline int __meminit vmemmap_create_mapping(unsigned long start, 10678c2ecf20Sopenharmony_ci unsigned long page_size, 10688c2ecf20Sopenharmony_ci unsigned long phys) 10698c2ecf20Sopenharmony_ci{ 10708c2ecf20Sopenharmony_ci if (radix_enabled()) 10718c2ecf20Sopenharmony_ci return radix__vmemmap_create_mapping(start, page_size, phys); 10728c2ecf20Sopenharmony_ci return hash__vmemmap_create_mapping(start, page_size, phys); 10738c2ecf20Sopenharmony_ci} 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci#ifdef CONFIG_MEMORY_HOTPLUG 10768c2ecf20Sopenharmony_cistatic inline void vmemmap_remove_mapping(unsigned long start, 10778c2ecf20Sopenharmony_ci unsigned long page_size) 10788c2ecf20Sopenharmony_ci{ 10798c2ecf20Sopenharmony_ci if (radix_enabled()) 10808c2ecf20Sopenharmony_ci return radix__vmemmap_remove_mapping(start, page_size); 10818c2ecf20Sopenharmony_ci return hash__vmemmap_remove_mapping(start, page_size); 10828c2ecf20Sopenharmony_ci} 10838c2ecf20Sopenharmony_ci#endif 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_cistatic inline pte_t pmd_pte(pmd_t pmd) 10868c2ecf20Sopenharmony_ci{ 10878c2ecf20Sopenharmony_ci return __pte_raw(pmd_raw(pmd)); 10888c2ecf20Sopenharmony_ci} 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_cistatic inline pmd_t pte_pmd(pte_t pte) 10918c2ecf20Sopenharmony_ci{ 10928c2ecf20Sopenharmony_ci return __pmd_raw(pte_raw(pte)); 10938c2ecf20Sopenharmony_ci} 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_cistatic inline pte_t *pmdp_ptep(pmd_t *pmd) 10968c2ecf20Sopenharmony_ci{ 10978c2ecf20Sopenharmony_ci return (pte_t *)pmd; 10988c2ecf20Sopenharmony_ci} 10998c2ecf20Sopenharmony_ci#define pmd_pfn(pmd) pte_pfn(pmd_pte(pmd)) 11008c2ecf20Sopenharmony_ci#define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd)) 11018c2ecf20Sopenharmony_ci#define pmd_young(pmd) pte_young(pmd_pte(pmd)) 11028c2ecf20Sopenharmony_ci#define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd))) 11038c2ecf20Sopenharmony_ci#define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd))) 11048c2ecf20Sopenharmony_ci#define pmd_mkdirty(pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd))) 11058c2ecf20Sopenharmony_ci#define pmd_mkclean(pmd) pte_pmd(pte_mkclean(pmd_pte(pmd))) 11068c2ecf20Sopenharmony_ci#define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd))) 11078c2ecf20Sopenharmony_ci#define pmd_mkwrite(pmd) pte_pmd(pte_mkwrite(pmd_pte(pmd))) 11088c2ecf20Sopenharmony_ci#define pmd_mk_savedwrite(pmd) pte_pmd(pte_mk_savedwrite(pmd_pte(pmd))) 11098c2ecf20Sopenharmony_ci#define pmd_clear_savedwrite(pmd) pte_pmd(pte_clear_savedwrite(pmd_pte(pmd))) 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY 11128c2ecf20Sopenharmony_ci#define pmd_soft_dirty(pmd) pte_soft_dirty(pmd_pte(pmd)) 11138c2ecf20Sopenharmony_ci#define pmd_mksoft_dirty(pmd) pte_pmd(pte_mksoft_dirty(pmd_pte(pmd))) 11148c2ecf20Sopenharmony_ci#define pmd_clear_soft_dirty(pmd) pte_pmd(pte_clear_soft_dirty(pmd_pte(pmd))) 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION 11178c2ecf20Sopenharmony_ci#define pmd_swp_mksoft_dirty(pmd) pte_pmd(pte_swp_mksoft_dirty(pmd_pte(pmd))) 11188c2ecf20Sopenharmony_ci#define pmd_swp_soft_dirty(pmd) pte_swp_soft_dirty(pmd_pte(pmd)) 11198c2ecf20Sopenharmony_ci#define pmd_swp_clear_soft_dirty(pmd) pte_pmd(pte_swp_clear_soft_dirty(pmd_pte(pmd))) 11208c2ecf20Sopenharmony_ci#endif 11218c2ecf20Sopenharmony_ci#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */ 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci#ifdef CONFIG_NUMA_BALANCING 11248c2ecf20Sopenharmony_cistatic inline int pmd_protnone(pmd_t pmd) 11258c2ecf20Sopenharmony_ci{ 11268c2ecf20Sopenharmony_ci return pte_protnone(pmd_pte(pmd)); 11278c2ecf20Sopenharmony_ci} 11288c2ecf20Sopenharmony_ci#endif /* CONFIG_NUMA_BALANCING */ 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci#define pmd_write(pmd) pte_write(pmd_pte(pmd)) 11318c2ecf20Sopenharmony_ci#define __pmd_write(pmd) __pte_write(pmd_pte(pmd)) 11328c2ecf20Sopenharmony_ci#define pmd_savedwrite(pmd) pte_savedwrite(pmd_pte(pmd)) 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci#define pmd_access_permitted pmd_access_permitted 11358c2ecf20Sopenharmony_cistatic inline bool pmd_access_permitted(pmd_t pmd, bool write) 11368c2ecf20Sopenharmony_ci{ 11378c2ecf20Sopenharmony_ci /* 11388c2ecf20Sopenharmony_ci * pmdp_invalidate sets this combination (which is not caught by 11398c2ecf20Sopenharmony_ci * !pte_present() check in pte_access_permitted), to prevent 11408c2ecf20Sopenharmony_ci * lock-free lookups, as part of the serialize_against_pte_lookup() 11418c2ecf20Sopenharmony_ci * synchronisation. 11428c2ecf20Sopenharmony_ci * 11438c2ecf20Sopenharmony_ci * This also catches the case where the PTE's hardware PRESENT bit is 11448c2ecf20Sopenharmony_ci * cleared while TLB is flushed, which is suboptimal but should not 11458c2ecf20Sopenharmony_ci * be frequent. 11468c2ecf20Sopenharmony_ci */ 11478c2ecf20Sopenharmony_ci if (pmd_is_serializing(pmd)) 11488c2ecf20Sopenharmony_ci return false; 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci return pte_access_permitted(pmd_pte(pmd), write); 11518c2ecf20Sopenharmony_ci} 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci#ifdef CONFIG_TRANSPARENT_HUGEPAGE 11548c2ecf20Sopenharmony_ciextern pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot); 11558c2ecf20Sopenharmony_ciextern pmd_t mk_pmd(struct page *page, pgprot_t pgprot); 11568c2ecf20Sopenharmony_ciextern pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot); 11578c2ecf20Sopenharmony_ciextern void set_pmd_at(struct mm_struct *mm, unsigned long addr, 11588c2ecf20Sopenharmony_ci pmd_t *pmdp, pmd_t pmd); 11598c2ecf20Sopenharmony_cistatic inline void update_mmu_cache_pmd(struct vm_area_struct *vma, 11608c2ecf20Sopenharmony_ci unsigned long addr, pmd_t *pmd) 11618c2ecf20Sopenharmony_ci{ 11628c2ecf20Sopenharmony_ci} 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ciextern int hash__has_transparent_hugepage(void); 11658c2ecf20Sopenharmony_cistatic inline int has_transparent_hugepage(void) 11668c2ecf20Sopenharmony_ci{ 11678c2ecf20Sopenharmony_ci if (radix_enabled()) 11688c2ecf20Sopenharmony_ci return radix__has_transparent_hugepage(); 11698c2ecf20Sopenharmony_ci return hash__has_transparent_hugepage(); 11708c2ecf20Sopenharmony_ci} 11718c2ecf20Sopenharmony_ci#define has_transparent_hugepage has_transparent_hugepage 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_cistatic inline unsigned long 11748c2ecf20Sopenharmony_cipmd_hugepage_update(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp, 11758c2ecf20Sopenharmony_ci unsigned long clr, unsigned long set) 11768c2ecf20Sopenharmony_ci{ 11778c2ecf20Sopenharmony_ci if (radix_enabled()) 11788c2ecf20Sopenharmony_ci return radix__pmd_hugepage_update(mm, addr, pmdp, clr, set); 11798c2ecf20Sopenharmony_ci return hash__pmd_hugepage_update(mm, addr, pmdp, clr, set); 11808c2ecf20Sopenharmony_ci} 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci/* 11838c2ecf20Sopenharmony_ci * returns true for pmd migration entries, THP, devmap, hugetlb 11848c2ecf20Sopenharmony_ci * But compile time dependent on THP config 11858c2ecf20Sopenharmony_ci */ 11868c2ecf20Sopenharmony_cistatic inline int pmd_large(pmd_t pmd) 11878c2ecf20Sopenharmony_ci{ 11888c2ecf20Sopenharmony_ci return !!(pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE)); 11898c2ecf20Sopenharmony_ci} 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci/* 11928c2ecf20Sopenharmony_ci * For radix we should always find H_PAGE_HASHPTE zero. Hence 11938c2ecf20Sopenharmony_ci * the below will work for radix too 11948c2ecf20Sopenharmony_ci */ 11958c2ecf20Sopenharmony_cistatic inline int __pmdp_test_and_clear_young(struct mm_struct *mm, 11968c2ecf20Sopenharmony_ci unsigned long addr, pmd_t *pmdp) 11978c2ecf20Sopenharmony_ci{ 11988c2ecf20Sopenharmony_ci unsigned long old; 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci if ((pmd_raw(*pmdp) & cpu_to_be64(_PAGE_ACCESSED | H_PAGE_HASHPTE)) == 0) 12018c2ecf20Sopenharmony_ci return 0; 12028c2ecf20Sopenharmony_ci old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED, 0); 12038c2ecf20Sopenharmony_ci return ((old & _PAGE_ACCESSED) != 0); 12048c2ecf20Sopenharmony_ci} 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_SET_WRPROTECT 12078c2ecf20Sopenharmony_cistatic inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr, 12088c2ecf20Sopenharmony_ci pmd_t *pmdp) 12098c2ecf20Sopenharmony_ci{ 12108c2ecf20Sopenharmony_ci if (__pmd_write((*pmdp))) 12118c2ecf20Sopenharmony_ci pmd_hugepage_update(mm, addr, pmdp, _PAGE_WRITE, 0); 12128c2ecf20Sopenharmony_ci else if (unlikely(pmd_savedwrite(*pmdp))) 12138c2ecf20Sopenharmony_ci pmd_hugepage_update(mm, addr, pmdp, 0, _PAGE_PRIVILEGED); 12148c2ecf20Sopenharmony_ci} 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci/* 12178c2ecf20Sopenharmony_ci * Only returns true for a THP. False for pmd migration entry. 12188c2ecf20Sopenharmony_ci * We also need to return true when we come across a pte that 12198c2ecf20Sopenharmony_ci * in between a thp split. While splitting THP, we mark the pmd 12208c2ecf20Sopenharmony_ci * invalid (pmdp_invalidate()) before we set it with pte page 12218c2ecf20Sopenharmony_ci * address. A pmd_trans_huge() check against a pmd entry during that time 12228c2ecf20Sopenharmony_ci * should return true. 12238c2ecf20Sopenharmony_ci * We should not call this on a hugetlb entry. We should check for HugeTLB 12248c2ecf20Sopenharmony_ci * entry using vma->vm_flags 12258c2ecf20Sopenharmony_ci * The page table walk rule is explained in Documentation/vm/transhuge.rst 12268c2ecf20Sopenharmony_ci */ 12278c2ecf20Sopenharmony_cistatic inline int pmd_trans_huge(pmd_t pmd) 12288c2ecf20Sopenharmony_ci{ 12298c2ecf20Sopenharmony_ci if (!pmd_present(pmd)) 12308c2ecf20Sopenharmony_ci return false; 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_ci if (radix_enabled()) 12338c2ecf20Sopenharmony_ci return radix__pmd_trans_huge(pmd); 12348c2ecf20Sopenharmony_ci return hash__pmd_trans_huge(pmd); 12358c2ecf20Sopenharmony_ci} 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMD_SAME 12388c2ecf20Sopenharmony_cistatic inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b) 12398c2ecf20Sopenharmony_ci{ 12408c2ecf20Sopenharmony_ci if (radix_enabled()) 12418c2ecf20Sopenharmony_ci return radix__pmd_same(pmd_a, pmd_b); 12428c2ecf20Sopenharmony_ci return hash__pmd_same(pmd_a, pmd_b); 12438c2ecf20Sopenharmony_ci} 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkhuge(pmd_t pmd) 12468c2ecf20Sopenharmony_ci{ 12478c2ecf20Sopenharmony_ci if (radix_enabled()) 12488c2ecf20Sopenharmony_ci return radix__pmd_mkhuge(pmd); 12498c2ecf20Sopenharmony_ci return hash__pmd_mkhuge(pmd); 12508c2ecf20Sopenharmony_ci} 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS 12538c2ecf20Sopenharmony_ciextern int pmdp_set_access_flags(struct vm_area_struct *vma, 12548c2ecf20Sopenharmony_ci unsigned long address, pmd_t *pmdp, 12558c2ecf20Sopenharmony_ci pmd_t entry, int dirty); 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG 12588c2ecf20Sopenharmony_ciextern int pmdp_test_and_clear_young(struct vm_area_struct *vma, 12598c2ecf20Sopenharmony_ci unsigned long address, pmd_t *pmdp); 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR 12628c2ecf20Sopenharmony_cistatic inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, 12638c2ecf20Sopenharmony_ci unsigned long addr, pmd_t *pmdp) 12648c2ecf20Sopenharmony_ci{ 12658c2ecf20Sopenharmony_ci if (radix_enabled()) 12668c2ecf20Sopenharmony_ci return radix__pmdp_huge_get_and_clear(mm, addr, pmdp); 12678c2ecf20Sopenharmony_ci return hash__pmdp_huge_get_and_clear(mm, addr, pmdp); 12688c2ecf20Sopenharmony_ci} 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_cistatic inline pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, 12718c2ecf20Sopenharmony_ci unsigned long address, pmd_t *pmdp) 12728c2ecf20Sopenharmony_ci{ 12738c2ecf20Sopenharmony_ci if (radix_enabled()) 12748c2ecf20Sopenharmony_ci return radix__pmdp_collapse_flush(vma, address, pmdp); 12758c2ecf20Sopenharmony_ci return hash__pmdp_collapse_flush(vma, address, pmdp); 12768c2ecf20Sopenharmony_ci} 12778c2ecf20Sopenharmony_ci#define pmdp_collapse_flush pmdp_collapse_flush 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR_FULL 12808c2ecf20Sopenharmony_cipmd_t pmdp_huge_get_and_clear_full(struct vm_area_struct *vma, 12818c2ecf20Sopenharmony_ci unsigned long addr, 12828c2ecf20Sopenharmony_ci pmd_t *pmdp, int full); 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PGTABLE_DEPOSIT 12858c2ecf20Sopenharmony_cistatic inline void pgtable_trans_huge_deposit(struct mm_struct *mm, 12868c2ecf20Sopenharmony_ci pmd_t *pmdp, pgtable_t pgtable) 12878c2ecf20Sopenharmony_ci{ 12888c2ecf20Sopenharmony_ci if (radix_enabled()) 12898c2ecf20Sopenharmony_ci return radix__pgtable_trans_huge_deposit(mm, pmdp, pgtable); 12908c2ecf20Sopenharmony_ci return hash__pgtable_trans_huge_deposit(mm, pmdp, pgtable); 12918c2ecf20Sopenharmony_ci} 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PGTABLE_WITHDRAW 12948c2ecf20Sopenharmony_cistatic inline pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, 12958c2ecf20Sopenharmony_ci pmd_t *pmdp) 12968c2ecf20Sopenharmony_ci{ 12978c2ecf20Sopenharmony_ci if (radix_enabled()) 12988c2ecf20Sopenharmony_ci return radix__pgtable_trans_huge_withdraw(mm, pmdp); 12998c2ecf20Sopenharmony_ci return hash__pgtable_trans_huge_withdraw(mm, pmdp); 13008c2ecf20Sopenharmony_ci} 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_INVALIDATE 13038c2ecf20Sopenharmony_ciextern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, 13048c2ecf20Sopenharmony_ci pmd_t *pmdp); 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci#define pmd_move_must_withdraw pmd_move_must_withdraw 13078c2ecf20Sopenharmony_cistruct spinlock; 13088c2ecf20Sopenharmony_ciextern int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl, 13098c2ecf20Sopenharmony_ci struct spinlock *old_pmd_ptl, 13108c2ecf20Sopenharmony_ci struct vm_area_struct *vma); 13118c2ecf20Sopenharmony_ci/* 13128c2ecf20Sopenharmony_ci * Hash translation mode use the deposited table to store hash pte 13138c2ecf20Sopenharmony_ci * slot information. 13148c2ecf20Sopenharmony_ci */ 13158c2ecf20Sopenharmony_ci#define arch_needs_pgtable_deposit arch_needs_pgtable_deposit 13168c2ecf20Sopenharmony_cistatic inline bool arch_needs_pgtable_deposit(void) 13178c2ecf20Sopenharmony_ci{ 13188c2ecf20Sopenharmony_ci if (radix_enabled()) 13198c2ecf20Sopenharmony_ci return false; 13208c2ecf20Sopenharmony_ci return true; 13218c2ecf20Sopenharmony_ci} 13228c2ecf20Sopenharmony_ciextern void serialize_against_pte_lookup(struct mm_struct *mm); 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkdevmap(pmd_t pmd) 13268c2ecf20Sopenharmony_ci{ 13278c2ecf20Sopenharmony_ci if (radix_enabled()) 13288c2ecf20Sopenharmony_ci return radix__pmd_mkdevmap(pmd); 13298c2ecf20Sopenharmony_ci return hash__pmd_mkdevmap(pmd); 13308c2ecf20Sopenharmony_ci} 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_cistatic inline int pmd_devmap(pmd_t pmd) 13338c2ecf20Sopenharmony_ci{ 13348c2ecf20Sopenharmony_ci return pte_devmap(pmd_pte(pmd)); 13358c2ecf20Sopenharmony_ci} 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_cistatic inline int pud_devmap(pud_t pud) 13388c2ecf20Sopenharmony_ci{ 13398c2ecf20Sopenharmony_ci return 0; 13408c2ecf20Sopenharmony_ci} 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_cistatic inline int pgd_devmap(pgd_t pgd) 13438c2ecf20Sopenharmony_ci{ 13448c2ecf20Sopenharmony_ci return 0; 13458c2ecf20Sopenharmony_ci} 13468c2ecf20Sopenharmony_ci#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_cistatic inline int pud_pfn(pud_t pud) 13498c2ecf20Sopenharmony_ci{ 13508c2ecf20Sopenharmony_ci /* 13518c2ecf20Sopenharmony_ci * Currently all calls to pud_pfn() are gated around a pud_devmap() 13528c2ecf20Sopenharmony_ci * check so this should never be used. If it grows another user we 13538c2ecf20Sopenharmony_ci * want to know about it. 13548c2ecf20Sopenharmony_ci */ 13558c2ecf20Sopenharmony_ci BUILD_BUG(); 13568c2ecf20Sopenharmony_ci return 0; 13578c2ecf20Sopenharmony_ci} 13588c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION 13598c2ecf20Sopenharmony_cipte_t ptep_modify_prot_start(struct vm_area_struct *, unsigned long, pte_t *); 13608c2ecf20Sopenharmony_civoid ptep_modify_prot_commit(struct vm_area_struct *, unsigned long, 13618c2ecf20Sopenharmony_ci pte_t *, pte_t, pte_t); 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci/* 13648c2ecf20Sopenharmony_ci * Returns true for a R -> RW upgrade of pte 13658c2ecf20Sopenharmony_ci */ 13668c2ecf20Sopenharmony_cistatic inline bool is_pte_rw_upgrade(unsigned long old_val, unsigned long new_val) 13678c2ecf20Sopenharmony_ci{ 13688c2ecf20Sopenharmony_ci if (!(old_val & _PAGE_READ)) 13698c2ecf20Sopenharmony_ci return false; 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci if ((!(old_val & _PAGE_WRITE)) && (new_val & _PAGE_WRITE)) 13728c2ecf20Sopenharmony_ci return true; 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_ci return false; 13758c2ecf20Sopenharmony_ci} 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_ci/* 13788c2ecf20Sopenharmony_ci * Like pmd_huge() and pmd_large(), but works regardless of config options 13798c2ecf20Sopenharmony_ci */ 13808c2ecf20Sopenharmony_ci#define pmd_is_leaf pmd_is_leaf 13818c2ecf20Sopenharmony_ci#define pmd_leaf pmd_is_leaf 13828c2ecf20Sopenharmony_cistatic inline bool pmd_is_leaf(pmd_t pmd) 13838c2ecf20Sopenharmony_ci{ 13848c2ecf20Sopenharmony_ci return !!(pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE)); 13858c2ecf20Sopenharmony_ci} 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_ci#define pud_is_leaf pud_is_leaf 13888c2ecf20Sopenharmony_ci#define pud_leaf pud_is_leaf 13898c2ecf20Sopenharmony_cistatic inline bool pud_is_leaf(pud_t pud) 13908c2ecf20Sopenharmony_ci{ 13918c2ecf20Sopenharmony_ci return !!(pud_raw(pud) & cpu_to_be64(_PAGE_PTE)); 13928c2ecf20Sopenharmony_ci} 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci#define p4d_is_leaf p4d_is_leaf 13958c2ecf20Sopenharmony_ci#define p4d_leaf p4d_is_leaf 13968c2ecf20Sopenharmony_cistatic inline bool p4d_is_leaf(p4d_t p4d) 13978c2ecf20Sopenharmony_ci{ 13988c2ecf20Sopenharmony_ci return !!(p4d_raw(p4d) & cpu_to_be64(_PAGE_PTE)); 13998c2ecf20Sopenharmony_ci} 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */ 14028c2ecf20Sopenharmony_ci#endif /* _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ */ 1403