18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * S390 version 48c2ecf20Sopenharmony_ci * Copyright IBM Corp. 1999, 2000 58c2ecf20Sopenharmony_ci * Author(s): Hartmut Penner (hp@de.ibm.com) 68c2ecf20Sopenharmony_ci * Ulrich Weigand (weigand@de.ibm.com) 78c2ecf20Sopenharmony_ci * Martin Schwidefsky (schwidefsky@de.ibm.com) 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Derived from "include/asm-i386/pgtable.h" 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#ifndef _ASM_S390_PGTABLE_H 138c2ecf20Sopenharmony_ci#define _ASM_S390_PGTABLE_H 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/sched.h> 168c2ecf20Sopenharmony_ci#include <linux/mm_types.h> 178c2ecf20Sopenharmony_ci#include <linux/page-flags.h> 188c2ecf20Sopenharmony_ci#include <linux/radix-tree.h> 198c2ecf20Sopenharmony_ci#include <linux/atomic.h> 208c2ecf20Sopenharmony_ci#include <asm/bug.h> 218c2ecf20Sopenharmony_ci#include <asm/page.h> 228c2ecf20Sopenharmony_ci#include <asm/uv.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ciextern pgd_t swapper_pg_dir[]; 258c2ecf20Sopenharmony_ciextern void paging_init(void); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cienum { 288c2ecf20Sopenharmony_ci PG_DIRECT_MAP_4K = 0, 298c2ecf20Sopenharmony_ci PG_DIRECT_MAP_1M, 308c2ecf20Sopenharmony_ci PG_DIRECT_MAP_2G, 318c2ecf20Sopenharmony_ci PG_DIRECT_MAP_MAX 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ciextern atomic_long_t direct_pages_count[PG_DIRECT_MAP_MAX]; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic inline void update_page_count(int level, long count) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_PROC_FS)) 398c2ecf20Sopenharmony_ci atomic_long_add(count, &direct_pages_count[level]); 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistruct seq_file; 438c2ecf20Sopenharmony_civoid arch_report_meminfo(struct seq_file *m); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* 468c2ecf20Sopenharmony_ci * The S390 doesn't have any external MMU info: the kernel page 478c2ecf20Sopenharmony_ci * tables contain all the necessary information. 488c2ecf20Sopenharmony_ci */ 498c2ecf20Sopenharmony_ci#define update_mmu_cache(vma, address, ptep) do { } while (0) 508c2ecf20Sopenharmony_ci#define update_mmu_cache_pmd(vma, address, ptep) do { } while (0) 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* 538c2ecf20Sopenharmony_ci * ZERO_PAGE is a global shared page that is always zero; used 548c2ecf20Sopenharmony_ci * for zero-mapped memory areas etc.. 558c2ecf20Sopenharmony_ci */ 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ciextern unsigned long empty_zero_page; 588c2ecf20Sopenharmony_ciextern unsigned long zero_page_mask; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci#define ZERO_PAGE(vaddr) \ 618c2ecf20Sopenharmony_ci (virt_to_page((void *)(empty_zero_page + \ 628c2ecf20Sopenharmony_ci (((unsigned long)(vaddr)) &zero_page_mask)))) 638c2ecf20Sopenharmony_ci#define __HAVE_COLOR_ZERO_PAGE 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci/* TODO: s390 cannot support io_remap_pfn_range... */ 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci#define FIRST_USER_ADDRESS 0UL 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci#define pte_ERROR(e) \ 708c2ecf20Sopenharmony_ci printk("%s:%d: bad pte %p.\n", __FILE__, __LINE__, (void *) pte_val(e)) 718c2ecf20Sopenharmony_ci#define pmd_ERROR(e) \ 728c2ecf20Sopenharmony_ci printk("%s:%d: bad pmd %p.\n", __FILE__, __LINE__, (void *) pmd_val(e)) 738c2ecf20Sopenharmony_ci#define pud_ERROR(e) \ 748c2ecf20Sopenharmony_ci printk("%s:%d: bad pud %p.\n", __FILE__, __LINE__, (void *) pud_val(e)) 758c2ecf20Sopenharmony_ci#define p4d_ERROR(e) \ 768c2ecf20Sopenharmony_ci printk("%s:%d: bad p4d %p.\n", __FILE__, __LINE__, (void *) p4d_val(e)) 778c2ecf20Sopenharmony_ci#define pgd_ERROR(e) \ 788c2ecf20Sopenharmony_ci printk("%s:%d: bad pgd %p.\n", __FILE__, __LINE__, (void *) pgd_val(e)) 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci/* 818c2ecf20Sopenharmony_ci * The vmalloc and module area will always be on the topmost area of the 828c2ecf20Sopenharmony_ci * kernel mapping. We reserve 128GB (64bit) for vmalloc and modules. 838c2ecf20Sopenharmony_ci * On 64 bit kernels we have a 2GB area at the top of the vmalloc area where 848c2ecf20Sopenharmony_ci * modules will reside. That makes sure that inter module branches always 858c2ecf20Sopenharmony_ci * happen without trampolines and in addition the placement within a 2GB frame 868c2ecf20Sopenharmony_ci * is branch prediction unit friendly. 878c2ecf20Sopenharmony_ci */ 888c2ecf20Sopenharmony_ciextern unsigned long VMALLOC_START; 898c2ecf20Sopenharmony_ciextern unsigned long VMALLOC_END; 908c2ecf20Sopenharmony_ci#define VMALLOC_DEFAULT_SIZE ((128UL << 30) - MODULES_LEN) 918c2ecf20Sopenharmony_ciextern struct page *vmemmap; 928c2ecf20Sopenharmony_ciextern unsigned long vmemmap_size; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci#define VMEM_MAX_PHYS ((unsigned long) vmemmap) 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ciextern unsigned long MODULES_VADDR; 978c2ecf20Sopenharmony_ciextern unsigned long MODULES_END; 988c2ecf20Sopenharmony_ci#define MODULES_VADDR MODULES_VADDR 998c2ecf20Sopenharmony_ci#define MODULES_END MODULES_END 1008c2ecf20Sopenharmony_ci#define MODULES_LEN (1UL << 31) 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic inline int is_module_addr(void *addr) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci BUILD_BUG_ON(MODULES_LEN > (1UL << 31)); 1058c2ecf20Sopenharmony_ci if (addr < (void *)MODULES_VADDR) 1068c2ecf20Sopenharmony_ci return 0; 1078c2ecf20Sopenharmony_ci if (addr > (void *)MODULES_END) 1088c2ecf20Sopenharmony_ci return 0; 1098c2ecf20Sopenharmony_ci return 1; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/* 1138c2ecf20Sopenharmony_ci * A 64 bit pagetable entry of S390 has following format: 1148c2ecf20Sopenharmony_ci * | PFRA |0IPC| OS | 1158c2ecf20Sopenharmony_ci * 0000000000111111111122222222223333333333444444444455555555556666 1168c2ecf20Sopenharmony_ci * 0123456789012345678901234567890123456789012345678901234567890123 1178c2ecf20Sopenharmony_ci * 1188c2ecf20Sopenharmony_ci * I Page-Invalid Bit: Page is not available for address-translation 1198c2ecf20Sopenharmony_ci * P Page-Protection Bit: Store access not possible for page 1208c2ecf20Sopenharmony_ci * C Change-bit override: HW is not required to set change bit 1218c2ecf20Sopenharmony_ci * 1228c2ecf20Sopenharmony_ci * A 64 bit segmenttable entry of S390 has following format: 1238c2ecf20Sopenharmony_ci * | P-table origin | TT 1248c2ecf20Sopenharmony_ci * 0000000000111111111122222222223333333333444444444455555555556666 1258c2ecf20Sopenharmony_ci * 0123456789012345678901234567890123456789012345678901234567890123 1268c2ecf20Sopenharmony_ci * 1278c2ecf20Sopenharmony_ci * I Segment-Invalid Bit: Segment is not available for address-translation 1288c2ecf20Sopenharmony_ci * C Common-Segment Bit: Segment is not private (PoP 3-30) 1298c2ecf20Sopenharmony_ci * P Page-Protection Bit: Store access not possible for page 1308c2ecf20Sopenharmony_ci * TT Type 00 1318c2ecf20Sopenharmony_ci * 1328c2ecf20Sopenharmony_ci * A 64 bit region table entry of S390 has following format: 1338c2ecf20Sopenharmony_ci * | S-table origin | TF TTTL 1348c2ecf20Sopenharmony_ci * 0000000000111111111122222222223333333333444444444455555555556666 1358c2ecf20Sopenharmony_ci * 0123456789012345678901234567890123456789012345678901234567890123 1368c2ecf20Sopenharmony_ci * 1378c2ecf20Sopenharmony_ci * I Segment-Invalid Bit: Segment is not available for address-translation 1388c2ecf20Sopenharmony_ci * TT Type 01 1398c2ecf20Sopenharmony_ci * TF 1408c2ecf20Sopenharmony_ci * TL Table length 1418c2ecf20Sopenharmony_ci * 1428c2ecf20Sopenharmony_ci * The 64 bit regiontable origin of S390 has following format: 1438c2ecf20Sopenharmony_ci * | region table origon | DTTL 1448c2ecf20Sopenharmony_ci * 0000000000111111111122222222223333333333444444444455555555556666 1458c2ecf20Sopenharmony_ci * 0123456789012345678901234567890123456789012345678901234567890123 1468c2ecf20Sopenharmony_ci * 1478c2ecf20Sopenharmony_ci * X Space-Switch event: 1488c2ecf20Sopenharmony_ci * G Segment-Invalid Bit: 1498c2ecf20Sopenharmony_ci * P Private-Space Bit: 1508c2ecf20Sopenharmony_ci * S Storage-Alteration: 1518c2ecf20Sopenharmony_ci * R Real space 1528c2ecf20Sopenharmony_ci * TL Table-Length: 1538c2ecf20Sopenharmony_ci * 1548c2ecf20Sopenharmony_ci * A storage key has the following format: 1558c2ecf20Sopenharmony_ci * | ACC |F|R|C|0| 1568c2ecf20Sopenharmony_ci * 0 3 4 5 6 7 1578c2ecf20Sopenharmony_ci * ACC: access key 1588c2ecf20Sopenharmony_ci * F : fetch protection bit 1598c2ecf20Sopenharmony_ci * R : referenced bit 1608c2ecf20Sopenharmony_ci * C : changed bit 1618c2ecf20Sopenharmony_ci */ 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci/* Hardware bits in the page table entry */ 1648c2ecf20Sopenharmony_ci#define _PAGE_NOEXEC 0x100 /* HW no-execute bit */ 1658c2ecf20Sopenharmony_ci#define _PAGE_PROTECT 0x200 /* HW read-only bit */ 1668c2ecf20Sopenharmony_ci#define _PAGE_INVALID 0x400 /* HW invalid bit */ 1678c2ecf20Sopenharmony_ci#define _PAGE_LARGE 0x800 /* Bit to mark a large pte */ 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci/* Software bits in the page table entry */ 1708c2ecf20Sopenharmony_ci#define _PAGE_PRESENT 0x001 /* SW pte present bit */ 1718c2ecf20Sopenharmony_ci#define _PAGE_YOUNG 0x004 /* SW pte young bit */ 1728c2ecf20Sopenharmony_ci#define _PAGE_DIRTY 0x008 /* SW pte dirty bit */ 1738c2ecf20Sopenharmony_ci#define _PAGE_READ 0x010 /* SW pte read bit */ 1748c2ecf20Sopenharmony_ci#define _PAGE_WRITE 0x020 /* SW pte write bit */ 1758c2ecf20Sopenharmony_ci#define _PAGE_SPECIAL 0x040 /* SW associated with special page */ 1768c2ecf20Sopenharmony_ci#define _PAGE_UNUSED 0x080 /* SW bit for pgste usage state */ 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci#ifdef CONFIG_MEM_SOFT_DIRTY 1798c2ecf20Sopenharmony_ci#define _PAGE_SOFT_DIRTY 0x002 /* SW pte soft dirty bit */ 1808c2ecf20Sopenharmony_ci#else 1818c2ecf20Sopenharmony_ci#define _PAGE_SOFT_DIRTY 0x000 1828c2ecf20Sopenharmony_ci#endif 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci/* Set of bits not changed in pte_modify */ 1858c2ecf20Sopenharmony_ci#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_SPECIAL | _PAGE_DIRTY | \ 1868c2ecf20Sopenharmony_ci _PAGE_YOUNG | _PAGE_SOFT_DIRTY) 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci/* 1898c2ecf20Sopenharmony_ci * handle_pte_fault uses pte_present and pte_none to find out the pte type 1908c2ecf20Sopenharmony_ci * WITHOUT holding the page table lock. The _PAGE_PRESENT bit is used to 1918c2ecf20Sopenharmony_ci * distinguish present from not-present ptes. It is changed only with the page 1928c2ecf20Sopenharmony_ci * table lock held. 1938c2ecf20Sopenharmony_ci * 1948c2ecf20Sopenharmony_ci * The following table gives the different possible bit combinations for 1958c2ecf20Sopenharmony_ci * the pte hardware and software bits in the last 12 bits of a pte 1968c2ecf20Sopenharmony_ci * (. unassigned bit, x don't care, t swap type): 1978c2ecf20Sopenharmony_ci * 1988c2ecf20Sopenharmony_ci * 842100000000 1998c2ecf20Sopenharmony_ci * 000084210000 2008c2ecf20Sopenharmony_ci * 000000008421 2018c2ecf20Sopenharmony_ci * .IR.uswrdy.p 2028c2ecf20Sopenharmony_ci * empty .10.00000000 2038c2ecf20Sopenharmony_ci * swap .11..ttttt.0 2048c2ecf20Sopenharmony_ci * prot-none, clean, old .11.xx0000.1 2058c2ecf20Sopenharmony_ci * prot-none, clean, young .11.xx0001.1 2068c2ecf20Sopenharmony_ci * prot-none, dirty, old .11.xx0010.1 2078c2ecf20Sopenharmony_ci * prot-none, dirty, young .11.xx0011.1 2088c2ecf20Sopenharmony_ci * read-only, clean, old .11.xx0100.1 2098c2ecf20Sopenharmony_ci * read-only, clean, young .01.xx0101.1 2108c2ecf20Sopenharmony_ci * read-only, dirty, old .11.xx0110.1 2118c2ecf20Sopenharmony_ci * read-only, dirty, young .01.xx0111.1 2128c2ecf20Sopenharmony_ci * read-write, clean, old .11.xx1100.1 2138c2ecf20Sopenharmony_ci * read-write, clean, young .01.xx1101.1 2148c2ecf20Sopenharmony_ci * read-write, dirty, old .10.xx1110.1 2158c2ecf20Sopenharmony_ci * read-write, dirty, young .00.xx1111.1 2168c2ecf20Sopenharmony_ci * HW-bits: R read-only, I invalid 2178c2ecf20Sopenharmony_ci * SW-bits: p present, y young, d dirty, r read, w write, s special, 2188c2ecf20Sopenharmony_ci * u unused, l large 2198c2ecf20Sopenharmony_ci * 2208c2ecf20Sopenharmony_ci * pte_none is true for the bit pattern .10.00000000, pte == 0x400 2218c2ecf20Sopenharmony_ci * pte_swap is true for the bit pattern .11..ooooo.0, (pte & 0x201) == 0x200 2228c2ecf20Sopenharmony_ci * pte_present is true for the bit pattern .xx.xxxxxx.1, (pte & 0x001) == 0x001 2238c2ecf20Sopenharmony_ci */ 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci/* Bits in the segment/region table address-space-control-element */ 2268c2ecf20Sopenharmony_ci#define _ASCE_ORIGIN ~0xfffUL/* region/segment table origin */ 2278c2ecf20Sopenharmony_ci#define _ASCE_PRIVATE_SPACE 0x100 /* private space control */ 2288c2ecf20Sopenharmony_ci#define _ASCE_ALT_EVENT 0x80 /* storage alteration event control */ 2298c2ecf20Sopenharmony_ci#define _ASCE_SPACE_SWITCH 0x40 /* space switch event */ 2308c2ecf20Sopenharmony_ci#define _ASCE_REAL_SPACE 0x20 /* real space control */ 2318c2ecf20Sopenharmony_ci#define _ASCE_TYPE_MASK 0x0c /* asce table type mask */ 2328c2ecf20Sopenharmony_ci#define _ASCE_TYPE_REGION1 0x0c /* region first table type */ 2338c2ecf20Sopenharmony_ci#define _ASCE_TYPE_REGION2 0x08 /* region second table type */ 2348c2ecf20Sopenharmony_ci#define _ASCE_TYPE_REGION3 0x04 /* region third table type */ 2358c2ecf20Sopenharmony_ci#define _ASCE_TYPE_SEGMENT 0x00 /* segment table type */ 2368c2ecf20Sopenharmony_ci#define _ASCE_TABLE_LENGTH 0x03 /* region table length */ 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci/* Bits in the region table entry */ 2398c2ecf20Sopenharmony_ci#define _REGION_ENTRY_ORIGIN ~0xfffUL/* region/segment table origin */ 2408c2ecf20Sopenharmony_ci#define _REGION_ENTRY_PROTECT 0x200 /* region protection bit */ 2418c2ecf20Sopenharmony_ci#define _REGION_ENTRY_NOEXEC 0x100 /* region no-execute bit */ 2428c2ecf20Sopenharmony_ci#define _REGION_ENTRY_OFFSET 0xc0 /* region table offset */ 2438c2ecf20Sopenharmony_ci#define _REGION_ENTRY_INVALID 0x20 /* invalid region table entry */ 2448c2ecf20Sopenharmony_ci#define _REGION_ENTRY_TYPE_MASK 0x0c /* region table type mask */ 2458c2ecf20Sopenharmony_ci#define _REGION_ENTRY_TYPE_R1 0x0c /* region first table type */ 2468c2ecf20Sopenharmony_ci#define _REGION_ENTRY_TYPE_R2 0x08 /* region second table type */ 2478c2ecf20Sopenharmony_ci#define _REGION_ENTRY_TYPE_R3 0x04 /* region third table type */ 2488c2ecf20Sopenharmony_ci#define _REGION_ENTRY_LENGTH 0x03 /* region third length */ 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci#define _REGION1_ENTRY (_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_LENGTH) 2518c2ecf20Sopenharmony_ci#define _REGION1_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INVALID) 2528c2ecf20Sopenharmony_ci#define _REGION2_ENTRY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_LENGTH) 2538c2ecf20Sopenharmony_ci#define _REGION2_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INVALID) 2548c2ecf20Sopenharmony_ci#define _REGION3_ENTRY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH) 2558c2ecf20Sopenharmony_ci#define _REGION3_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INVALID) 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci#define _REGION3_ENTRY_ORIGIN_LARGE ~0x7fffffffUL /* large page address */ 2588c2ecf20Sopenharmony_ci#define _REGION3_ENTRY_DIRTY 0x2000 /* SW region dirty bit */ 2598c2ecf20Sopenharmony_ci#define _REGION3_ENTRY_YOUNG 0x1000 /* SW region young bit */ 2608c2ecf20Sopenharmony_ci#define _REGION3_ENTRY_LARGE 0x0400 /* RTTE-format control, large page */ 2618c2ecf20Sopenharmony_ci#define _REGION3_ENTRY_READ 0x0002 /* SW region read bit */ 2628c2ecf20Sopenharmony_ci#define _REGION3_ENTRY_WRITE 0x0001 /* SW region write bit */ 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci#ifdef CONFIG_MEM_SOFT_DIRTY 2658c2ecf20Sopenharmony_ci#define _REGION3_ENTRY_SOFT_DIRTY 0x4000 /* SW region soft dirty bit */ 2668c2ecf20Sopenharmony_ci#else 2678c2ecf20Sopenharmony_ci#define _REGION3_ENTRY_SOFT_DIRTY 0x0000 /* SW region soft dirty bit */ 2688c2ecf20Sopenharmony_ci#endif 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci#define _REGION_ENTRY_BITS 0xfffffffffffff22fUL 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci/* Bits in the segment table entry */ 2738c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_BITS 0xfffffffffffffe33UL 2748c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_HARDWARE_BITS 0xfffffffffffffe30UL 2758c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_HARDWARE_BITS_LARGE 0xfffffffffff00730UL 2768c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address */ 2778c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_ORIGIN ~0x7ffUL/* page table origin */ 2788c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_PROTECT 0x200 /* segment protection bit */ 2798c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_NOEXEC 0x100 /* segment no-execute bit */ 2808c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_INVALID 0x20 /* invalid segment table entry */ 2818c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_TYPE_MASK 0x0c /* segment table type mask */ 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY (0) 2848c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INVALID) 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_DIRTY 0x2000 /* SW segment dirty bit */ 2878c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_YOUNG 0x1000 /* SW segment young bit */ 2888c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_LARGE 0x0400 /* STE-format control, large page */ 2898c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_WRITE 0x0002 /* SW segment write bit */ 2908c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_READ 0x0001 /* SW segment read bit */ 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci#ifdef CONFIG_MEM_SOFT_DIRTY 2938c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_SOFT_DIRTY 0x4000 /* SW segment soft dirty bit */ 2948c2ecf20Sopenharmony_ci#else 2958c2ecf20Sopenharmony_ci#define _SEGMENT_ENTRY_SOFT_DIRTY 0x0000 /* SW segment soft dirty bit */ 2968c2ecf20Sopenharmony_ci#endif 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci#define _CRST_ENTRIES 2048 /* number of region/segment table entries */ 2998c2ecf20Sopenharmony_ci#define _PAGE_ENTRIES 256 /* number of page table entries */ 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci#define _CRST_TABLE_SIZE (_CRST_ENTRIES * 8) 3028c2ecf20Sopenharmony_ci#define _PAGE_TABLE_SIZE (_PAGE_ENTRIES * 8) 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci#define _REGION1_SHIFT 53 3058c2ecf20Sopenharmony_ci#define _REGION2_SHIFT 42 3068c2ecf20Sopenharmony_ci#define _REGION3_SHIFT 31 3078c2ecf20Sopenharmony_ci#define _SEGMENT_SHIFT 20 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci#define _REGION1_INDEX (0x7ffUL << _REGION1_SHIFT) 3108c2ecf20Sopenharmony_ci#define _REGION2_INDEX (0x7ffUL << _REGION2_SHIFT) 3118c2ecf20Sopenharmony_ci#define _REGION3_INDEX (0x7ffUL << _REGION3_SHIFT) 3128c2ecf20Sopenharmony_ci#define _SEGMENT_INDEX (0x7ffUL << _SEGMENT_SHIFT) 3138c2ecf20Sopenharmony_ci#define _PAGE_INDEX (0xffUL << _PAGE_SHIFT) 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci#define _REGION1_SIZE (1UL << _REGION1_SHIFT) 3168c2ecf20Sopenharmony_ci#define _REGION2_SIZE (1UL << _REGION2_SHIFT) 3178c2ecf20Sopenharmony_ci#define _REGION3_SIZE (1UL << _REGION3_SHIFT) 3188c2ecf20Sopenharmony_ci#define _SEGMENT_SIZE (1UL << _SEGMENT_SHIFT) 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci#define _REGION1_MASK (~(_REGION1_SIZE - 1)) 3218c2ecf20Sopenharmony_ci#define _REGION2_MASK (~(_REGION2_SIZE - 1)) 3228c2ecf20Sopenharmony_ci#define _REGION3_MASK (~(_REGION3_SIZE - 1)) 3238c2ecf20Sopenharmony_ci#define _SEGMENT_MASK (~(_SEGMENT_SIZE - 1)) 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci#define PMD_SHIFT _SEGMENT_SHIFT 3268c2ecf20Sopenharmony_ci#define PUD_SHIFT _REGION3_SHIFT 3278c2ecf20Sopenharmony_ci#define P4D_SHIFT _REGION2_SHIFT 3288c2ecf20Sopenharmony_ci#define PGDIR_SHIFT _REGION1_SHIFT 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci#define PMD_SIZE _SEGMENT_SIZE 3318c2ecf20Sopenharmony_ci#define PUD_SIZE _REGION3_SIZE 3328c2ecf20Sopenharmony_ci#define P4D_SIZE _REGION2_SIZE 3338c2ecf20Sopenharmony_ci#define PGDIR_SIZE _REGION1_SIZE 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci#define PMD_MASK _SEGMENT_MASK 3368c2ecf20Sopenharmony_ci#define PUD_MASK _REGION3_MASK 3378c2ecf20Sopenharmony_ci#define P4D_MASK _REGION2_MASK 3388c2ecf20Sopenharmony_ci#define PGDIR_MASK _REGION1_MASK 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci#define PTRS_PER_PTE _PAGE_ENTRIES 3418c2ecf20Sopenharmony_ci#define PTRS_PER_PMD _CRST_ENTRIES 3428c2ecf20Sopenharmony_ci#define PTRS_PER_PUD _CRST_ENTRIES 3438c2ecf20Sopenharmony_ci#define PTRS_PER_P4D _CRST_ENTRIES 3448c2ecf20Sopenharmony_ci#define PTRS_PER_PGD _CRST_ENTRIES 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci#define MAX_PTRS_PER_P4D PTRS_PER_P4D 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci/* 3498c2ecf20Sopenharmony_ci * Segment table and region3 table entry encoding 3508c2ecf20Sopenharmony_ci * (R = read-only, I = invalid, y = young bit): 3518c2ecf20Sopenharmony_ci * dy..R...I...wr 3528c2ecf20Sopenharmony_ci * prot-none, clean, old 00..1...1...00 3538c2ecf20Sopenharmony_ci * prot-none, clean, young 01..1...1...00 3548c2ecf20Sopenharmony_ci * prot-none, dirty, old 10..1...1...00 3558c2ecf20Sopenharmony_ci * prot-none, dirty, young 11..1...1...00 3568c2ecf20Sopenharmony_ci * read-only, clean, old 00..1...1...01 3578c2ecf20Sopenharmony_ci * read-only, clean, young 01..1...0...01 3588c2ecf20Sopenharmony_ci * read-only, dirty, old 10..1...1...01 3598c2ecf20Sopenharmony_ci * read-only, dirty, young 11..1...0...01 3608c2ecf20Sopenharmony_ci * read-write, clean, old 00..1...1...11 3618c2ecf20Sopenharmony_ci * read-write, clean, young 01..1...0...11 3628c2ecf20Sopenharmony_ci * read-write, dirty, old 10..0...1...11 3638c2ecf20Sopenharmony_ci * read-write, dirty, young 11..0...0...11 3648c2ecf20Sopenharmony_ci * The segment table origin is used to distinguish empty (origin==0) from 3658c2ecf20Sopenharmony_ci * read-write, old segment table entries (origin!=0) 3668c2ecf20Sopenharmony_ci * HW-bits: R read-only, I invalid 3678c2ecf20Sopenharmony_ci * SW-bits: y young, d dirty, r read, w write 3688c2ecf20Sopenharmony_ci */ 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci/* Page status table bits for virtualization */ 3718c2ecf20Sopenharmony_ci#define PGSTE_ACC_BITS 0xf000000000000000UL 3728c2ecf20Sopenharmony_ci#define PGSTE_FP_BIT 0x0800000000000000UL 3738c2ecf20Sopenharmony_ci#define PGSTE_PCL_BIT 0x0080000000000000UL 3748c2ecf20Sopenharmony_ci#define PGSTE_HR_BIT 0x0040000000000000UL 3758c2ecf20Sopenharmony_ci#define PGSTE_HC_BIT 0x0020000000000000UL 3768c2ecf20Sopenharmony_ci#define PGSTE_GR_BIT 0x0004000000000000UL 3778c2ecf20Sopenharmony_ci#define PGSTE_GC_BIT 0x0002000000000000UL 3788c2ecf20Sopenharmony_ci#define PGSTE_UC_BIT 0x0000800000000000UL /* user dirty (migration) */ 3798c2ecf20Sopenharmony_ci#define PGSTE_IN_BIT 0x0000400000000000UL /* IPTE notify bit */ 3808c2ecf20Sopenharmony_ci#define PGSTE_VSIE_BIT 0x0000200000000000UL /* ref'd in a shadow table */ 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci/* Guest Page State used for virtualization */ 3838c2ecf20Sopenharmony_ci#define _PGSTE_GPS_ZERO 0x0000000080000000UL 3848c2ecf20Sopenharmony_ci#define _PGSTE_GPS_NODAT 0x0000000040000000UL 3858c2ecf20Sopenharmony_ci#define _PGSTE_GPS_USAGE_MASK 0x0000000003000000UL 3868c2ecf20Sopenharmony_ci#define _PGSTE_GPS_USAGE_STABLE 0x0000000000000000UL 3878c2ecf20Sopenharmony_ci#define _PGSTE_GPS_USAGE_UNUSED 0x0000000001000000UL 3888c2ecf20Sopenharmony_ci#define _PGSTE_GPS_USAGE_POT_VOLATILE 0x0000000002000000UL 3898c2ecf20Sopenharmony_ci#define _PGSTE_GPS_USAGE_VOLATILE _PGSTE_GPS_USAGE_MASK 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci/* 3928c2ecf20Sopenharmony_ci * A user page table pointer has the space-switch-event bit, the 3938c2ecf20Sopenharmony_ci * private-space-control bit and the storage-alteration-event-control 3948c2ecf20Sopenharmony_ci * bit set. A kernel page table pointer doesn't need them. 3958c2ecf20Sopenharmony_ci */ 3968c2ecf20Sopenharmony_ci#define _ASCE_USER_BITS (_ASCE_SPACE_SWITCH | _ASCE_PRIVATE_SPACE | \ 3978c2ecf20Sopenharmony_ci _ASCE_ALT_EVENT) 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci/* 4008c2ecf20Sopenharmony_ci * Page protection definitions. 4018c2ecf20Sopenharmony_ci */ 4028c2ecf20Sopenharmony_ci#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_INVALID | _PAGE_PROTECT) 4038c2ecf20Sopenharmony_ci#define PAGE_RO __pgprot(_PAGE_PRESENT | _PAGE_READ | \ 4048c2ecf20Sopenharmony_ci _PAGE_NOEXEC | _PAGE_INVALID | _PAGE_PROTECT) 4058c2ecf20Sopenharmony_ci#define PAGE_RX __pgprot(_PAGE_PRESENT | _PAGE_READ | \ 4068c2ecf20Sopenharmony_ci _PAGE_INVALID | _PAGE_PROTECT) 4078c2ecf20Sopenharmony_ci#define PAGE_RW __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ 4088c2ecf20Sopenharmony_ci _PAGE_NOEXEC | _PAGE_INVALID | _PAGE_PROTECT) 4098c2ecf20Sopenharmony_ci#define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ 4108c2ecf20Sopenharmony_ci _PAGE_INVALID | _PAGE_PROTECT) 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ 4138c2ecf20Sopenharmony_ci _PAGE_YOUNG | _PAGE_DIRTY | _PAGE_NOEXEC) 4148c2ecf20Sopenharmony_ci#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ 4158c2ecf20Sopenharmony_ci _PAGE_YOUNG | _PAGE_DIRTY | _PAGE_NOEXEC) 4168c2ecf20Sopenharmony_ci#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_YOUNG | \ 4178c2ecf20Sopenharmony_ci _PAGE_PROTECT | _PAGE_NOEXEC) 4188c2ecf20Sopenharmony_ci#define PAGE_KERNEL_EXEC __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ 4198c2ecf20Sopenharmony_ci _PAGE_YOUNG | _PAGE_DIRTY) 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci/* 4228c2ecf20Sopenharmony_ci * On s390 the page table entry has an invalid bit and a read-only bit. 4238c2ecf20Sopenharmony_ci * Read permission implies execute permission and write permission 4248c2ecf20Sopenharmony_ci * implies read permission. 4258c2ecf20Sopenharmony_ci */ 4268c2ecf20Sopenharmony_ci /*xwr*/ 4278c2ecf20Sopenharmony_ci#define __P000 PAGE_NONE 4288c2ecf20Sopenharmony_ci#define __P001 PAGE_RO 4298c2ecf20Sopenharmony_ci#define __P010 PAGE_RO 4308c2ecf20Sopenharmony_ci#define __P011 PAGE_RO 4318c2ecf20Sopenharmony_ci#define __P100 PAGE_RX 4328c2ecf20Sopenharmony_ci#define __P101 PAGE_RX 4338c2ecf20Sopenharmony_ci#define __P110 PAGE_RX 4348c2ecf20Sopenharmony_ci#define __P111 PAGE_RX 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci#define __S000 PAGE_NONE 4378c2ecf20Sopenharmony_ci#define __S001 PAGE_RO 4388c2ecf20Sopenharmony_ci#define __S010 PAGE_RW 4398c2ecf20Sopenharmony_ci#define __S011 PAGE_RW 4408c2ecf20Sopenharmony_ci#define __S100 PAGE_RX 4418c2ecf20Sopenharmony_ci#define __S101 PAGE_RX 4428c2ecf20Sopenharmony_ci#define __S110 PAGE_RWX 4438c2ecf20Sopenharmony_ci#define __S111 PAGE_RWX 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci/* 4468c2ecf20Sopenharmony_ci * Segment entry (large page) protection definitions. 4478c2ecf20Sopenharmony_ci */ 4488c2ecf20Sopenharmony_ci#define SEGMENT_NONE __pgprot(_SEGMENT_ENTRY_INVALID | \ 4498c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_PROTECT) 4508c2ecf20Sopenharmony_ci#define SEGMENT_RO __pgprot(_SEGMENT_ENTRY_PROTECT | \ 4518c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_READ | \ 4528c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_NOEXEC) 4538c2ecf20Sopenharmony_ci#define SEGMENT_RX __pgprot(_SEGMENT_ENTRY_PROTECT | \ 4548c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_READ) 4558c2ecf20Sopenharmony_ci#define SEGMENT_RW __pgprot(_SEGMENT_ENTRY_READ | \ 4568c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_WRITE | \ 4578c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_NOEXEC) 4588c2ecf20Sopenharmony_ci#define SEGMENT_RWX __pgprot(_SEGMENT_ENTRY_READ | \ 4598c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_WRITE) 4608c2ecf20Sopenharmony_ci#define SEGMENT_KERNEL __pgprot(_SEGMENT_ENTRY | \ 4618c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_LARGE | \ 4628c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_READ | \ 4638c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_WRITE | \ 4648c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_YOUNG | \ 4658c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_DIRTY | \ 4668c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_NOEXEC) 4678c2ecf20Sopenharmony_ci#define SEGMENT_KERNEL_RO __pgprot(_SEGMENT_ENTRY | \ 4688c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_LARGE | \ 4698c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_READ | \ 4708c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_YOUNG | \ 4718c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_PROTECT | \ 4728c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_NOEXEC) 4738c2ecf20Sopenharmony_ci#define SEGMENT_KERNEL_EXEC __pgprot(_SEGMENT_ENTRY | \ 4748c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_LARGE | \ 4758c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_READ | \ 4768c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_WRITE | \ 4778c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_YOUNG | \ 4788c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_DIRTY) 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci/* 4818c2ecf20Sopenharmony_ci * Region3 entry (large page) protection definitions. 4828c2ecf20Sopenharmony_ci */ 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci#define REGION3_KERNEL __pgprot(_REGION_ENTRY_TYPE_R3 | \ 4858c2ecf20Sopenharmony_ci _REGION3_ENTRY_LARGE | \ 4868c2ecf20Sopenharmony_ci _REGION3_ENTRY_READ | \ 4878c2ecf20Sopenharmony_ci _REGION3_ENTRY_WRITE | \ 4888c2ecf20Sopenharmony_ci _REGION3_ENTRY_YOUNG | \ 4898c2ecf20Sopenharmony_ci _REGION3_ENTRY_DIRTY | \ 4908c2ecf20Sopenharmony_ci _REGION_ENTRY_NOEXEC) 4918c2ecf20Sopenharmony_ci#define REGION3_KERNEL_RO __pgprot(_REGION_ENTRY_TYPE_R3 | \ 4928c2ecf20Sopenharmony_ci _REGION3_ENTRY_LARGE | \ 4938c2ecf20Sopenharmony_ci _REGION3_ENTRY_READ | \ 4948c2ecf20Sopenharmony_ci _REGION3_ENTRY_YOUNG | \ 4958c2ecf20Sopenharmony_ci _REGION_ENTRY_PROTECT | \ 4968c2ecf20Sopenharmony_ci _REGION_ENTRY_NOEXEC) 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_cistatic inline bool mm_p4d_folded(struct mm_struct *mm) 4998c2ecf20Sopenharmony_ci{ 5008c2ecf20Sopenharmony_ci return mm->context.asce_limit <= _REGION1_SIZE; 5018c2ecf20Sopenharmony_ci} 5028c2ecf20Sopenharmony_ci#define mm_p4d_folded(mm) mm_p4d_folded(mm) 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_cistatic inline bool mm_pud_folded(struct mm_struct *mm) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci return mm->context.asce_limit <= _REGION2_SIZE; 5078c2ecf20Sopenharmony_ci} 5088c2ecf20Sopenharmony_ci#define mm_pud_folded(mm) mm_pud_folded(mm) 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_cistatic inline bool mm_pmd_folded(struct mm_struct *mm) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci return mm->context.asce_limit <= _REGION3_SIZE; 5138c2ecf20Sopenharmony_ci} 5148c2ecf20Sopenharmony_ci#define mm_pmd_folded(mm) mm_pmd_folded(mm) 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_cistatic inline int mm_has_pgste(struct mm_struct *mm) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci#ifdef CONFIG_PGSTE 5198c2ecf20Sopenharmony_ci if (unlikely(mm->context.has_pgste)) 5208c2ecf20Sopenharmony_ci return 1; 5218c2ecf20Sopenharmony_ci#endif 5228c2ecf20Sopenharmony_ci return 0; 5238c2ecf20Sopenharmony_ci} 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_cistatic inline int mm_is_protected(struct mm_struct *mm) 5268c2ecf20Sopenharmony_ci{ 5278c2ecf20Sopenharmony_ci#ifdef CONFIG_PGSTE 5288c2ecf20Sopenharmony_ci if (unlikely(atomic_read(&mm->context.is_protected))) 5298c2ecf20Sopenharmony_ci return 1; 5308c2ecf20Sopenharmony_ci#endif 5318c2ecf20Sopenharmony_ci return 0; 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_cistatic inline int mm_alloc_pgste(struct mm_struct *mm) 5358c2ecf20Sopenharmony_ci{ 5368c2ecf20Sopenharmony_ci#ifdef CONFIG_PGSTE 5378c2ecf20Sopenharmony_ci if (unlikely(mm->context.alloc_pgste)) 5388c2ecf20Sopenharmony_ci return 1; 5398c2ecf20Sopenharmony_ci#endif 5408c2ecf20Sopenharmony_ci return 0; 5418c2ecf20Sopenharmony_ci} 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci/* 5448c2ecf20Sopenharmony_ci * In the case that a guest uses storage keys 5458c2ecf20Sopenharmony_ci * faults should no longer be backed by zero pages 5468c2ecf20Sopenharmony_ci */ 5478c2ecf20Sopenharmony_ci#define mm_forbids_zeropage mm_has_pgste 5488c2ecf20Sopenharmony_cistatic inline int mm_uses_skeys(struct mm_struct *mm) 5498c2ecf20Sopenharmony_ci{ 5508c2ecf20Sopenharmony_ci#ifdef CONFIG_PGSTE 5518c2ecf20Sopenharmony_ci if (mm->context.uses_skeys) 5528c2ecf20Sopenharmony_ci return 1; 5538c2ecf20Sopenharmony_ci#endif 5548c2ecf20Sopenharmony_ci return 0; 5558c2ecf20Sopenharmony_ci} 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_cistatic inline void csp(unsigned int *ptr, unsigned int old, unsigned int new) 5588c2ecf20Sopenharmony_ci{ 5598c2ecf20Sopenharmony_ci register unsigned long reg2 asm("2") = old; 5608c2ecf20Sopenharmony_ci register unsigned long reg3 asm("3") = new; 5618c2ecf20Sopenharmony_ci unsigned long address = (unsigned long)ptr | 1; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci asm volatile( 5648c2ecf20Sopenharmony_ci " csp %0,%3" 5658c2ecf20Sopenharmony_ci : "+d" (reg2), "+m" (*ptr) 5668c2ecf20Sopenharmony_ci : "d" (reg3), "d" (address) 5678c2ecf20Sopenharmony_ci : "cc"); 5688c2ecf20Sopenharmony_ci} 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_cistatic inline void cspg(unsigned long *ptr, unsigned long old, unsigned long new) 5718c2ecf20Sopenharmony_ci{ 5728c2ecf20Sopenharmony_ci register unsigned long reg2 asm("2") = old; 5738c2ecf20Sopenharmony_ci register unsigned long reg3 asm("3") = new; 5748c2ecf20Sopenharmony_ci unsigned long address = (unsigned long)ptr | 1; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci asm volatile( 5778c2ecf20Sopenharmony_ci " .insn rre,0xb98a0000,%0,%3" 5788c2ecf20Sopenharmony_ci : "+d" (reg2), "+m" (*ptr) 5798c2ecf20Sopenharmony_ci : "d" (reg3), "d" (address) 5808c2ecf20Sopenharmony_ci : "cc"); 5818c2ecf20Sopenharmony_ci} 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci#define CRDTE_DTT_PAGE 0x00UL 5848c2ecf20Sopenharmony_ci#define CRDTE_DTT_SEGMENT 0x10UL 5858c2ecf20Sopenharmony_ci#define CRDTE_DTT_REGION3 0x14UL 5868c2ecf20Sopenharmony_ci#define CRDTE_DTT_REGION2 0x18UL 5878c2ecf20Sopenharmony_ci#define CRDTE_DTT_REGION1 0x1cUL 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_cistatic inline void crdte(unsigned long old, unsigned long new, 5908c2ecf20Sopenharmony_ci unsigned long table, unsigned long dtt, 5918c2ecf20Sopenharmony_ci unsigned long address, unsigned long asce) 5928c2ecf20Sopenharmony_ci{ 5938c2ecf20Sopenharmony_ci register unsigned long reg2 asm("2") = old; 5948c2ecf20Sopenharmony_ci register unsigned long reg3 asm("3") = new; 5958c2ecf20Sopenharmony_ci register unsigned long reg4 asm("4") = table | dtt; 5968c2ecf20Sopenharmony_ci register unsigned long reg5 asm("5") = address; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci asm volatile(".insn rrf,0xb98f0000,%0,%2,%4,0" 5998c2ecf20Sopenharmony_ci : "+d" (reg2) 6008c2ecf20Sopenharmony_ci : "d" (reg3), "d" (reg4), "d" (reg5), "a" (asce) 6018c2ecf20Sopenharmony_ci : "memory", "cc"); 6028c2ecf20Sopenharmony_ci} 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci/* 6058c2ecf20Sopenharmony_ci * pgd/p4d/pud/pmd/pte query functions 6068c2ecf20Sopenharmony_ci */ 6078c2ecf20Sopenharmony_cistatic inline int pgd_folded(pgd_t pgd) 6088c2ecf20Sopenharmony_ci{ 6098c2ecf20Sopenharmony_ci return (pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R1; 6108c2ecf20Sopenharmony_ci} 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_cistatic inline int pgd_present(pgd_t pgd) 6138c2ecf20Sopenharmony_ci{ 6148c2ecf20Sopenharmony_ci if (pgd_folded(pgd)) 6158c2ecf20Sopenharmony_ci return 1; 6168c2ecf20Sopenharmony_ci return (pgd_val(pgd) & _REGION_ENTRY_ORIGIN) != 0UL; 6178c2ecf20Sopenharmony_ci} 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_cistatic inline int pgd_none(pgd_t pgd) 6208c2ecf20Sopenharmony_ci{ 6218c2ecf20Sopenharmony_ci if (pgd_folded(pgd)) 6228c2ecf20Sopenharmony_ci return 0; 6238c2ecf20Sopenharmony_ci return (pgd_val(pgd) & _REGION_ENTRY_INVALID) != 0UL; 6248c2ecf20Sopenharmony_ci} 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_cistatic inline int pgd_bad(pgd_t pgd) 6278c2ecf20Sopenharmony_ci{ 6288c2ecf20Sopenharmony_ci if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R1) 6298c2ecf20Sopenharmony_ci return 0; 6308c2ecf20Sopenharmony_ci return (pgd_val(pgd) & ~_REGION_ENTRY_BITS) != 0; 6318c2ecf20Sopenharmony_ci} 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_cistatic inline unsigned long pgd_pfn(pgd_t pgd) 6348c2ecf20Sopenharmony_ci{ 6358c2ecf20Sopenharmony_ci unsigned long origin_mask; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci origin_mask = _REGION_ENTRY_ORIGIN; 6388c2ecf20Sopenharmony_ci return (pgd_val(pgd) & origin_mask) >> PAGE_SHIFT; 6398c2ecf20Sopenharmony_ci} 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_cistatic inline int p4d_folded(p4d_t p4d) 6428c2ecf20Sopenharmony_ci{ 6438c2ecf20Sopenharmony_ci return (p4d_val(p4d) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R2; 6448c2ecf20Sopenharmony_ci} 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_cistatic inline int p4d_present(p4d_t p4d) 6478c2ecf20Sopenharmony_ci{ 6488c2ecf20Sopenharmony_ci if (p4d_folded(p4d)) 6498c2ecf20Sopenharmony_ci return 1; 6508c2ecf20Sopenharmony_ci return (p4d_val(p4d) & _REGION_ENTRY_ORIGIN) != 0UL; 6518c2ecf20Sopenharmony_ci} 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_cistatic inline int p4d_none(p4d_t p4d) 6548c2ecf20Sopenharmony_ci{ 6558c2ecf20Sopenharmony_ci if (p4d_folded(p4d)) 6568c2ecf20Sopenharmony_ci return 0; 6578c2ecf20Sopenharmony_ci return p4d_val(p4d) == _REGION2_ENTRY_EMPTY; 6588c2ecf20Sopenharmony_ci} 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_cistatic inline unsigned long p4d_pfn(p4d_t p4d) 6618c2ecf20Sopenharmony_ci{ 6628c2ecf20Sopenharmony_ci unsigned long origin_mask; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci origin_mask = _REGION_ENTRY_ORIGIN; 6658c2ecf20Sopenharmony_ci return (p4d_val(p4d) & origin_mask) >> PAGE_SHIFT; 6668c2ecf20Sopenharmony_ci} 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_cistatic inline int pud_folded(pud_t pud) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci return (pud_val(pud) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R3; 6718c2ecf20Sopenharmony_ci} 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_cistatic inline int pud_present(pud_t pud) 6748c2ecf20Sopenharmony_ci{ 6758c2ecf20Sopenharmony_ci if (pud_folded(pud)) 6768c2ecf20Sopenharmony_ci return 1; 6778c2ecf20Sopenharmony_ci return (pud_val(pud) & _REGION_ENTRY_ORIGIN) != 0UL; 6788c2ecf20Sopenharmony_ci} 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_cistatic inline int pud_none(pud_t pud) 6818c2ecf20Sopenharmony_ci{ 6828c2ecf20Sopenharmony_ci if (pud_folded(pud)) 6838c2ecf20Sopenharmony_ci return 0; 6848c2ecf20Sopenharmony_ci return pud_val(pud) == _REGION3_ENTRY_EMPTY; 6858c2ecf20Sopenharmony_ci} 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci#define pud_leaf pud_large 6888c2ecf20Sopenharmony_cistatic inline int pud_large(pud_t pud) 6898c2ecf20Sopenharmony_ci{ 6908c2ecf20Sopenharmony_ci if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) != _REGION_ENTRY_TYPE_R3) 6918c2ecf20Sopenharmony_ci return 0; 6928c2ecf20Sopenharmony_ci return !!(pud_val(pud) & _REGION3_ENTRY_LARGE); 6938c2ecf20Sopenharmony_ci} 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci#define pmd_leaf pmd_large 6968c2ecf20Sopenharmony_cistatic inline int pmd_large(pmd_t pmd) 6978c2ecf20Sopenharmony_ci{ 6988c2ecf20Sopenharmony_ci return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0; 6998c2ecf20Sopenharmony_ci} 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_cistatic inline int pmd_bad(pmd_t pmd) 7028c2ecf20Sopenharmony_ci{ 7038c2ecf20Sopenharmony_ci if ((pmd_val(pmd) & _SEGMENT_ENTRY_TYPE_MASK) > 0 || pmd_large(pmd)) 7048c2ecf20Sopenharmony_ci return 1; 7058c2ecf20Sopenharmony_ci return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS) != 0; 7068c2ecf20Sopenharmony_ci} 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_cistatic inline int pud_bad(pud_t pud) 7098c2ecf20Sopenharmony_ci{ 7108c2ecf20Sopenharmony_ci unsigned long type = pud_val(pud) & _REGION_ENTRY_TYPE_MASK; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci if (type > _REGION_ENTRY_TYPE_R3 || pud_large(pud)) 7138c2ecf20Sopenharmony_ci return 1; 7148c2ecf20Sopenharmony_ci if (type < _REGION_ENTRY_TYPE_R3) 7158c2ecf20Sopenharmony_ci return 0; 7168c2ecf20Sopenharmony_ci return (pud_val(pud) & ~_REGION_ENTRY_BITS) != 0; 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_cistatic inline int p4d_bad(p4d_t p4d) 7208c2ecf20Sopenharmony_ci{ 7218c2ecf20Sopenharmony_ci unsigned long type = p4d_val(p4d) & _REGION_ENTRY_TYPE_MASK; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci if (type > _REGION_ENTRY_TYPE_R2) 7248c2ecf20Sopenharmony_ci return 1; 7258c2ecf20Sopenharmony_ci if (type < _REGION_ENTRY_TYPE_R2) 7268c2ecf20Sopenharmony_ci return 0; 7278c2ecf20Sopenharmony_ci return (p4d_val(p4d) & ~_REGION_ENTRY_BITS) != 0; 7288c2ecf20Sopenharmony_ci} 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_cistatic inline int pmd_present(pmd_t pmd) 7318c2ecf20Sopenharmony_ci{ 7328c2ecf20Sopenharmony_ci return pmd_val(pmd) != _SEGMENT_ENTRY_EMPTY; 7338c2ecf20Sopenharmony_ci} 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_cistatic inline int pmd_none(pmd_t pmd) 7368c2ecf20Sopenharmony_ci{ 7378c2ecf20Sopenharmony_ci return pmd_val(pmd) == _SEGMENT_ENTRY_EMPTY; 7388c2ecf20Sopenharmony_ci} 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci#define pmd_write pmd_write 7418c2ecf20Sopenharmony_cistatic inline int pmd_write(pmd_t pmd) 7428c2ecf20Sopenharmony_ci{ 7438c2ecf20Sopenharmony_ci return (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) != 0; 7448c2ecf20Sopenharmony_ci} 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci#define pud_write pud_write 7478c2ecf20Sopenharmony_cistatic inline int pud_write(pud_t pud) 7488c2ecf20Sopenharmony_ci{ 7498c2ecf20Sopenharmony_ci return (pud_val(pud) & _REGION3_ENTRY_WRITE) != 0; 7508c2ecf20Sopenharmony_ci} 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_cistatic inline int pmd_dirty(pmd_t pmd) 7538c2ecf20Sopenharmony_ci{ 7548c2ecf20Sopenharmony_ci return (pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY) != 0; 7558c2ecf20Sopenharmony_ci} 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_cistatic inline int pmd_young(pmd_t pmd) 7588c2ecf20Sopenharmony_ci{ 7598c2ecf20Sopenharmony_ci return (pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG) != 0; 7608c2ecf20Sopenharmony_ci} 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_cistatic inline int pte_present(pte_t pte) 7638c2ecf20Sopenharmony_ci{ 7648c2ecf20Sopenharmony_ci /* Bit pattern: (pte & 0x001) == 0x001 */ 7658c2ecf20Sopenharmony_ci return (pte_val(pte) & _PAGE_PRESENT) != 0; 7668c2ecf20Sopenharmony_ci} 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_cistatic inline int pte_none(pte_t pte) 7698c2ecf20Sopenharmony_ci{ 7708c2ecf20Sopenharmony_ci /* Bit pattern: pte == 0x400 */ 7718c2ecf20Sopenharmony_ci return pte_val(pte) == _PAGE_INVALID; 7728c2ecf20Sopenharmony_ci} 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_cistatic inline int pte_swap(pte_t pte) 7758c2ecf20Sopenharmony_ci{ 7768c2ecf20Sopenharmony_ci /* Bit pattern: (pte & 0x201) == 0x200 */ 7778c2ecf20Sopenharmony_ci return (pte_val(pte) & (_PAGE_PROTECT | _PAGE_PRESENT)) 7788c2ecf20Sopenharmony_ci == _PAGE_PROTECT; 7798c2ecf20Sopenharmony_ci} 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_cistatic inline int pte_special(pte_t pte) 7828c2ecf20Sopenharmony_ci{ 7838c2ecf20Sopenharmony_ci return (pte_val(pte) & _PAGE_SPECIAL); 7848c2ecf20Sopenharmony_ci} 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTE_SAME 7878c2ecf20Sopenharmony_cistatic inline int pte_same(pte_t a, pte_t b) 7888c2ecf20Sopenharmony_ci{ 7898c2ecf20Sopenharmony_ci return pte_val(a) == pte_val(b); 7908c2ecf20Sopenharmony_ci} 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci#ifdef CONFIG_NUMA_BALANCING 7938c2ecf20Sopenharmony_cistatic inline int pte_protnone(pte_t pte) 7948c2ecf20Sopenharmony_ci{ 7958c2ecf20Sopenharmony_ci return pte_present(pte) && !(pte_val(pte) & _PAGE_READ); 7968c2ecf20Sopenharmony_ci} 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_cistatic inline int pmd_protnone(pmd_t pmd) 7998c2ecf20Sopenharmony_ci{ 8008c2ecf20Sopenharmony_ci /* pmd_large(pmd) implies pmd_present(pmd) */ 8018c2ecf20Sopenharmony_ci return pmd_large(pmd) && !(pmd_val(pmd) & _SEGMENT_ENTRY_READ); 8028c2ecf20Sopenharmony_ci} 8038c2ecf20Sopenharmony_ci#endif 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_cistatic inline int pte_soft_dirty(pte_t pte) 8068c2ecf20Sopenharmony_ci{ 8078c2ecf20Sopenharmony_ci return pte_val(pte) & _PAGE_SOFT_DIRTY; 8088c2ecf20Sopenharmony_ci} 8098c2ecf20Sopenharmony_ci#define pte_swp_soft_dirty pte_soft_dirty 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_cistatic inline pte_t pte_mksoft_dirty(pte_t pte) 8128c2ecf20Sopenharmony_ci{ 8138c2ecf20Sopenharmony_ci pte_val(pte) |= _PAGE_SOFT_DIRTY; 8148c2ecf20Sopenharmony_ci return pte; 8158c2ecf20Sopenharmony_ci} 8168c2ecf20Sopenharmony_ci#define pte_swp_mksoft_dirty pte_mksoft_dirty 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_cistatic inline pte_t pte_clear_soft_dirty(pte_t pte) 8198c2ecf20Sopenharmony_ci{ 8208c2ecf20Sopenharmony_ci pte_val(pte) &= ~_PAGE_SOFT_DIRTY; 8218c2ecf20Sopenharmony_ci return pte; 8228c2ecf20Sopenharmony_ci} 8238c2ecf20Sopenharmony_ci#define pte_swp_clear_soft_dirty pte_clear_soft_dirty 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_cistatic inline int pmd_soft_dirty(pmd_t pmd) 8268c2ecf20Sopenharmony_ci{ 8278c2ecf20Sopenharmony_ci return pmd_val(pmd) & _SEGMENT_ENTRY_SOFT_DIRTY; 8288c2ecf20Sopenharmony_ci} 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mksoft_dirty(pmd_t pmd) 8318c2ecf20Sopenharmony_ci{ 8328c2ecf20Sopenharmony_ci pmd_val(pmd) |= _SEGMENT_ENTRY_SOFT_DIRTY; 8338c2ecf20Sopenharmony_ci return pmd; 8348c2ecf20Sopenharmony_ci} 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_cistatic inline pmd_t pmd_clear_soft_dirty(pmd_t pmd) 8378c2ecf20Sopenharmony_ci{ 8388c2ecf20Sopenharmony_ci pmd_val(pmd) &= ~_SEGMENT_ENTRY_SOFT_DIRTY; 8398c2ecf20Sopenharmony_ci return pmd; 8408c2ecf20Sopenharmony_ci} 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci/* 8438c2ecf20Sopenharmony_ci * query functions pte_write/pte_dirty/pte_young only work if 8448c2ecf20Sopenharmony_ci * pte_present() is true. Undefined behaviour if not.. 8458c2ecf20Sopenharmony_ci */ 8468c2ecf20Sopenharmony_cistatic inline int pte_write(pte_t pte) 8478c2ecf20Sopenharmony_ci{ 8488c2ecf20Sopenharmony_ci return (pte_val(pte) & _PAGE_WRITE) != 0; 8498c2ecf20Sopenharmony_ci} 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_cistatic inline int pte_dirty(pte_t pte) 8528c2ecf20Sopenharmony_ci{ 8538c2ecf20Sopenharmony_ci return (pte_val(pte) & _PAGE_DIRTY) != 0; 8548c2ecf20Sopenharmony_ci} 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_cistatic inline int pte_young(pte_t pte) 8578c2ecf20Sopenharmony_ci{ 8588c2ecf20Sopenharmony_ci return (pte_val(pte) & _PAGE_YOUNG) != 0; 8598c2ecf20Sopenharmony_ci} 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTE_UNUSED 8628c2ecf20Sopenharmony_cistatic inline int pte_unused(pte_t pte) 8638c2ecf20Sopenharmony_ci{ 8648c2ecf20Sopenharmony_ci return pte_val(pte) & _PAGE_UNUSED; 8658c2ecf20Sopenharmony_ci} 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci/* 8688c2ecf20Sopenharmony_ci * Extract the pgprot value from the given pte while at the same time making it 8698c2ecf20Sopenharmony_ci * usable for kernel address space mappings where fault driven dirty and 8708c2ecf20Sopenharmony_ci * young/old accounting is not supported, i.e _PAGE_PROTECT and _PAGE_INVALID 8718c2ecf20Sopenharmony_ci * must not be set. 8728c2ecf20Sopenharmony_ci */ 8738c2ecf20Sopenharmony_cistatic inline pgprot_t pte_pgprot(pte_t pte) 8748c2ecf20Sopenharmony_ci{ 8758c2ecf20Sopenharmony_ci unsigned long pte_flags = pte_val(pte) & _PAGE_CHG_MASK; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci if (pte_write(pte)) 8788c2ecf20Sopenharmony_ci pte_flags |= pgprot_val(PAGE_KERNEL); 8798c2ecf20Sopenharmony_ci else 8808c2ecf20Sopenharmony_ci pte_flags |= pgprot_val(PAGE_KERNEL_RO); 8818c2ecf20Sopenharmony_ci pte_flags |= pte_val(pte) & mio_wb_bit_mask; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci return __pgprot(pte_flags); 8848c2ecf20Sopenharmony_ci} 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci/* 8878c2ecf20Sopenharmony_ci * pgd/pmd/pte modification functions 8888c2ecf20Sopenharmony_ci */ 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_cistatic inline void pgd_clear(pgd_t *pgd) 8918c2ecf20Sopenharmony_ci{ 8928c2ecf20Sopenharmony_ci if ((pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R1) 8938c2ecf20Sopenharmony_ci pgd_val(*pgd) = _REGION1_ENTRY_EMPTY; 8948c2ecf20Sopenharmony_ci} 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_cistatic inline void p4d_clear(p4d_t *p4d) 8978c2ecf20Sopenharmony_ci{ 8988c2ecf20Sopenharmony_ci if ((p4d_val(*p4d) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R2) 8998c2ecf20Sopenharmony_ci p4d_val(*p4d) = _REGION2_ENTRY_EMPTY; 9008c2ecf20Sopenharmony_ci} 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_cistatic inline void pud_clear(pud_t *pud) 9038c2ecf20Sopenharmony_ci{ 9048c2ecf20Sopenharmony_ci if ((pud_val(*pud) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) 9058c2ecf20Sopenharmony_ci pud_val(*pud) = _REGION3_ENTRY_EMPTY; 9068c2ecf20Sopenharmony_ci} 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_cistatic inline void pmd_clear(pmd_t *pmdp) 9098c2ecf20Sopenharmony_ci{ 9108c2ecf20Sopenharmony_ci pmd_val(*pmdp) = _SEGMENT_ENTRY_EMPTY; 9118c2ecf20Sopenharmony_ci} 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_cistatic inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) 9148c2ecf20Sopenharmony_ci{ 9158c2ecf20Sopenharmony_ci pte_val(*ptep) = _PAGE_INVALID; 9168c2ecf20Sopenharmony_ci} 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci/* 9198c2ecf20Sopenharmony_ci * The following pte modification functions only work if 9208c2ecf20Sopenharmony_ci * pte_present() is true. Undefined behaviour if not.. 9218c2ecf20Sopenharmony_ci */ 9228c2ecf20Sopenharmony_cistatic inline pte_t pte_modify(pte_t pte, pgprot_t newprot) 9238c2ecf20Sopenharmony_ci{ 9248c2ecf20Sopenharmony_ci pte_val(pte) &= _PAGE_CHG_MASK; 9258c2ecf20Sopenharmony_ci pte_val(pte) |= pgprot_val(newprot); 9268c2ecf20Sopenharmony_ci /* 9278c2ecf20Sopenharmony_ci * newprot for PAGE_NONE, PAGE_RO, PAGE_RX, PAGE_RW and PAGE_RWX 9288c2ecf20Sopenharmony_ci * has the invalid bit set, clear it again for readable, young pages 9298c2ecf20Sopenharmony_ci */ 9308c2ecf20Sopenharmony_ci if ((pte_val(pte) & _PAGE_YOUNG) && (pte_val(pte) & _PAGE_READ)) 9318c2ecf20Sopenharmony_ci pte_val(pte) &= ~_PAGE_INVALID; 9328c2ecf20Sopenharmony_ci /* 9338c2ecf20Sopenharmony_ci * newprot for PAGE_RO, PAGE_RX, PAGE_RW and PAGE_RWX has the page 9348c2ecf20Sopenharmony_ci * protection bit set, clear it again for writable, dirty pages 9358c2ecf20Sopenharmony_ci */ 9368c2ecf20Sopenharmony_ci if ((pte_val(pte) & _PAGE_DIRTY) && (pte_val(pte) & _PAGE_WRITE)) 9378c2ecf20Sopenharmony_ci pte_val(pte) &= ~_PAGE_PROTECT; 9388c2ecf20Sopenharmony_ci return pte; 9398c2ecf20Sopenharmony_ci} 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_cistatic inline pte_t pte_wrprotect(pte_t pte) 9428c2ecf20Sopenharmony_ci{ 9438c2ecf20Sopenharmony_ci pte_val(pte) &= ~_PAGE_WRITE; 9448c2ecf20Sopenharmony_ci pte_val(pte) |= _PAGE_PROTECT; 9458c2ecf20Sopenharmony_ci return pte; 9468c2ecf20Sopenharmony_ci} 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_cistatic inline pte_t pte_mkwrite(pte_t pte) 9498c2ecf20Sopenharmony_ci{ 9508c2ecf20Sopenharmony_ci pte_val(pte) |= _PAGE_WRITE; 9518c2ecf20Sopenharmony_ci if (pte_val(pte) & _PAGE_DIRTY) 9528c2ecf20Sopenharmony_ci pte_val(pte) &= ~_PAGE_PROTECT; 9538c2ecf20Sopenharmony_ci return pte; 9548c2ecf20Sopenharmony_ci} 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_cistatic inline pte_t pte_mkclean(pte_t pte) 9578c2ecf20Sopenharmony_ci{ 9588c2ecf20Sopenharmony_ci pte_val(pte) &= ~_PAGE_DIRTY; 9598c2ecf20Sopenharmony_ci pte_val(pte) |= _PAGE_PROTECT; 9608c2ecf20Sopenharmony_ci return pte; 9618c2ecf20Sopenharmony_ci} 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_cistatic inline pte_t pte_mkdirty(pte_t pte) 9648c2ecf20Sopenharmony_ci{ 9658c2ecf20Sopenharmony_ci pte_val(pte) |= _PAGE_DIRTY | _PAGE_SOFT_DIRTY; 9668c2ecf20Sopenharmony_ci if (pte_val(pte) & _PAGE_WRITE) 9678c2ecf20Sopenharmony_ci pte_val(pte) &= ~_PAGE_PROTECT; 9688c2ecf20Sopenharmony_ci return pte; 9698c2ecf20Sopenharmony_ci} 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_cistatic inline pte_t pte_mkold(pte_t pte) 9728c2ecf20Sopenharmony_ci{ 9738c2ecf20Sopenharmony_ci pte_val(pte) &= ~_PAGE_YOUNG; 9748c2ecf20Sopenharmony_ci pte_val(pte) |= _PAGE_INVALID; 9758c2ecf20Sopenharmony_ci return pte; 9768c2ecf20Sopenharmony_ci} 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_cistatic inline pte_t pte_mkyoung(pte_t pte) 9798c2ecf20Sopenharmony_ci{ 9808c2ecf20Sopenharmony_ci pte_val(pte) |= _PAGE_YOUNG; 9818c2ecf20Sopenharmony_ci if (pte_val(pte) & _PAGE_READ) 9828c2ecf20Sopenharmony_ci pte_val(pte) &= ~_PAGE_INVALID; 9838c2ecf20Sopenharmony_ci return pte; 9848c2ecf20Sopenharmony_ci} 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_cistatic inline pte_t pte_mkspecial(pte_t pte) 9878c2ecf20Sopenharmony_ci{ 9888c2ecf20Sopenharmony_ci pte_val(pte) |= _PAGE_SPECIAL; 9898c2ecf20Sopenharmony_ci return pte; 9908c2ecf20Sopenharmony_ci} 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci#ifdef CONFIG_HUGETLB_PAGE 9938c2ecf20Sopenharmony_cistatic inline pte_t pte_mkhuge(pte_t pte) 9948c2ecf20Sopenharmony_ci{ 9958c2ecf20Sopenharmony_ci pte_val(pte) |= _PAGE_LARGE; 9968c2ecf20Sopenharmony_ci return pte; 9978c2ecf20Sopenharmony_ci} 9988c2ecf20Sopenharmony_ci#endif 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci#define IPTE_GLOBAL 0 10018c2ecf20Sopenharmony_ci#define IPTE_LOCAL 1 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci#define IPTE_NODAT 0x400 10048c2ecf20Sopenharmony_ci#define IPTE_GUEST_ASCE 0x800 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_cistatic __always_inline void __ptep_ipte(unsigned long address, pte_t *ptep, 10078c2ecf20Sopenharmony_ci unsigned long opt, unsigned long asce, 10088c2ecf20Sopenharmony_ci int local) 10098c2ecf20Sopenharmony_ci{ 10108c2ecf20Sopenharmony_ci unsigned long pto = (unsigned long) ptep; 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci if (__builtin_constant_p(opt) && opt == 0) { 10138c2ecf20Sopenharmony_ci /* Invalidation + TLB flush for the pte */ 10148c2ecf20Sopenharmony_ci asm volatile( 10158c2ecf20Sopenharmony_ci " .insn rrf,0xb2210000,%[r1],%[r2],0,%[m4]" 10168c2ecf20Sopenharmony_ci : "+m" (*ptep) : [r1] "a" (pto), [r2] "a" (address), 10178c2ecf20Sopenharmony_ci [m4] "i" (local)); 10188c2ecf20Sopenharmony_ci return; 10198c2ecf20Sopenharmony_ci } 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci /* Invalidate ptes with options + TLB flush of the ptes */ 10228c2ecf20Sopenharmony_ci opt = opt | (asce & _ASCE_ORIGIN); 10238c2ecf20Sopenharmony_ci asm volatile( 10248c2ecf20Sopenharmony_ci " .insn rrf,0xb2210000,%[r1],%[r2],%[r3],%[m4]" 10258c2ecf20Sopenharmony_ci : [r2] "+a" (address), [r3] "+a" (opt) 10268c2ecf20Sopenharmony_ci : [r1] "a" (pto), [m4] "i" (local) : "memory"); 10278c2ecf20Sopenharmony_ci} 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_cistatic __always_inline void __ptep_ipte_range(unsigned long address, int nr, 10308c2ecf20Sopenharmony_ci pte_t *ptep, int local) 10318c2ecf20Sopenharmony_ci{ 10328c2ecf20Sopenharmony_ci unsigned long pto = (unsigned long) ptep; 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci /* Invalidate a range of ptes + TLB flush of the ptes */ 10358c2ecf20Sopenharmony_ci do { 10368c2ecf20Sopenharmony_ci asm volatile( 10378c2ecf20Sopenharmony_ci " .insn rrf,0xb2210000,%[r1],%[r2],%[r3],%[m4]" 10388c2ecf20Sopenharmony_ci : [r2] "+a" (address), [r3] "+a" (nr) 10398c2ecf20Sopenharmony_ci : [r1] "a" (pto), [m4] "i" (local) : "memory"); 10408c2ecf20Sopenharmony_ci } while (nr != 255); 10418c2ecf20Sopenharmony_ci} 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci/* 10448c2ecf20Sopenharmony_ci * This is hard to understand. ptep_get_and_clear and ptep_clear_flush 10458c2ecf20Sopenharmony_ci * both clear the TLB for the unmapped pte. The reason is that 10468c2ecf20Sopenharmony_ci * ptep_get_and_clear is used in common code (e.g. change_pte_range) 10478c2ecf20Sopenharmony_ci * to modify an active pte. The sequence is 10488c2ecf20Sopenharmony_ci * 1) ptep_get_and_clear 10498c2ecf20Sopenharmony_ci * 2) set_pte_at 10508c2ecf20Sopenharmony_ci * 3) flush_tlb_range 10518c2ecf20Sopenharmony_ci * On s390 the tlb needs to get flushed with the modification of the pte 10528c2ecf20Sopenharmony_ci * if the pte is active. The only way how this can be implemented is to 10538c2ecf20Sopenharmony_ci * have ptep_get_and_clear do the tlb flush. In exchange flush_tlb_range 10548c2ecf20Sopenharmony_ci * is a nop. 10558c2ecf20Sopenharmony_ci */ 10568c2ecf20Sopenharmony_cipte_t ptep_xchg_direct(struct mm_struct *, unsigned long, pte_t *, pte_t); 10578c2ecf20Sopenharmony_cipte_t ptep_xchg_lazy(struct mm_struct *, unsigned long, pte_t *, pte_t); 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG 10608c2ecf20Sopenharmony_cistatic inline int ptep_test_and_clear_young(struct vm_area_struct *vma, 10618c2ecf20Sopenharmony_ci unsigned long addr, pte_t *ptep) 10628c2ecf20Sopenharmony_ci{ 10638c2ecf20Sopenharmony_ci pte_t pte = *ptep; 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci pte = ptep_xchg_direct(vma->vm_mm, addr, ptep, pte_mkold(pte)); 10668c2ecf20Sopenharmony_ci return pte_young(pte); 10678c2ecf20Sopenharmony_ci} 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH 10708c2ecf20Sopenharmony_cistatic inline int ptep_clear_flush_young(struct vm_area_struct *vma, 10718c2ecf20Sopenharmony_ci unsigned long address, pte_t *ptep) 10728c2ecf20Sopenharmony_ci{ 10738c2ecf20Sopenharmony_ci return ptep_test_and_clear_young(vma, address, ptep); 10748c2ecf20Sopenharmony_ci} 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_GET_AND_CLEAR 10778c2ecf20Sopenharmony_cistatic inline pte_t ptep_get_and_clear(struct mm_struct *mm, 10788c2ecf20Sopenharmony_ci unsigned long addr, pte_t *ptep) 10798c2ecf20Sopenharmony_ci{ 10808c2ecf20Sopenharmony_ci pte_t res; 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci res = ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID)); 10838c2ecf20Sopenharmony_ci if (mm_is_protected(mm) && pte_present(res)) 10848c2ecf20Sopenharmony_ci uv_convert_from_secure(pte_val(res) & PAGE_MASK); 10858c2ecf20Sopenharmony_ci return res; 10868c2ecf20Sopenharmony_ci} 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION 10898c2ecf20Sopenharmony_cipte_t ptep_modify_prot_start(struct vm_area_struct *, unsigned long, pte_t *); 10908c2ecf20Sopenharmony_civoid ptep_modify_prot_commit(struct vm_area_struct *, unsigned long, 10918c2ecf20Sopenharmony_ci pte_t *, pte_t, pte_t); 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_CLEAR_FLUSH 10948c2ecf20Sopenharmony_cistatic inline pte_t ptep_clear_flush(struct vm_area_struct *vma, 10958c2ecf20Sopenharmony_ci unsigned long addr, pte_t *ptep) 10968c2ecf20Sopenharmony_ci{ 10978c2ecf20Sopenharmony_ci pte_t res; 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci res = ptep_xchg_direct(vma->vm_mm, addr, ptep, __pte(_PAGE_INVALID)); 11008c2ecf20Sopenharmony_ci if (mm_is_protected(vma->vm_mm) && pte_present(res)) 11018c2ecf20Sopenharmony_ci uv_convert_from_secure(pte_val(res) & PAGE_MASK); 11028c2ecf20Sopenharmony_ci return res; 11038c2ecf20Sopenharmony_ci} 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci/* 11068c2ecf20Sopenharmony_ci * The batched pte unmap code uses ptep_get_and_clear_full to clear the 11078c2ecf20Sopenharmony_ci * ptes. Here an optimization is possible. tlb_gather_mmu flushes all 11088c2ecf20Sopenharmony_ci * tlbs of an mm if it can guarantee that the ptes of the mm_struct 11098c2ecf20Sopenharmony_ci * cannot be accessed while the batched unmap is running. In this case 11108c2ecf20Sopenharmony_ci * full==1 and a simple pte_clear is enough. See tlb.h. 11118c2ecf20Sopenharmony_ci */ 11128c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL 11138c2ecf20Sopenharmony_cistatic inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, 11148c2ecf20Sopenharmony_ci unsigned long addr, 11158c2ecf20Sopenharmony_ci pte_t *ptep, int full) 11168c2ecf20Sopenharmony_ci{ 11178c2ecf20Sopenharmony_ci pte_t res; 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci if (full) { 11208c2ecf20Sopenharmony_ci res = *ptep; 11218c2ecf20Sopenharmony_ci *ptep = __pte(_PAGE_INVALID); 11228c2ecf20Sopenharmony_ci } else { 11238c2ecf20Sopenharmony_ci res = ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID)); 11248c2ecf20Sopenharmony_ci } 11258c2ecf20Sopenharmony_ci if (mm_is_protected(mm) && pte_present(res)) 11268c2ecf20Sopenharmony_ci uv_convert_from_secure(pte_val(res) & PAGE_MASK); 11278c2ecf20Sopenharmony_ci return res; 11288c2ecf20Sopenharmony_ci} 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_SET_WRPROTECT 11318c2ecf20Sopenharmony_cistatic inline void ptep_set_wrprotect(struct mm_struct *mm, 11328c2ecf20Sopenharmony_ci unsigned long addr, pte_t *ptep) 11338c2ecf20Sopenharmony_ci{ 11348c2ecf20Sopenharmony_ci pte_t pte = *ptep; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci if (pte_write(pte)) 11378c2ecf20Sopenharmony_ci ptep_xchg_lazy(mm, addr, ptep, pte_wrprotect(pte)); 11388c2ecf20Sopenharmony_ci} 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS 11418c2ecf20Sopenharmony_cistatic inline int ptep_set_access_flags(struct vm_area_struct *vma, 11428c2ecf20Sopenharmony_ci unsigned long addr, pte_t *ptep, 11438c2ecf20Sopenharmony_ci pte_t entry, int dirty) 11448c2ecf20Sopenharmony_ci{ 11458c2ecf20Sopenharmony_ci if (pte_same(*ptep, entry)) 11468c2ecf20Sopenharmony_ci return 0; 11478c2ecf20Sopenharmony_ci ptep_xchg_direct(vma->vm_mm, addr, ptep, entry); 11488c2ecf20Sopenharmony_ci return 1; 11498c2ecf20Sopenharmony_ci} 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci/* 11528c2ecf20Sopenharmony_ci * Additional functions to handle KVM guest page tables 11538c2ecf20Sopenharmony_ci */ 11548c2ecf20Sopenharmony_civoid ptep_set_pte_at(struct mm_struct *mm, unsigned long addr, 11558c2ecf20Sopenharmony_ci pte_t *ptep, pte_t entry); 11568c2ecf20Sopenharmony_civoid ptep_set_notify(struct mm_struct *mm, unsigned long addr, pte_t *ptep); 11578c2ecf20Sopenharmony_civoid ptep_notify(struct mm_struct *mm, unsigned long addr, 11588c2ecf20Sopenharmony_ci pte_t *ptep, unsigned long bits); 11598c2ecf20Sopenharmony_ciint ptep_force_prot(struct mm_struct *mm, unsigned long gaddr, 11608c2ecf20Sopenharmony_ci pte_t *ptep, int prot, unsigned long bit); 11618c2ecf20Sopenharmony_civoid ptep_zap_unused(struct mm_struct *mm, unsigned long addr, 11628c2ecf20Sopenharmony_ci pte_t *ptep , int reset); 11638c2ecf20Sopenharmony_civoid ptep_zap_key(struct mm_struct *mm, unsigned long addr, pte_t *ptep); 11648c2ecf20Sopenharmony_ciint ptep_shadow_pte(struct mm_struct *mm, unsigned long saddr, 11658c2ecf20Sopenharmony_ci pte_t *sptep, pte_t *tptep, pte_t pte); 11668c2ecf20Sopenharmony_civoid ptep_unshadow_pte(struct mm_struct *mm, unsigned long saddr, pte_t *ptep); 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_cibool ptep_test_and_clear_uc(struct mm_struct *mm, unsigned long address, 11698c2ecf20Sopenharmony_ci pte_t *ptep); 11708c2ecf20Sopenharmony_ciint set_guest_storage_key(struct mm_struct *mm, unsigned long addr, 11718c2ecf20Sopenharmony_ci unsigned char key, bool nq); 11728c2ecf20Sopenharmony_ciint cond_set_guest_storage_key(struct mm_struct *mm, unsigned long addr, 11738c2ecf20Sopenharmony_ci unsigned char key, unsigned char *oldkey, 11748c2ecf20Sopenharmony_ci bool nq, bool mr, bool mc); 11758c2ecf20Sopenharmony_ciint reset_guest_reference_bit(struct mm_struct *mm, unsigned long addr); 11768c2ecf20Sopenharmony_ciint get_guest_storage_key(struct mm_struct *mm, unsigned long addr, 11778c2ecf20Sopenharmony_ci unsigned char *key); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ciint set_pgste_bits(struct mm_struct *mm, unsigned long addr, 11808c2ecf20Sopenharmony_ci unsigned long bits, unsigned long value); 11818c2ecf20Sopenharmony_ciint get_pgste(struct mm_struct *mm, unsigned long hva, unsigned long *pgstep); 11828c2ecf20Sopenharmony_ciint pgste_perform_essa(struct mm_struct *mm, unsigned long hva, int orc, 11838c2ecf20Sopenharmony_ci unsigned long *oldpte, unsigned long *oldpgste); 11848c2ecf20Sopenharmony_civoid gmap_pmdp_csp(struct mm_struct *mm, unsigned long vmaddr); 11858c2ecf20Sopenharmony_civoid gmap_pmdp_invalidate(struct mm_struct *mm, unsigned long vmaddr); 11868c2ecf20Sopenharmony_civoid gmap_pmdp_idte_local(struct mm_struct *mm, unsigned long vmaddr); 11878c2ecf20Sopenharmony_civoid gmap_pmdp_idte_global(struct mm_struct *mm, unsigned long vmaddr); 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci#define pgprot_writecombine pgprot_writecombine 11908c2ecf20Sopenharmony_cipgprot_t pgprot_writecombine(pgprot_t prot); 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci#define pgprot_writethrough pgprot_writethrough 11938c2ecf20Sopenharmony_cipgprot_t pgprot_writethrough(pgprot_t prot); 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci/* 11968c2ecf20Sopenharmony_ci * Certain architectures need to do special things when PTEs 11978c2ecf20Sopenharmony_ci * within a page table are directly modified. Thus, the following 11988c2ecf20Sopenharmony_ci * hook is made available. 11998c2ecf20Sopenharmony_ci */ 12008c2ecf20Sopenharmony_cistatic inline void set_pte_at(struct mm_struct *mm, unsigned long addr, 12018c2ecf20Sopenharmony_ci pte_t *ptep, pte_t entry) 12028c2ecf20Sopenharmony_ci{ 12038c2ecf20Sopenharmony_ci if (pte_present(entry)) 12048c2ecf20Sopenharmony_ci pte_val(entry) &= ~_PAGE_UNUSED; 12058c2ecf20Sopenharmony_ci if (mm_has_pgste(mm)) 12068c2ecf20Sopenharmony_ci ptep_set_pte_at(mm, addr, ptep, entry); 12078c2ecf20Sopenharmony_ci else 12088c2ecf20Sopenharmony_ci *ptep = entry; 12098c2ecf20Sopenharmony_ci} 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci/* 12128c2ecf20Sopenharmony_ci * Conversion functions: convert a page and protection to a page entry, 12138c2ecf20Sopenharmony_ci * and a page entry and page directory to the page they refer to. 12148c2ecf20Sopenharmony_ci */ 12158c2ecf20Sopenharmony_cistatic inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) 12168c2ecf20Sopenharmony_ci{ 12178c2ecf20Sopenharmony_ci pte_t __pte; 12188c2ecf20Sopenharmony_ci 12198c2ecf20Sopenharmony_ci pte_val(__pte) = physpage | pgprot_val(pgprot); 12208c2ecf20Sopenharmony_ci if (!MACHINE_HAS_NX) 12218c2ecf20Sopenharmony_ci pte_val(__pte) &= ~_PAGE_NOEXEC; 12228c2ecf20Sopenharmony_ci return pte_mkyoung(__pte); 12238c2ecf20Sopenharmony_ci} 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_cistatic inline pte_t mk_pte(struct page *page, pgprot_t pgprot) 12268c2ecf20Sopenharmony_ci{ 12278c2ecf20Sopenharmony_ci unsigned long physpage = page_to_phys(page); 12288c2ecf20Sopenharmony_ci pte_t __pte = mk_pte_phys(physpage, pgprot); 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci if (pte_write(__pte) && PageDirty(page)) 12318c2ecf20Sopenharmony_ci __pte = pte_mkdirty(__pte); 12328c2ecf20Sopenharmony_ci return __pte; 12338c2ecf20Sopenharmony_ci} 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) 12368c2ecf20Sopenharmony_ci#define p4d_index(address) (((address) >> P4D_SHIFT) & (PTRS_PER_P4D-1)) 12378c2ecf20Sopenharmony_ci#define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) 12388c2ecf20Sopenharmony_ci#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci#define p4d_deref(pud) (p4d_val(pud) & _REGION_ENTRY_ORIGIN) 12418c2ecf20Sopenharmony_ci#define pgd_deref(pgd) (pgd_val(pgd) & _REGION_ENTRY_ORIGIN) 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_cistatic inline unsigned long pmd_deref(pmd_t pmd) 12448c2ecf20Sopenharmony_ci{ 12458c2ecf20Sopenharmony_ci unsigned long origin_mask; 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci origin_mask = _SEGMENT_ENTRY_ORIGIN; 12488c2ecf20Sopenharmony_ci if (pmd_large(pmd)) 12498c2ecf20Sopenharmony_ci origin_mask = _SEGMENT_ENTRY_ORIGIN_LARGE; 12508c2ecf20Sopenharmony_ci return pmd_val(pmd) & origin_mask; 12518c2ecf20Sopenharmony_ci} 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_cistatic inline unsigned long pmd_pfn(pmd_t pmd) 12548c2ecf20Sopenharmony_ci{ 12558c2ecf20Sopenharmony_ci return pmd_deref(pmd) >> PAGE_SHIFT; 12568c2ecf20Sopenharmony_ci} 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_cistatic inline unsigned long pud_deref(pud_t pud) 12598c2ecf20Sopenharmony_ci{ 12608c2ecf20Sopenharmony_ci unsigned long origin_mask; 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci origin_mask = _REGION_ENTRY_ORIGIN; 12638c2ecf20Sopenharmony_ci if (pud_large(pud)) 12648c2ecf20Sopenharmony_ci origin_mask = _REGION3_ENTRY_ORIGIN_LARGE; 12658c2ecf20Sopenharmony_ci return pud_val(pud) & origin_mask; 12668c2ecf20Sopenharmony_ci} 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_cistatic inline unsigned long pud_pfn(pud_t pud) 12698c2ecf20Sopenharmony_ci{ 12708c2ecf20Sopenharmony_ci return pud_deref(pud) >> PAGE_SHIFT; 12718c2ecf20Sopenharmony_ci} 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci/* 12748c2ecf20Sopenharmony_ci * The pgd_offset function *always* adds the index for the top-level 12758c2ecf20Sopenharmony_ci * region/segment table. This is done to get a sequence like the 12768c2ecf20Sopenharmony_ci * following to work: 12778c2ecf20Sopenharmony_ci * pgdp = pgd_offset(current->mm, addr); 12788c2ecf20Sopenharmony_ci * pgd = READ_ONCE(*pgdp); 12798c2ecf20Sopenharmony_ci * p4dp = p4d_offset(&pgd, addr); 12808c2ecf20Sopenharmony_ci * ... 12818c2ecf20Sopenharmony_ci * The subsequent p4d_offset, pud_offset and pmd_offset functions 12828c2ecf20Sopenharmony_ci * only add an index if they dereferenced the pointer. 12838c2ecf20Sopenharmony_ci */ 12848c2ecf20Sopenharmony_cistatic inline pgd_t *pgd_offset_raw(pgd_t *pgd, unsigned long address) 12858c2ecf20Sopenharmony_ci{ 12868c2ecf20Sopenharmony_ci unsigned long rste; 12878c2ecf20Sopenharmony_ci unsigned int shift; 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci /* Get the first entry of the top level table */ 12908c2ecf20Sopenharmony_ci rste = pgd_val(*pgd); 12918c2ecf20Sopenharmony_ci /* Pick up the shift from the table type of the first entry */ 12928c2ecf20Sopenharmony_ci shift = ((rste & _REGION_ENTRY_TYPE_MASK) >> 2) * 11 + 20; 12938c2ecf20Sopenharmony_ci return pgd + ((address >> shift) & (PTRS_PER_PGD - 1)); 12948c2ecf20Sopenharmony_ci} 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci#define pgd_offset(mm, address) pgd_offset_raw(READ_ONCE((mm)->pgd), address) 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_cistatic inline p4d_t *p4d_offset_lockless(pgd_t *pgdp, pgd_t pgd, unsigned long address) 12998c2ecf20Sopenharmony_ci{ 13008c2ecf20Sopenharmony_ci if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R1) 13018c2ecf20Sopenharmony_ci return (p4d_t *) pgd_deref(pgd) + p4d_index(address); 13028c2ecf20Sopenharmony_ci return (p4d_t *) pgdp; 13038c2ecf20Sopenharmony_ci} 13048c2ecf20Sopenharmony_ci#define p4d_offset_lockless p4d_offset_lockless 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_cistatic inline p4d_t *p4d_offset(pgd_t *pgdp, unsigned long address) 13078c2ecf20Sopenharmony_ci{ 13088c2ecf20Sopenharmony_ci return p4d_offset_lockless(pgdp, *pgdp, address); 13098c2ecf20Sopenharmony_ci} 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_cistatic inline pud_t *pud_offset_lockless(p4d_t *p4dp, p4d_t p4d, unsigned long address) 13128c2ecf20Sopenharmony_ci{ 13138c2ecf20Sopenharmony_ci if ((p4d_val(p4d) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R2) 13148c2ecf20Sopenharmony_ci return (pud_t *) p4d_deref(p4d) + pud_index(address); 13158c2ecf20Sopenharmony_ci return (pud_t *) p4dp; 13168c2ecf20Sopenharmony_ci} 13178c2ecf20Sopenharmony_ci#define pud_offset_lockless pud_offset_lockless 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_cistatic inline pud_t *pud_offset(p4d_t *p4dp, unsigned long address) 13208c2ecf20Sopenharmony_ci{ 13218c2ecf20Sopenharmony_ci return pud_offset_lockless(p4dp, *p4dp, address); 13228c2ecf20Sopenharmony_ci} 13238c2ecf20Sopenharmony_ci#define pud_offset pud_offset 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_cistatic inline pmd_t *pmd_offset_lockless(pud_t *pudp, pud_t pud, unsigned long address) 13268c2ecf20Sopenharmony_ci{ 13278c2ecf20Sopenharmony_ci if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R3) 13288c2ecf20Sopenharmony_ci return (pmd_t *) pud_deref(pud) + pmd_index(address); 13298c2ecf20Sopenharmony_ci return (pmd_t *) pudp; 13308c2ecf20Sopenharmony_ci} 13318c2ecf20Sopenharmony_ci#define pmd_offset_lockless pmd_offset_lockless 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_cistatic inline pmd_t *pmd_offset(pud_t *pudp, unsigned long address) 13348c2ecf20Sopenharmony_ci{ 13358c2ecf20Sopenharmony_ci return pmd_offset_lockless(pudp, *pudp, address); 13368c2ecf20Sopenharmony_ci} 13378c2ecf20Sopenharmony_ci#define pmd_offset pmd_offset 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_cistatic inline unsigned long pmd_page_vaddr(pmd_t pmd) 13408c2ecf20Sopenharmony_ci{ 13418c2ecf20Sopenharmony_ci return (unsigned long) pmd_deref(pmd); 13428c2ecf20Sopenharmony_ci} 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_cistatic inline bool gup_fast_permitted(unsigned long start, unsigned long end) 13458c2ecf20Sopenharmony_ci{ 13468c2ecf20Sopenharmony_ci return end <= current->mm->context.asce_limit; 13478c2ecf20Sopenharmony_ci} 13488c2ecf20Sopenharmony_ci#define gup_fast_permitted gup_fast_permitted 13498c2ecf20Sopenharmony_ci 13508c2ecf20Sopenharmony_ci#define pfn_pte(pfn,pgprot) mk_pte_phys(__pa((pfn) << PAGE_SHIFT),(pgprot)) 13518c2ecf20Sopenharmony_ci#define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT) 13528c2ecf20Sopenharmony_ci#define pte_page(x) pfn_to_page(pte_pfn(x)) 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci#define pmd_page(pmd) pfn_to_page(pmd_pfn(pmd)) 13558c2ecf20Sopenharmony_ci#define pud_page(pud) pfn_to_page(pud_pfn(pud)) 13568c2ecf20Sopenharmony_ci#define p4d_page(p4d) pfn_to_page(p4d_pfn(p4d)) 13578c2ecf20Sopenharmony_ci#define pgd_page(pgd) pfn_to_page(pgd_pfn(pgd)) 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_cistatic inline pmd_t pmd_wrprotect(pmd_t pmd) 13608c2ecf20Sopenharmony_ci{ 13618c2ecf20Sopenharmony_ci pmd_val(pmd) &= ~_SEGMENT_ENTRY_WRITE; 13628c2ecf20Sopenharmony_ci pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT; 13638c2ecf20Sopenharmony_ci return pmd; 13648c2ecf20Sopenharmony_ci} 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkwrite(pmd_t pmd) 13678c2ecf20Sopenharmony_ci{ 13688c2ecf20Sopenharmony_ci pmd_val(pmd) |= _SEGMENT_ENTRY_WRITE; 13698c2ecf20Sopenharmony_ci if (pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY) 13708c2ecf20Sopenharmony_ci pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT; 13718c2ecf20Sopenharmony_ci return pmd; 13728c2ecf20Sopenharmony_ci} 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkclean(pmd_t pmd) 13758c2ecf20Sopenharmony_ci{ 13768c2ecf20Sopenharmony_ci pmd_val(pmd) &= ~_SEGMENT_ENTRY_DIRTY; 13778c2ecf20Sopenharmony_ci pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT; 13788c2ecf20Sopenharmony_ci return pmd; 13798c2ecf20Sopenharmony_ci} 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkdirty(pmd_t pmd) 13828c2ecf20Sopenharmony_ci{ 13838c2ecf20Sopenharmony_ci pmd_val(pmd) |= _SEGMENT_ENTRY_DIRTY | _SEGMENT_ENTRY_SOFT_DIRTY; 13848c2ecf20Sopenharmony_ci if (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) 13858c2ecf20Sopenharmony_ci pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT; 13868c2ecf20Sopenharmony_ci return pmd; 13878c2ecf20Sopenharmony_ci} 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_cistatic inline pud_t pud_wrprotect(pud_t pud) 13908c2ecf20Sopenharmony_ci{ 13918c2ecf20Sopenharmony_ci pud_val(pud) &= ~_REGION3_ENTRY_WRITE; 13928c2ecf20Sopenharmony_ci pud_val(pud) |= _REGION_ENTRY_PROTECT; 13938c2ecf20Sopenharmony_ci return pud; 13948c2ecf20Sopenharmony_ci} 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_cistatic inline pud_t pud_mkwrite(pud_t pud) 13978c2ecf20Sopenharmony_ci{ 13988c2ecf20Sopenharmony_ci pud_val(pud) |= _REGION3_ENTRY_WRITE; 13998c2ecf20Sopenharmony_ci if (pud_val(pud) & _REGION3_ENTRY_DIRTY) 14008c2ecf20Sopenharmony_ci pud_val(pud) &= ~_REGION_ENTRY_PROTECT; 14018c2ecf20Sopenharmony_ci return pud; 14028c2ecf20Sopenharmony_ci} 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_cistatic inline pud_t pud_mkclean(pud_t pud) 14058c2ecf20Sopenharmony_ci{ 14068c2ecf20Sopenharmony_ci pud_val(pud) &= ~_REGION3_ENTRY_DIRTY; 14078c2ecf20Sopenharmony_ci pud_val(pud) |= _REGION_ENTRY_PROTECT; 14088c2ecf20Sopenharmony_ci return pud; 14098c2ecf20Sopenharmony_ci} 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_cistatic inline pud_t pud_mkdirty(pud_t pud) 14128c2ecf20Sopenharmony_ci{ 14138c2ecf20Sopenharmony_ci pud_val(pud) |= _REGION3_ENTRY_DIRTY | _REGION3_ENTRY_SOFT_DIRTY; 14148c2ecf20Sopenharmony_ci if (pud_val(pud) & _REGION3_ENTRY_WRITE) 14158c2ecf20Sopenharmony_ci pud_val(pud) &= ~_REGION_ENTRY_PROTECT; 14168c2ecf20Sopenharmony_ci return pud; 14178c2ecf20Sopenharmony_ci} 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLB_PAGE) 14208c2ecf20Sopenharmony_cistatic inline unsigned long massage_pgprot_pmd(pgprot_t pgprot) 14218c2ecf20Sopenharmony_ci{ 14228c2ecf20Sopenharmony_ci /* 14238c2ecf20Sopenharmony_ci * pgprot is PAGE_NONE, PAGE_RO, PAGE_RX, PAGE_RW or PAGE_RWX 14248c2ecf20Sopenharmony_ci * (see __Pxxx / __Sxxx). Convert to segment table entry format. 14258c2ecf20Sopenharmony_ci */ 14268c2ecf20Sopenharmony_ci if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE)) 14278c2ecf20Sopenharmony_ci return pgprot_val(SEGMENT_NONE); 14288c2ecf20Sopenharmony_ci if (pgprot_val(pgprot) == pgprot_val(PAGE_RO)) 14298c2ecf20Sopenharmony_ci return pgprot_val(SEGMENT_RO); 14308c2ecf20Sopenharmony_ci if (pgprot_val(pgprot) == pgprot_val(PAGE_RX)) 14318c2ecf20Sopenharmony_ci return pgprot_val(SEGMENT_RX); 14328c2ecf20Sopenharmony_ci if (pgprot_val(pgprot) == pgprot_val(PAGE_RW)) 14338c2ecf20Sopenharmony_ci return pgprot_val(SEGMENT_RW); 14348c2ecf20Sopenharmony_ci return pgprot_val(SEGMENT_RWX); 14358c2ecf20Sopenharmony_ci} 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkyoung(pmd_t pmd) 14388c2ecf20Sopenharmony_ci{ 14398c2ecf20Sopenharmony_ci pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG; 14408c2ecf20Sopenharmony_ci if (pmd_val(pmd) & _SEGMENT_ENTRY_READ) 14418c2ecf20Sopenharmony_ci pmd_val(pmd) &= ~_SEGMENT_ENTRY_INVALID; 14428c2ecf20Sopenharmony_ci return pmd; 14438c2ecf20Sopenharmony_ci} 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkold(pmd_t pmd) 14468c2ecf20Sopenharmony_ci{ 14478c2ecf20Sopenharmony_ci pmd_val(pmd) &= ~_SEGMENT_ENTRY_YOUNG; 14488c2ecf20Sopenharmony_ci pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID; 14498c2ecf20Sopenharmony_ci return pmd; 14508c2ecf20Sopenharmony_ci} 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_cistatic inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) 14538c2ecf20Sopenharmony_ci{ 14548c2ecf20Sopenharmony_ci pmd_val(pmd) &= _SEGMENT_ENTRY_ORIGIN_LARGE | 14558c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_DIRTY | _SEGMENT_ENTRY_YOUNG | 14568c2ecf20Sopenharmony_ci _SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_SOFT_DIRTY; 14578c2ecf20Sopenharmony_ci pmd_val(pmd) |= massage_pgprot_pmd(newprot); 14588c2ecf20Sopenharmony_ci if (!(pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY)) 14598c2ecf20Sopenharmony_ci pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT; 14608c2ecf20Sopenharmony_ci if (!(pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG)) 14618c2ecf20Sopenharmony_ci pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID; 14628c2ecf20Sopenharmony_ci return pmd; 14638c2ecf20Sopenharmony_ci} 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_cistatic inline pmd_t mk_pmd_phys(unsigned long physpage, pgprot_t pgprot) 14668c2ecf20Sopenharmony_ci{ 14678c2ecf20Sopenharmony_ci pmd_t __pmd; 14688c2ecf20Sopenharmony_ci pmd_val(__pmd) = physpage + massage_pgprot_pmd(pgprot); 14698c2ecf20Sopenharmony_ci return __pmd; 14708c2ecf20Sopenharmony_ci} 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_ci#endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLB_PAGE */ 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_cistatic inline void __pmdp_csp(pmd_t *pmdp) 14758c2ecf20Sopenharmony_ci{ 14768c2ecf20Sopenharmony_ci csp((unsigned int *)pmdp + 1, pmd_val(*pmdp), 14778c2ecf20Sopenharmony_ci pmd_val(*pmdp) | _SEGMENT_ENTRY_INVALID); 14788c2ecf20Sopenharmony_ci} 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci#define IDTE_GLOBAL 0 14818c2ecf20Sopenharmony_ci#define IDTE_LOCAL 1 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci#define IDTE_PTOA 0x0800 14848c2ecf20Sopenharmony_ci#define IDTE_NODAT 0x1000 14858c2ecf20Sopenharmony_ci#define IDTE_GUEST_ASCE 0x2000 14868c2ecf20Sopenharmony_ci 14878c2ecf20Sopenharmony_cistatic __always_inline void __pmdp_idte(unsigned long addr, pmd_t *pmdp, 14888c2ecf20Sopenharmony_ci unsigned long opt, unsigned long asce, 14898c2ecf20Sopenharmony_ci int local) 14908c2ecf20Sopenharmony_ci{ 14918c2ecf20Sopenharmony_ci unsigned long sto; 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci sto = (unsigned long) pmdp - pmd_index(addr) * sizeof(pmd_t); 14948c2ecf20Sopenharmony_ci if (__builtin_constant_p(opt) && opt == 0) { 14958c2ecf20Sopenharmony_ci /* flush without guest asce */ 14968c2ecf20Sopenharmony_ci asm volatile( 14978c2ecf20Sopenharmony_ci " .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]" 14988c2ecf20Sopenharmony_ci : "+m" (*pmdp) 14998c2ecf20Sopenharmony_ci : [r1] "a" (sto), [r2] "a" ((addr & HPAGE_MASK)), 15008c2ecf20Sopenharmony_ci [m4] "i" (local) 15018c2ecf20Sopenharmony_ci : "cc" ); 15028c2ecf20Sopenharmony_ci } else { 15038c2ecf20Sopenharmony_ci /* flush with guest asce */ 15048c2ecf20Sopenharmony_ci asm volatile( 15058c2ecf20Sopenharmony_ci " .insn rrf,0xb98e0000,%[r1],%[r2],%[r3],%[m4]" 15068c2ecf20Sopenharmony_ci : "+m" (*pmdp) 15078c2ecf20Sopenharmony_ci : [r1] "a" (sto), [r2] "a" ((addr & HPAGE_MASK) | opt), 15088c2ecf20Sopenharmony_ci [r3] "a" (asce), [m4] "i" (local) 15098c2ecf20Sopenharmony_ci : "cc" ); 15108c2ecf20Sopenharmony_ci } 15118c2ecf20Sopenharmony_ci} 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_cistatic __always_inline void __pudp_idte(unsigned long addr, pud_t *pudp, 15148c2ecf20Sopenharmony_ci unsigned long opt, unsigned long asce, 15158c2ecf20Sopenharmony_ci int local) 15168c2ecf20Sopenharmony_ci{ 15178c2ecf20Sopenharmony_ci unsigned long r3o; 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci r3o = (unsigned long) pudp - pud_index(addr) * sizeof(pud_t); 15208c2ecf20Sopenharmony_ci r3o |= _ASCE_TYPE_REGION3; 15218c2ecf20Sopenharmony_ci if (__builtin_constant_p(opt) && opt == 0) { 15228c2ecf20Sopenharmony_ci /* flush without guest asce */ 15238c2ecf20Sopenharmony_ci asm volatile( 15248c2ecf20Sopenharmony_ci " .insn rrf,0xb98e0000,%[r1],%[r2],0,%[m4]" 15258c2ecf20Sopenharmony_ci : "+m" (*pudp) 15268c2ecf20Sopenharmony_ci : [r1] "a" (r3o), [r2] "a" ((addr & PUD_MASK)), 15278c2ecf20Sopenharmony_ci [m4] "i" (local) 15288c2ecf20Sopenharmony_ci : "cc"); 15298c2ecf20Sopenharmony_ci } else { 15308c2ecf20Sopenharmony_ci /* flush with guest asce */ 15318c2ecf20Sopenharmony_ci asm volatile( 15328c2ecf20Sopenharmony_ci " .insn rrf,0xb98e0000,%[r1],%[r2],%[r3],%[m4]" 15338c2ecf20Sopenharmony_ci : "+m" (*pudp) 15348c2ecf20Sopenharmony_ci : [r1] "a" (r3o), [r2] "a" ((addr & PUD_MASK) | opt), 15358c2ecf20Sopenharmony_ci [r3] "a" (asce), [m4] "i" (local) 15368c2ecf20Sopenharmony_ci : "cc" ); 15378c2ecf20Sopenharmony_ci } 15388c2ecf20Sopenharmony_ci} 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_cipmd_t pmdp_xchg_direct(struct mm_struct *, unsigned long, pmd_t *, pmd_t); 15418c2ecf20Sopenharmony_cipmd_t pmdp_xchg_lazy(struct mm_struct *, unsigned long, pmd_t *, pmd_t); 15428c2ecf20Sopenharmony_cipud_t pudp_xchg_direct(struct mm_struct *, unsigned long, pud_t *, pud_t); 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci#ifdef CONFIG_TRANSPARENT_HUGEPAGE 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PGTABLE_DEPOSIT 15478c2ecf20Sopenharmony_civoid pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, 15488c2ecf20Sopenharmony_ci pgtable_t pgtable); 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PGTABLE_WITHDRAW 15518c2ecf20Sopenharmony_cipgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp); 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS 15548c2ecf20Sopenharmony_cistatic inline int pmdp_set_access_flags(struct vm_area_struct *vma, 15558c2ecf20Sopenharmony_ci unsigned long addr, pmd_t *pmdp, 15568c2ecf20Sopenharmony_ci pmd_t entry, int dirty) 15578c2ecf20Sopenharmony_ci{ 15588c2ecf20Sopenharmony_ci VM_BUG_ON(addr & ~HPAGE_MASK); 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci entry = pmd_mkyoung(entry); 15618c2ecf20Sopenharmony_ci if (dirty) 15628c2ecf20Sopenharmony_ci entry = pmd_mkdirty(entry); 15638c2ecf20Sopenharmony_ci if (pmd_val(*pmdp) == pmd_val(entry)) 15648c2ecf20Sopenharmony_ci return 0; 15658c2ecf20Sopenharmony_ci pmdp_xchg_direct(vma->vm_mm, addr, pmdp, entry); 15668c2ecf20Sopenharmony_ci return 1; 15678c2ecf20Sopenharmony_ci} 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG 15708c2ecf20Sopenharmony_cistatic inline int pmdp_test_and_clear_young(struct vm_area_struct *vma, 15718c2ecf20Sopenharmony_ci unsigned long addr, pmd_t *pmdp) 15728c2ecf20Sopenharmony_ci{ 15738c2ecf20Sopenharmony_ci pmd_t pmd = *pmdp; 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci pmd = pmdp_xchg_direct(vma->vm_mm, addr, pmdp, pmd_mkold(pmd)); 15768c2ecf20Sopenharmony_ci return pmd_young(pmd); 15778c2ecf20Sopenharmony_ci} 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_CLEAR_YOUNG_FLUSH 15808c2ecf20Sopenharmony_cistatic inline int pmdp_clear_flush_young(struct vm_area_struct *vma, 15818c2ecf20Sopenharmony_ci unsigned long addr, pmd_t *pmdp) 15828c2ecf20Sopenharmony_ci{ 15838c2ecf20Sopenharmony_ci VM_BUG_ON(addr & ~HPAGE_MASK); 15848c2ecf20Sopenharmony_ci return pmdp_test_and_clear_young(vma, addr, pmdp); 15858c2ecf20Sopenharmony_ci} 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_cistatic inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, 15888c2ecf20Sopenharmony_ci pmd_t *pmdp, pmd_t entry) 15898c2ecf20Sopenharmony_ci{ 15908c2ecf20Sopenharmony_ci if (!MACHINE_HAS_NX) 15918c2ecf20Sopenharmony_ci pmd_val(entry) &= ~_SEGMENT_ENTRY_NOEXEC; 15928c2ecf20Sopenharmony_ci *pmdp = entry; 15938c2ecf20Sopenharmony_ci} 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkhuge(pmd_t pmd) 15968c2ecf20Sopenharmony_ci{ 15978c2ecf20Sopenharmony_ci pmd_val(pmd) |= _SEGMENT_ENTRY_LARGE; 15988c2ecf20Sopenharmony_ci pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG; 15998c2ecf20Sopenharmony_ci pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT; 16008c2ecf20Sopenharmony_ci return pmd; 16018c2ecf20Sopenharmony_ci} 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR 16048c2ecf20Sopenharmony_cistatic inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, 16058c2ecf20Sopenharmony_ci unsigned long addr, pmd_t *pmdp) 16068c2ecf20Sopenharmony_ci{ 16078c2ecf20Sopenharmony_ci return pmdp_xchg_direct(mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_EMPTY)); 16088c2ecf20Sopenharmony_ci} 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR_FULL 16118c2ecf20Sopenharmony_cistatic inline pmd_t pmdp_huge_get_and_clear_full(struct vm_area_struct *vma, 16128c2ecf20Sopenharmony_ci unsigned long addr, 16138c2ecf20Sopenharmony_ci pmd_t *pmdp, int full) 16148c2ecf20Sopenharmony_ci{ 16158c2ecf20Sopenharmony_ci if (full) { 16168c2ecf20Sopenharmony_ci pmd_t pmd = *pmdp; 16178c2ecf20Sopenharmony_ci *pmdp = __pmd(_SEGMENT_ENTRY_EMPTY); 16188c2ecf20Sopenharmony_ci return pmd; 16198c2ecf20Sopenharmony_ci } 16208c2ecf20Sopenharmony_ci return pmdp_xchg_lazy(vma->vm_mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_EMPTY)); 16218c2ecf20Sopenharmony_ci} 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_HUGE_CLEAR_FLUSH 16248c2ecf20Sopenharmony_cistatic inline pmd_t pmdp_huge_clear_flush(struct vm_area_struct *vma, 16258c2ecf20Sopenharmony_ci unsigned long addr, pmd_t *pmdp) 16268c2ecf20Sopenharmony_ci{ 16278c2ecf20Sopenharmony_ci return pmdp_huge_get_and_clear(vma->vm_mm, addr, pmdp); 16288c2ecf20Sopenharmony_ci} 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_INVALIDATE 16318c2ecf20Sopenharmony_cistatic inline pmd_t pmdp_invalidate(struct vm_area_struct *vma, 16328c2ecf20Sopenharmony_ci unsigned long addr, pmd_t *pmdp) 16338c2ecf20Sopenharmony_ci{ 16348c2ecf20Sopenharmony_ci pmd_t pmd = __pmd(pmd_val(*pmdp) | _SEGMENT_ENTRY_INVALID); 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci return pmdp_xchg_direct(vma->vm_mm, addr, pmdp, pmd); 16378c2ecf20Sopenharmony_ci} 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_SET_WRPROTECT 16408c2ecf20Sopenharmony_cistatic inline void pmdp_set_wrprotect(struct mm_struct *mm, 16418c2ecf20Sopenharmony_ci unsigned long addr, pmd_t *pmdp) 16428c2ecf20Sopenharmony_ci{ 16438c2ecf20Sopenharmony_ci pmd_t pmd = *pmdp; 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci if (pmd_write(pmd)) 16468c2ecf20Sopenharmony_ci pmd = pmdp_xchg_lazy(mm, addr, pmdp, pmd_wrprotect(pmd)); 16478c2ecf20Sopenharmony_ci} 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_cistatic inline pmd_t pmdp_collapse_flush(struct vm_area_struct *vma, 16508c2ecf20Sopenharmony_ci unsigned long address, 16518c2ecf20Sopenharmony_ci pmd_t *pmdp) 16528c2ecf20Sopenharmony_ci{ 16538c2ecf20Sopenharmony_ci return pmdp_huge_get_and_clear(vma->vm_mm, address, pmdp); 16548c2ecf20Sopenharmony_ci} 16558c2ecf20Sopenharmony_ci#define pmdp_collapse_flush pmdp_collapse_flush 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci#define pfn_pmd(pfn, pgprot) mk_pmd_phys(__pa((pfn) << PAGE_SHIFT), (pgprot)) 16588c2ecf20Sopenharmony_ci#define mk_pmd(page, pgprot) pfn_pmd(page_to_pfn(page), (pgprot)) 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_cistatic inline int pmd_trans_huge(pmd_t pmd) 16618c2ecf20Sopenharmony_ci{ 16628c2ecf20Sopenharmony_ci return pmd_val(pmd) & _SEGMENT_ENTRY_LARGE; 16638c2ecf20Sopenharmony_ci} 16648c2ecf20Sopenharmony_ci 16658c2ecf20Sopenharmony_ci#define has_transparent_hugepage has_transparent_hugepage 16668c2ecf20Sopenharmony_cistatic inline int has_transparent_hugepage(void) 16678c2ecf20Sopenharmony_ci{ 16688c2ecf20Sopenharmony_ci return MACHINE_HAS_EDAT1 ? 1 : 0; 16698c2ecf20Sopenharmony_ci} 16708c2ecf20Sopenharmony_ci#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci/* 16738c2ecf20Sopenharmony_ci * 64 bit swap entry format: 16748c2ecf20Sopenharmony_ci * A page-table entry has some bits we have to treat in a special way. 16758c2ecf20Sopenharmony_ci * Bits 52 and bit 55 have to be zero, otherwise a specification 16768c2ecf20Sopenharmony_ci * exception will occur instead of a page translation exception. The 16778c2ecf20Sopenharmony_ci * specification exception has the bad habit not to store necessary 16788c2ecf20Sopenharmony_ci * information in the lowcore. 16798c2ecf20Sopenharmony_ci * Bits 54 and 63 are used to indicate the page type. 16808c2ecf20Sopenharmony_ci * A swap pte is indicated by bit pattern (pte & 0x201) == 0x200 16818c2ecf20Sopenharmony_ci * This leaves the bits 0-51 and bits 56-62 to store type and offset. 16828c2ecf20Sopenharmony_ci * We use the 5 bits from 57-61 for the type and the 52 bits from 0-51 16838c2ecf20Sopenharmony_ci * for the offset. 16848c2ecf20Sopenharmony_ci * | offset |01100|type |00| 16858c2ecf20Sopenharmony_ci * |0000000000111111111122222222223333333333444444444455|55555|55566|66| 16868c2ecf20Sopenharmony_ci * |0123456789012345678901234567890123456789012345678901|23456|78901|23| 16878c2ecf20Sopenharmony_ci */ 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci#define __SWP_OFFSET_MASK ((1UL << 52) - 1) 16908c2ecf20Sopenharmony_ci#define __SWP_OFFSET_SHIFT 12 16918c2ecf20Sopenharmony_ci#define __SWP_TYPE_MASK ((1UL << 5) - 1) 16928c2ecf20Sopenharmony_ci#define __SWP_TYPE_SHIFT 2 16938c2ecf20Sopenharmony_ci 16948c2ecf20Sopenharmony_cistatic inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) 16958c2ecf20Sopenharmony_ci{ 16968c2ecf20Sopenharmony_ci pte_t pte; 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci pte_val(pte) = _PAGE_INVALID | _PAGE_PROTECT; 16998c2ecf20Sopenharmony_ci pte_val(pte) |= (offset & __SWP_OFFSET_MASK) << __SWP_OFFSET_SHIFT; 17008c2ecf20Sopenharmony_ci pte_val(pte) |= (type & __SWP_TYPE_MASK) << __SWP_TYPE_SHIFT; 17018c2ecf20Sopenharmony_ci return pte; 17028c2ecf20Sopenharmony_ci} 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_cistatic inline unsigned long __swp_type(swp_entry_t entry) 17058c2ecf20Sopenharmony_ci{ 17068c2ecf20Sopenharmony_ci return (entry.val >> __SWP_TYPE_SHIFT) & __SWP_TYPE_MASK; 17078c2ecf20Sopenharmony_ci} 17088c2ecf20Sopenharmony_ci 17098c2ecf20Sopenharmony_cistatic inline unsigned long __swp_offset(swp_entry_t entry) 17108c2ecf20Sopenharmony_ci{ 17118c2ecf20Sopenharmony_ci return (entry.val >> __SWP_OFFSET_SHIFT) & __SWP_OFFSET_MASK; 17128c2ecf20Sopenharmony_ci} 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_cistatic inline swp_entry_t __swp_entry(unsigned long type, unsigned long offset) 17158c2ecf20Sopenharmony_ci{ 17168c2ecf20Sopenharmony_ci return (swp_entry_t) { pte_val(mk_swap_pte(type, offset)) }; 17178c2ecf20Sopenharmony_ci} 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_ci#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) 17208c2ecf20Sopenharmony_ci#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci#define kern_addr_valid(addr) (1) 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ciextern int vmem_add_mapping(unsigned long start, unsigned long size); 17258c2ecf20Sopenharmony_ciextern void vmem_remove_mapping(unsigned long start, unsigned long size); 17268c2ecf20Sopenharmony_ciextern int s390_enable_sie(void); 17278c2ecf20Sopenharmony_ciextern int s390_enable_skey(void); 17288c2ecf20Sopenharmony_ciextern void s390_reset_cmma(struct mm_struct *mm); 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_ci/* s390 has a private copy of get unmapped area to deal with cache synonyms */ 17318c2ecf20Sopenharmony_ci#define HAVE_ARCH_UNMAPPED_AREA 17328c2ecf20Sopenharmony_ci#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ci#endif /* _S390_PAGE_H */ 1735