18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef _ASM_POWERPC_NOHASH_32_PGTABLE_H 38c2ecf20Sopenharmony_ci#define _ASM_POWERPC_NOHASH_32_PGTABLE_H 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <asm-generic/pgtable-nopmd.h> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 88c2ecf20Sopenharmony_ci#include <linux/sched.h> 98c2ecf20Sopenharmony_ci#include <linux/threads.h> 108c2ecf20Sopenharmony_ci#include <asm/mmu.h> /* For sub-arch specific PPC_PIN_SIZE */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#ifdef CONFIG_44x 138c2ecf20Sopenharmony_ciextern int icache_44x_need_flush; 148c2ecf20Sopenharmony_ci#endif 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define PTE_INDEX_SIZE PTE_SHIFT 198c2ecf20Sopenharmony_ci#define PMD_INDEX_SIZE 0 208c2ecf20Sopenharmony_ci#define PUD_INDEX_SIZE 0 218c2ecf20Sopenharmony_ci#define PGD_INDEX_SIZE (32 - PGDIR_SHIFT) 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define PMD_CACHE_INDEX PMD_INDEX_SIZE 248c2ecf20Sopenharmony_ci#define PUD_CACHE_INDEX PUD_INDEX_SIZE 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 278c2ecf20Sopenharmony_ci#define PTE_TABLE_SIZE (sizeof(pte_t) << PTE_INDEX_SIZE) 288c2ecf20Sopenharmony_ci#define PMD_TABLE_SIZE 0 298c2ecf20Sopenharmony_ci#define PUD_TABLE_SIZE 0 308c2ecf20Sopenharmony_ci#define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE) 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define PMD_MASKED_BITS (PTE_TABLE_SIZE - 1) 338c2ecf20Sopenharmony_ci#endif /* __ASSEMBLY__ */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) 368c2ecf20Sopenharmony_ci#define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* 398c2ecf20Sopenharmony_ci * The normal case is that PTEs are 32-bits and we have a 1-page 408c2ecf20Sopenharmony_ci * 1024-entry pgdir pointing to 1-page 1024-entry PTE pages. -- paulus 418c2ecf20Sopenharmony_ci * 428c2ecf20Sopenharmony_ci * For any >32-bit physical address platform, we can use the following 438c2ecf20Sopenharmony_ci * two level page table layout where the pgdir is 8KB and the MS 13 bits 448c2ecf20Sopenharmony_ci * are an index to the second level table. The combined pgdir/pmd first 458c2ecf20Sopenharmony_ci * level has 2048 entries and the second level has 512 64-bit PTE entries. 468c2ecf20Sopenharmony_ci * -Matt 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_ci/* PGDIR_SHIFT determines what a top-level page table entry can map */ 498c2ecf20Sopenharmony_ci#define PGDIR_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE) 508c2ecf20Sopenharmony_ci#define PGDIR_SIZE (1UL << PGDIR_SHIFT) 518c2ecf20Sopenharmony_ci#define PGDIR_MASK (~(PGDIR_SIZE-1)) 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci/* Bits to mask out from a PGD to get to the PUD page */ 548c2ecf20Sopenharmony_ci#define PGD_MASKED_BITS 0 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) 578c2ecf20Sopenharmony_ci#define FIRST_USER_ADDRESS 0UL 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#define pte_ERROR(e) \ 608c2ecf20Sopenharmony_ci pr_err("%s:%d: bad pte %llx.\n", __FILE__, __LINE__, \ 618c2ecf20Sopenharmony_ci (unsigned long long)pte_val(e)) 628c2ecf20Sopenharmony_ci#define pgd_ERROR(e) \ 638c2ecf20Sopenharmony_ci pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ciint map_kernel_page(unsigned long va, phys_addr_t pa, pgprot_t prot); 688c2ecf20Sopenharmony_civoid unmap_kernel_page(unsigned long va); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci/* 748c2ecf20Sopenharmony_ci * This is the bottom of the PKMAP area with HIGHMEM or an arbitrary 758c2ecf20Sopenharmony_ci * value (for now) on others, from where we can start layout kernel 768c2ecf20Sopenharmony_ci * virtual space that goes below PKMAP and FIXMAP 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_ci#include <asm/fixmap.h> 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci/* 818c2ecf20Sopenharmony_ci * ioremap_bot starts at that address. Early ioremaps move down from there, 828c2ecf20Sopenharmony_ci * until mem_init() at which point this becomes the top of the vmalloc 838c2ecf20Sopenharmony_ci * and ioremap space 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_ci#ifdef CONFIG_HIGHMEM 868c2ecf20Sopenharmony_ci#define IOREMAP_TOP PKMAP_BASE 878c2ecf20Sopenharmony_ci#else 888c2ecf20Sopenharmony_ci#define IOREMAP_TOP FIXADDR_START 898c2ecf20Sopenharmony_ci#endif 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci/* PPC32 shares vmalloc area with ioremap */ 928c2ecf20Sopenharmony_ci#define IOREMAP_START VMALLOC_START 938c2ecf20Sopenharmony_ci#define IOREMAP_END VMALLOC_END 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* 968c2ecf20Sopenharmony_ci * Just any arbitrary offset to the start of the vmalloc VM area: the 978c2ecf20Sopenharmony_ci * current 16MB value just means that there will be a 64MB "hole" after the 988c2ecf20Sopenharmony_ci * physical memory until the kernel virtual memory starts. That means that 998c2ecf20Sopenharmony_ci * any out-of-bounds memory accesses will hopefully be caught. 1008c2ecf20Sopenharmony_ci * The vmalloc() routines leaves a hole of 4kB between each vmalloced 1018c2ecf20Sopenharmony_ci * area for the same reason. ;) 1028c2ecf20Sopenharmony_ci * 1038c2ecf20Sopenharmony_ci * We no longer map larger than phys RAM with the BATs so we don't have 1048c2ecf20Sopenharmony_ci * to worry about the VMALLOC_OFFSET causing problems. We do have to worry 1058c2ecf20Sopenharmony_ci * about clashes between our early calls to ioremap() that start growing down 1068c2ecf20Sopenharmony_ci * from IOREMAP_TOP being run into the VM area allocations (growing upwards 1078c2ecf20Sopenharmony_ci * from VMALLOC_START). For this reason we have ioremap_bot to check when 1088c2ecf20Sopenharmony_ci * we actually run into our mappings setup in the early boot with the VM 1098c2ecf20Sopenharmony_ci * system. This really does become a problem for machines with good amounts 1108c2ecf20Sopenharmony_ci * of RAM. -- Cort 1118c2ecf20Sopenharmony_ci */ 1128c2ecf20Sopenharmony_ci#define VMALLOC_OFFSET (0x1000000) /* 16M */ 1138c2ecf20Sopenharmony_ci#ifdef PPC_PIN_SIZE 1148c2ecf20Sopenharmony_ci#define VMALLOC_START (((ALIGN((long)high_memory, PPC_PIN_SIZE) + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))) 1158c2ecf20Sopenharmony_ci#else 1168c2ecf20Sopenharmony_ci#define VMALLOC_START ((((long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))) 1178c2ecf20Sopenharmony_ci#endif 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci#ifdef CONFIG_KASAN_VMALLOC 1208c2ecf20Sopenharmony_ci#define VMALLOC_END ALIGN_DOWN(ioremap_bot, PAGE_SIZE << KASAN_SHADOW_SCALE_SHIFT) 1218c2ecf20Sopenharmony_ci#else 1228c2ecf20Sopenharmony_ci#define VMALLOC_END ioremap_bot 1238c2ecf20Sopenharmony_ci#endif 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci/* 1268c2ecf20Sopenharmony_ci * Bits in a linux-style PTE. These match the bits in the 1278c2ecf20Sopenharmony_ci * (hardware-defined) PowerPC PTE as closely as possible. 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci#if defined(CONFIG_40x) 1318c2ecf20Sopenharmony_ci#include <asm/nohash/32/pte-40x.h> 1328c2ecf20Sopenharmony_ci#elif defined(CONFIG_44x) 1338c2ecf20Sopenharmony_ci#include <asm/nohash/32/pte-44x.h> 1348c2ecf20Sopenharmony_ci#elif defined(CONFIG_FSL_BOOKE) && defined(CONFIG_PTE_64BIT) 1358c2ecf20Sopenharmony_ci#include <asm/nohash/pte-book3e.h> 1368c2ecf20Sopenharmony_ci#elif defined(CONFIG_FSL_BOOKE) 1378c2ecf20Sopenharmony_ci#include <asm/nohash/32/pte-fsl-booke.h> 1388c2ecf20Sopenharmony_ci#elif defined(CONFIG_PPC_8xx) 1398c2ecf20Sopenharmony_ci#include <asm/nohash/32/pte-8xx.h> 1408c2ecf20Sopenharmony_ci#endif 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci/* 1438c2ecf20Sopenharmony_ci * Location of the PFN in the PTE. Most 32-bit platforms use the same 1448c2ecf20Sopenharmony_ci * as _PAGE_SHIFT here (ie, naturally aligned). 1458c2ecf20Sopenharmony_ci * Platform who don't just pre-define the value so we don't override it here. 1468c2ecf20Sopenharmony_ci */ 1478c2ecf20Sopenharmony_ci#ifndef PTE_RPN_SHIFT 1488c2ecf20Sopenharmony_ci#define PTE_RPN_SHIFT (PAGE_SHIFT) 1498c2ecf20Sopenharmony_ci#endif 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci/* 1528c2ecf20Sopenharmony_ci * The mask covered by the RPN must be a ULL on 32-bit platforms with 1538c2ecf20Sopenharmony_ci * 64-bit PTEs. 1548c2ecf20Sopenharmony_ci */ 1558c2ecf20Sopenharmony_ci#if defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) 1568c2ecf20Sopenharmony_ci#define PTE_RPN_MASK (~((1ULL << PTE_RPN_SHIFT) - 1)) 1578c2ecf20Sopenharmony_ci#define MAX_POSSIBLE_PHYSMEM_BITS 36 1588c2ecf20Sopenharmony_ci#else 1598c2ecf20Sopenharmony_ci#define PTE_RPN_MASK (~((1UL << PTE_RPN_SHIFT) - 1)) 1608c2ecf20Sopenharmony_ci#define MAX_POSSIBLE_PHYSMEM_BITS 32 1618c2ecf20Sopenharmony_ci#endif 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci/* 1648c2ecf20Sopenharmony_ci * _PAGE_CHG_MASK masks of bits that are to be preserved across 1658c2ecf20Sopenharmony_ci * pgprot changes. 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_ci#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SPECIAL) 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci#define pte_clear(mm, addr, ptep) \ 1728c2ecf20Sopenharmony_ci do { pte_update(mm, addr, ptep, ~0, 0, 0); } while (0) 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci#ifndef pte_mkwrite 1758c2ecf20Sopenharmony_cistatic inline pte_t pte_mkwrite(pte_t pte) 1768c2ecf20Sopenharmony_ci{ 1778c2ecf20Sopenharmony_ci return __pte(pte_val(pte) | _PAGE_RW); 1788c2ecf20Sopenharmony_ci} 1798c2ecf20Sopenharmony_ci#endif 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic inline pte_t pte_mkdirty(pte_t pte) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci return __pte(pte_val(pte) | _PAGE_DIRTY); 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic inline pte_t pte_mkyoung(pte_t pte) 1878c2ecf20Sopenharmony_ci{ 1888c2ecf20Sopenharmony_ci return __pte(pte_val(pte) | _PAGE_ACCESSED); 1898c2ecf20Sopenharmony_ci} 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci#ifndef pte_wrprotect 1928c2ecf20Sopenharmony_cistatic inline pte_t pte_wrprotect(pte_t pte) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci return __pte(pte_val(pte) & ~_PAGE_RW); 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci#endif 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic inline pte_t pte_mkexec(pte_t pte) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci return __pte(pte_val(pte) | _PAGE_EXEC); 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci#define pmd_none(pmd) (!pmd_val(pmd)) 2048c2ecf20Sopenharmony_ci#define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD) 2058c2ecf20Sopenharmony_ci#define pmd_present(pmd) (pmd_val(pmd) & _PMD_PRESENT_MASK) 2068c2ecf20Sopenharmony_cistatic inline void pmd_clear(pmd_t *pmdp) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci *pmdp = __pmd(0); 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci/* 2128c2ecf20Sopenharmony_ci * PTE updates. This function is called whenever an existing 2138c2ecf20Sopenharmony_ci * valid PTE is updated. This does -not- include set_pte_at() 2148c2ecf20Sopenharmony_ci * which nowadays only sets a new PTE. 2158c2ecf20Sopenharmony_ci * 2168c2ecf20Sopenharmony_ci * Depending on the type of MMU, we may need to use atomic updates 2178c2ecf20Sopenharmony_ci * and the PTE may be either 32 or 64 bit wide. In the later case, 2188c2ecf20Sopenharmony_ci * when using atomic updates, only the low part of the PTE is 2198c2ecf20Sopenharmony_ci * accessed atomically. 2208c2ecf20Sopenharmony_ci * 2218c2ecf20Sopenharmony_ci * In addition, on 44x, we also maintain a global flag indicating 2228c2ecf20Sopenharmony_ci * that an executable user mapping was modified, which is needed 2238c2ecf20Sopenharmony_ci * to properly flush the virtually tagged instruction cache of 2248c2ecf20Sopenharmony_ci * those implementations. 2258c2ecf20Sopenharmony_ci * 2268c2ecf20Sopenharmony_ci * On the 8xx, the page tables are a bit special. For 16k pages, we have 2278c2ecf20Sopenharmony_ci * 4 identical entries. For 512k pages, we have 128 entries as if it was 2288c2ecf20Sopenharmony_ci * 4k pages, but they are flagged as 512k pages for the hardware. 2298c2ecf20Sopenharmony_ci * For other page sizes, we have a single entry in the table. 2308c2ecf20Sopenharmony_ci */ 2318c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_8xx 2328c2ecf20Sopenharmony_cistatic pmd_t *pmd_off(struct mm_struct *mm, unsigned long addr); 2338c2ecf20Sopenharmony_cistatic int hugepd_ok(hugepd_t hpd); 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic int number_of_cells_per_pte(pmd_t *pmd, pte_basic_t val, int huge) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci if (!huge) 2388c2ecf20Sopenharmony_ci return PAGE_SIZE / SZ_4K; 2398c2ecf20Sopenharmony_ci else if (hugepd_ok(*((hugepd_t *)pmd))) 2408c2ecf20Sopenharmony_ci return 1; 2418c2ecf20Sopenharmony_ci else if (IS_ENABLED(CONFIG_PPC_4K_PAGES) && !(val & _PAGE_HUGE)) 2428c2ecf20Sopenharmony_ci return SZ_16K / SZ_4K; 2438c2ecf20Sopenharmony_ci else 2448c2ecf20Sopenharmony_ci return SZ_512K / SZ_4K; 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cistatic inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p, 2488c2ecf20Sopenharmony_ci unsigned long clr, unsigned long set, int huge) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci pte_basic_t *entry = &p->pte; 2518c2ecf20Sopenharmony_ci pte_basic_t old = pte_val(*p); 2528c2ecf20Sopenharmony_ci pte_basic_t new = (old & ~(pte_basic_t)clr) | set; 2538c2ecf20Sopenharmony_ci int num, i; 2548c2ecf20Sopenharmony_ci pmd_t *pmd = pmd_off(mm, addr); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci num = number_of_cells_per_pte(pmd, new, huge); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci for (i = 0; i < num; i++, entry++, new += SZ_4K) 2598c2ecf20Sopenharmony_ci *entry = new; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci return old; 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_16K_PAGES 2658c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_GET 2668c2ecf20Sopenharmony_cistatic inline pte_t ptep_get(pte_t *ptep) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci pte_basic_t val = READ_ONCE(ptep->pte); 2698c2ecf20Sopenharmony_ci pte_t pte = {val, val, val, val}; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci return pte; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci#endif /* CONFIG_PPC_16K_PAGES */ 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci#else 2768c2ecf20Sopenharmony_cistatic inline pte_basic_t pte_update(struct mm_struct *mm, unsigned long addr, pte_t *p, 2778c2ecf20Sopenharmony_ci unsigned long clr, unsigned long set, int huge) 2788c2ecf20Sopenharmony_ci{ 2798c2ecf20Sopenharmony_ci pte_basic_t old = pte_val(*p); 2808c2ecf20Sopenharmony_ci pte_basic_t new = (old & ~(pte_basic_t)clr) | set; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci *p = __pte(new); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci#ifdef CONFIG_44x 2858c2ecf20Sopenharmony_ci if ((old & _PAGE_USER) && (old & _PAGE_EXEC)) 2868c2ecf20Sopenharmony_ci icache_44x_need_flush = 1; 2878c2ecf20Sopenharmony_ci#endif 2888c2ecf20Sopenharmony_ci return old; 2898c2ecf20Sopenharmony_ci} 2908c2ecf20Sopenharmony_ci#endif 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG 2938c2ecf20Sopenharmony_cistatic inline int __ptep_test_and_clear_young(struct mm_struct *mm, 2948c2ecf20Sopenharmony_ci unsigned long addr, pte_t *ptep) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci unsigned long old; 2978c2ecf20Sopenharmony_ci old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0); 2988c2ecf20Sopenharmony_ci return (old & _PAGE_ACCESSED) != 0; 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci#define ptep_test_and_clear_young(__vma, __addr, __ptep) \ 3018c2ecf20Sopenharmony_ci __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep) 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_GET_AND_CLEAR 3048c2ecf20Sopenharmony_cistatic inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, 3058c2ecf20Sopenharmony_ci pte_t *ptep) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci return __pte(pte_update(mm, addr, ptep, ~0, 0, 0)); 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_SET_WRPROTECT 3118c2ecf20Sopenharmony_cistatic inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, 3128c2ecf20Sopenharmony_ci pte_t *ptep) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci unsigned long clr = ~pte_val(pte_wrprotect(__pte(~0))); 3158c2ecf20Sopenharmony_ci unsigned long set = pte_val(pte_wrprotect(__pte(0))); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci pte_update(mm, addr, ptep, clr, set, 0); 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic inline void __ptep_set_access_flags(struct vm_area_struct *vma, 3218c2ecf20Sopenharmony_ci pte_t *ptep, pte_t entry, 3228c2ecf20Sopenharmony_ci unsigned long address, 3238c2ecf20Sopenharmony_ci int psize) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci pte_t pte_set = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(0))))); 3268c2ecf20Sopenharmony_ci pte_t pte_clr = pte_mkyoung(pte_mkdirty(pte_mkwrite(pte_mkexec(__pte(~0))))); 3278c2ecf20Sopenharmony_ci unsigned long set = pte_val(entry) & pte_val(pte_set); 3288c2ecf20Sopenharmony_ci unsigned long clr = ~pte_val(entry) & ~pte_val(pte_clr); 3298c2ecf20Sopenharmony_ci int huge = psize > mmu_virtual_psize ? 1 : 0; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci pte_update(vma->vm_mm, address, ptep, clr, set, huge); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci flush_tlb_page(vma, address); 3348c2ecf20Sopenharmony_ci} 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic inline int pte_young(pte_t pte) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci return pte_val(pte) & _PAGE_ACCESSED; 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTE_SAME 3428c2ecf20Sopenharmony_ci#define pte_same(A,B) ((pte_val(A) ^ pte_val(B)) == 0) 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci/* 3458c2ecf20Sopenharmony_ci * Note that on Book E processors, the pmd contains the kernel virtual 3468c2ecf20Sopenharmony_ci * (lowmem) address of the pte page. The physical address is less useful 3478c2ecf20Sopenharmony_ci * because everything runs with translation enabled (even the TLB miss 3488c2ecf20Sopenharmony_ci * handler). On everything else the pmd contains the physical address 3498c2ecf20Sopenharmony_ci * of the pte page. -- paulus 3508c2ecf20Sopenharmony_ci */ 3518c2ecf20Sopenharmony_ci#ifndef CONFIG_BOOKE 3528c2ecf20Sopenharmony_ci#define pmd_page(pmd) \ 3538c2ecf20Sopenharmony_ci pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT) 3548c2ecf20Sopenharmony_ci#else 3558c2ecf20Sopenharmony_ci#define pmd_page_vaddr(pmd) \ 3568c2ecf20Sopenharmony_ci ((unsigned long)(pmd_val(pmd) & ~(PTE_TABLE_SIZE - 1))) 3578c2ecf20Sopenharmony_ci#define pmd_page(pmd) \ 3588c2ecf20Sopenharmony_ci pfn_to_page((__pa(pmd_val(pmd)) >> PAGE_SHIFT)) 3598c2ecf20Sopenharmony_ci#endif 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci/* 3628c2ecf20Sopenharmony_ci * Encode and decode a swap entry. 3638c2ecf20Sopenharmony_ci * Note that the bits we use in a PTE for representing a swap entry 3648c2ecf20Sopenharmony_ci * must not include the _PAGE_PRESENT bit. 3658c2ecf20Sopenharmony_ci * -- paulus 3668c2ecf20Sopenharmony_ci */ 3678c2ecf20Sopenharmony_ci#define __swp_type(entry) ((entry).val & 0x1f) 3688c2ecf20Sopenharmony_ci#define __swp_offset(entry) ((entry).val >> 5) 3698c2ecf20Sopenharmony_ci#define __swp_entry(type, offset) ((swp_entry_t) { (type) | ((offset) << 5) }) 3708c2ecf20Sopenharmony_ci#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 }) 3718c2ecf20Sopenharmony_ci#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 }) 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci#endif /* __ASM_POWERPC_NOHASH_32_PGTABLE_H */ 376