18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * pgtable.h: SpitFire page table operations. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu) 68c2ecf20Sopenharmony_ci * Copyright 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#ifndef _SPARC64_PGTABLE_H 108c2ecf20Sopenharmony_ci#define _SPARC64_PGTABLE_H 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci/* This file contains the functions and defines necessary to modify and use 138c2ecf20Sopenharmony_ci * the SpitFire page tables. 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <asm-generic/pgtable-nop4d.h> 178c2ecf20Sopenharmony_ci#include <linux/compiler.h> 188c2ecf20Sopenharmony_ci#include <linux/const.h> 198c2ecf20Sopenharmony_ci#include <asm/types.h> 208c2ecf20Sopenharmony_ci#include <asm/spitfire.h> 218c2ecf20Sopenharmony_ci#include <asm/asi.h> 228c2ecf20Sopenharmony_ci#include <asm/adi.h> 238c2ecf20Sopenharmony_ci#include <asm/page.h> 248c2ecf20Sopenharmony_ci#include <asm/processor.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB). 278c2ecf20Sopenharmony_ci * The page copy blockops can use 0x6000000 to 0x8000000. 288c2ecf20Sopenharmony_ci * The 8K TSB is mapped in the 0x8000000 to 0x8400000 range. 298c2ecf20Sopenharmony_ci * The 4M TSB is mapped in the 0x8400000 to 0x8800000 range. 308c2ecf20Sopenharmony_ci * The PROM resides in an area spanning 0xf0000000 to 0x100000000. 318c2ecf20Sopenharmony_ci * The vmalloc area spans 0x100000000 to 0x200000000. 328c2ecf20Sopenharmony_ci * Since modules need to be in the lowest 32-bits of the address space, 338c2ecf20Sopenharmony_ci * we place them right before the OBP area from 0x10000000 to 0xf0000000. 348c2ecf20Sopenharmony_ci * There is a single static kernel PMD which maps from 0x0 to address 358c2ecf20Sopenharmony_ci * 0x400000000. 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci#define TLBTEMP_BASE _AC(0x0000000006000000,UL) 388c2ecf20Sopenharmony_ci#define TSBMAP_8K_BASE _AC(0x0000000008000000,UL) 398c2ecf20Sopenharmony_ci#define TSBMAP_4M_BASE _AC(0x0000000008400000,UL) 408c2ecf20Sopenharmony_ci#define MODULES_VADDR _AC(0x0000000010000000,UL) 418c2ecf20Sopenharmony_ci#define MODULES_LEN _AC(0x00000000e0000000,UL) 428c2ecf20Sopenharmony_ci#define MODULES_END _AC(0x00000000f0000000,UL) 438c2ecf20Sopenharmony_ci#define LOW_OBP_ADDRESS _AC(0x00000000f0000000,UL) 448c2ecf20Sopenharmony_ci#define HI_OBP_ADDRESS _AC(0x0000000100000000,UL) 458c2ecf20Sopenharmony_ci#define VMALLOC_START _AC(0x0000000100000000,UL) 468c2ecf20Sopenharmony_ci#define VMEMMAP_BASE VMALLOC_END 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* PMD_SHIFT determines the size of the area a second-level page 498c2ecf20Sopenharmony_ci * table can map 508c2ecf20Sopenharmony_ci */ 518c2ecf20Sopenharmony_ci#define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT-3)) 528c2ecf20Sopenharmony_ci#define PMD_SIZE (_AC(1,UL) << PMD_SHIFT) 538c2ecf20Sopenharmony_ci#define PMD_MASK (~(PMD_SIZE-1)) 548c2ecf20Sopenharmony_ci#define PMD_BITS (PAGE_SHIFT - 3) 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* PUD_SHIFT determines the size of the area a third-level page 578c2ecf20Sopenharmony_ci * table can map 588c2ecf20Sopenharmony_ci */ 598c2ecf20Sopenharmony_ci#define PUD_SHIFT (PMD_SHIFT + PMD_BITS) 608c2ecf20Sopenharmony_ci#define PUD_SIZE (_AC(1,UL) << PUD_SHIFT) 618c2ecf20Sopenharmony_ci#define PUD_MASK (~(PUD_SIZE-1)) 628c2ecf20Sopenharmony_ci#define PUD_BITS (PAGE_SHIFT - 3) 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* PGDIR_SHIFT determines what a fourth-level page table entry can map */ 658c2ecf20Sopenharmony_ci#define PGDIR_SHIFT (PUD_SHIFT + PUD_BITS) 668c2ecf20Sopenharmony_ci#define PGDIR_SIZE (_AC(1,UL) << PGDIR_SHIFT) 678c2ecf20Sopenharmony_ci#define PGDIR_MASK (~(PGDIR_SIZE-1)) 688c2ecf20Sopenharmony_ci#define PGDIR_BITS (PAGE_SHIFT - 3) 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci#if (MAX_PHYS_ADDRESS_BITS > PGDIR_SHIFT + PGDIR_BITS) 718c2ecf20Sopenharmony_ci#error MAX_PHYS_ADDRESS_BITS exceeds what kernel page tables can support 728c2ecf20Sopenharmony_ci#endif 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci#if (PGDIR_SHIFT + PGDIR_BITS) != 53 758c2ecf20Sopenharmony_ci#error Page table parameters do not cover virtual address space properly. 768c2ecf20Sopenharmony_ci#endif 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#if (PMD_SHIFT != HPAGE_SHIFT) 798c2ecf20Sopenharmony_ci#error PMD_SHIFT must equal HPAGE_SHIFT for transparent huge pages. 808c2ecf20Sopenharmony_ci#endif 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ciextern unsigned long VMALLOC_END; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci#define vmemmap ((struct page *)VMEMMAP_BASE) 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci#include <linux/sched.h> 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cibool kern_addr_valid(unsigned long addr); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci/* Entries per page directory level. */ 938c2ecf20Sopenharmony_ci#define PTRS_PER_PTE (1UL << (PAGE_SHIFT-3)) 948c2ecf20Sopenharmony_ci#define PTRS_PER_PMD (1UL << PMD_BITS) 958c2ecf20Sopenharmony_ci#define PTRS_PER_PUD (1UL << PUD_BITS) 968c2ecf20Sopenharmony_ci#define PTRS_PER_PGD (1UL << PGDIR_BITS) 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci/* Kernel has a separate 44bit address space. */ 998c2ecf20Sopenharmony_ci#define FIRST_USER_ADDRESS 0UL 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci#define pmd_ERROR(e) \ 1028c2ecf20Sopenharmony_ci pr_err("%s:%d: bad pmd %p(%016lx) seen at (%pS)\n", \ 1038c2ecf20Sopenharmony_ci __FILE__, __LINE__, &(e), pmd_val(e), __builtin_return_address(0)) 1048c2ecf20Sopenharmony_ci#define pud_ERROR(e) \ 1058c2ecf20Sopenharmony_ci pr_err("%s:%d: bad pud %p(%016lx) seen at (%pS)\n", \ 1068c2ecf20Sopenharmony_ci __FILE__, __LINE__, &(e), pud_val(e), __builtin_return_address(0)) 1078c2ecf20Sopenharmony_ci#define pgd_ERROR(e) \ 1088c2ecf20Sopenharmony_ci pr_err("%s:%d: bad pgd %p(%016lx) seen at (%pS)\n", \ 1098c2ecf20Sopenharmony_ci __FILE__, __LINE__, &(e), pgd_val(e), __builtin_return_address(0)) 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci#endif /* !(__ASSEMBLY__) */ 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci/* PTE bits which are the same in SUN4U and SUN4V format. */ 1148c2ecf20Sopenharmony_ci#define _PAGE_VALID _AC(0x8000000000000000,UL) /* Valid TTE */ 1158c2ecf20Sopenharmony_ci#define _PAGE_R _AC(0x8000000000000000,UL) /* Keep ref bit uptodate*/ 1168c2ecf20Sopenharmony_ci#define _PAGE_SPECIAL _AC(0x0200000000000000,UL) /* Special page */ 1178c2ecf20Sopenharmony_ci#define _PAGE_PMD_HUGE _AC(0x0100000000000000,UL) /* Huge page */ 1188c2ecf20Sopenharmony_ci#define _PAGE_PUD_HUGE _PAGE_PMD_HUGE 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci/* SUN4U pte bits... */ 1218c2ecf20Sopenharmony_ci#define _PAGE_SZ4MB_4U _AC(0x6000000000000000,UL) /* 4MB Page */ 1228c2ecf20Sopenharmony_ci#define _PAGE_SZ512K_4U _AC(0x4000000000000000,UL) /* 512K Page */ 1238c2ecf20Sopenharmony_ci#define _PAGE_SZ64K_4U _AC(0x2000000000000000,UL) /* 64K Page */ 1248c2ecf20Sopenharmony_ci#define _PAGE_SZ8K_4U _AC(0x0000000000000000,UL) /* 8K Page */ 1258c2ecf20Sopenharmony_ci#define _PAGE_NFO_4U _AC(0x1000000000000000,UL) /* No Fault Only */ 1268c2ecf20Sopenharmony_ci#define _PAGE_IE_4U _AC(0x0800000000000000,UL) /* Invert Endianness */ 1278c2ecf20Sopenharmony_ci#define _PAGE_SOFT2_4U _AC(0x07FC000000000000,UL) /* Software bits, set 2 */ 1288c2ecf20Sopenharmony_ci#define _PAGE_SPECIAL_4U _AC(0x0200000000000000,UL) /* Special page */ 1298c2ecf20Sopenharmony_ci#define _PAGE_PMD_HUGE_4U _AC(0x0100000000000000,UL) /* Huge page */ 1308c2ecf20Sopenharmony_ci#define _PAGE_RES1_4U _AC(0x0002000000000000,UL) /* Reserved */ 1318c2ecf20Sopenharmony_ci#define _PAGE_SZ32MB_4U _AC(0x0001000000000000,UL) /* (Panther) 32MB page */ 1328c2ecf20Sopenharmony_ci#define _PAGE_SZ256MB_4U _AC(0x2001000000000000,UL) /* (Panther) 256MB page */ 1338c2ecf20Sopenharmony_ci#define _PAGE_SZALL_4U _AC(0x6001000000000000,UL) /* All pgsz bits */ 1348c2ecf20Sopenharmony_ci#define _PAGE_SN_4U _AC(0x0000800000000000,UL) /* (Cheetah) Snoop */ 1358c2ecf20Sopenharmony_ci#define _PAGE_RES2_4U _AC(0x0000780000000000,UL) /* Reserved */ 1368c2ecf20Sopenharmony_ci#define _PAGE_PADDR_4U _AC(0x000007FFFFFFE000,UL) /* (Cheetah) pa[42:13] */ 1378c2ecf20Sopenharmony_ci#define _PAGE_SOFT_4U _AC(0x0000000000001F80,UL) /* Software bits: */ 1388c2ecf20Sopenharmony_ci#define _PAGE_EXEC_4U _AC(0x0000000000001000,UL) /* Executable SW bit */ 1398c2ecf20Sopenharmony_ci#define _PAGE_MODIFIED_4U _AC(0x0000000000000800,UL) /* Modified (dirty) */ 1408c2ecf20Sopenharmony_ci#define _PAGE_ACCESSED_4U _AC(0x0000000000000400,UL) /* Accessed (ref'd) */ 1418c2ecf20Sopenharmony_ci#define _PAGE_READ_4U _AC(0x0000000000000200,UL) /* Readable SW Bit */ 1428c2ecf20Sopenharmony_ci#define _PAGE_WRITE_4U _AC(0x0000000000000100,UL) /* Writable SW Bit */ 1438c2ecf20Sopenharmony_ci#define _PAGE_PRESENT_4U _AC(0x0000000000000080,UL) /* Present */ 1448c2ecf20Sopenharmony_ci#define _PAGE_L_4U _AC(0x0000000000000040,UL) /* Locked TTE */ 1458c2ecf20Sopenharmony_ci#define _PAGE_CP_4U _AC(0x0000000000000020,UL) /* Cacheable in P-Cache */ 1468c2ecf20Sopenharmony_ci#define _PAGE_CV_4U _AC(0x0000000000000010,UL) /* Cacheable in V-Cache */ 1478c2ecf20Sopenharmony_ci#define _PAGE_E_4U _AC(0x0000000000000008,UL) /* side-Effect */ 1488c2ecf20Sopenharmony_ci#define _PAGE_P_4U _AC(0x0000000000000004,UL) /* Privileged Page */ 1498c2ecf20Sopenharmony_ci#define _PAGE_W_4U _AC(0x0000000000000002,UL) /* Writable */ 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci/* SUN4V pte bits... */ 1528c2ecf20Sopenharmony_ci#define _PAGE_NFO_4V _AC(0x4000000000000000,UL) /* No Fault Only */ 1538c2ecf20Sopenharmony_ci#define _PAGE_SOFT2_4V _AC(0x3F00000000000000,UL) /* Software bits, set 2 */ 1548c2ecf20Sopenharmony_ci#define _PAGE_MODIFIED_4V _AC(0x2000000000000000,UL) /* Modified (dirty) */ 1558c2ecf20Sopenharmony_ci#define _PAGE_ACCESSED_4V _AC(0x1000000000000000,UL) /* Accessed (ref'd) */ 1568c2ecf20Sopenharmony_ci#define _PAGE_READ_4V _AC(0x0800000000000000,UL) /* Readable SW Bit */ 1578c2ecf20Sopenharmony_ci#define _PAGE_WRITE_4V _AC(0x0400000000000000,UL) /* Writable SW Bit */ 1588c2ecf20Sopenharmony_ci#define _PAGE_SPECIAL_4V _AC(0x0200000000000000,UL) /* Special page */ 1598c2ecf20Sopenharmony_ci#define _PAGE_PMD_HUGE_4V _AC(0x0100000000000000,UL) /* Huge page */ 1608c2ecf20Sopenharmony_ci#define _PAGE_PADDR_4V _AC(0x00FFFFFFFFFFE000,UL) /* paddr[55:13] */ 1618c2ecf20Sopenharmony_ci#define _PAGE_IE_4V _AC(0x0000000000001000,UL) /* Invert Endianness */ 1628c2ecf20Sopenharmony_ci#define _PAGE_E_4V _AC(0x0000000000000800,UL) /* side-Effect */ 1638c2ecf20Sopenharmony_ci#define _PAGE_CP_4V _AC(0x0000000000000400,UL) /* Cacheable in P-Cache */ 1648c2ecf20Sopenharmony_ci#define _PAGE_CV_4V _AC(0x0000000000000200,UL) /* Cacheable in V-Cache */ 1658c2ecf20Sopenharmony_ci/* Bit 9 is used to enable MCD corruption detection instead on M7 */ 1668c2ecf20Sopenharmony_ci#define _PAGE_MCD_4V _AC(0x0000000000000200,UL) /* Memory Corruption */ 1678c2ecf20Sopenharmony_ci#define _PAGE_P_4V _AC(0x0000000000000100,UL) /* Privileged Page */ 1688c2ecf20Sopenharmony_ci#define _PAGE_EXEC_4V _AC(0x0000000000000080,UL) /* Executable Page */ 1698c2ecf20Sopenharmony_ci#define _PAGE_W_4V _AC(0x0000000000000040,UL) /* Writable */ 1708c2ecf20Sopenharmony_ci#define _PAGE_SOFT_4V _AC(0x0000000000000030,UL) /* Software bits */ 1718c2ecf20Sopenharmony_ci#define _PAGE_PRESENT_4V _AC(0x0000000000000010,UL) /* Present */ 1728c2ecf20Sopenharmony_ci#define _PAGE_RESV_4V _AC(0x0000000000000008,UL) /* Reserved */ 1738c2ecf20Sopenharmony_ci#define _PAGE_SZ16GB_4V _AC(0x0000000000000007,UL) /* 16GB Page */ 1748c2ecf20Sopenharmony_ci#define _PAGE_SZ2GB_4V _AC(0x0000000000000006,UL) /* 2GB Page */ 1758c2ecf20Sopenharmony_ci#define _PAGE_SZ256MB_4V _AC(0x0000000000000005,UL) /* 256MB Page */ 1768c2ecf20Sopenharmony_ci#define _PAGE_SZ32MB_4V _AC(0x0000000000000004,UL) /* 32MB Page */ 1778c2ecf20Sopenharmony_ci#define _PAGE_SZ4MB_4V _AC(0x0000000000000003,UL) /* 4MB Page */ 1788c2ecf20Sopenharmony_ci#define _PAGE_SZ512K_4V _AC(0x0000000000000002,UL) /* 512K Page */ 1798c2ecf20Sopenharmony_ci#define _PAGE_SZ64K_4V _AC(0x0000000000000001,UL) /* 64K Page */ 1808c2ecf20Sopenharmony_ci#define _PAGE_SZ8K_4V _AC(0x0000000000000000,UL) /* 8K Page */ 1818c2ecf20Sopenharmony_ci#define _PAGE_SZALL_4V _AC(0x0000000000000007,UL) /* All pgsz bits */ 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci#define _PAGE_SZBITS_4U _PAGE_SZ8K_4U 1848c2ecf20Sopenharmony_ci#define _PAGE_SZBITS_4V _PAGE_SZ8K_4V 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci#if REAL_HPAGE_SHIFT != 22 1878c2ecf20Sopenharmony_ci#error REAL_HPAGE_SHIFT and _PAGE_SZHUGE_foo must match up 1888c2ecf20Sopenharmony_ci#endif 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci#define _PAGE_SZHUGE_4U _PAGE_SZ4MB_4U 1918c2ecf20Sopenharmony_ci#define _PAGE_SZHUGE_4V _PAGE_SZ4MB_4V 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci/* These are actually filled in at boot time by sun4{u,v}_pgprot_init() */ 1948c2ecf20Sopenharmony_ci#define __P000 __pgprot(0) 1958c2ecf20Sopenharmony_ci#define __P001 __pgprot(0) 1968c2ecf20Sopenharmony_ci#define __P010 __pgprot(0) 1978c2ecf20Sopenharmony_ci#define __P011 __pgprot(0) 1988c2ecf20Sopenharmony_ci#define __P100 __pgprot(0) 1998c2ecf20Sopenharmony_ci#define __P101 __pgprot(0) 2008c2ecf20Sopenharmony_ci#define __P110 __pgprot(0) 2018c2ecf20Sopenharmony_ci#define __P111 __pgprot(0) 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci#define __S000 __pgprot(0) 2048c2ecf20Sopenharmony_ci#define __S001 __pgprot(0) 2058c2ecf20Sopenharmony_ci#define __S010 __pgprot(0) 2068c2ecf20Sopenharmony_ci#define __S011 __pgprot(0) 2078c2ecf20Sopenharmony_ci#define __S100 __pgprot(0) 2088c2ecf20Sopenharmony_ci#define __S101 __pgprot(0) 2098c2ecf20Sopenharmony_ci#define __S110 __pgprot(0) 2108c2ecf20Sopenharmony_ci#define __S111 __pgprot(0) 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__ 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cipte_t mk_pte_io(unsigned long, pgprot_t, int, unsigned long); 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ciunsigned long pte_sz_bits(unsigned long size); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ciextern pgprot_t PAGE_KERNEL; 2198c2ecf20Sopenharmony_ciextern pgprot_t PAGE_KERNEL_LOCKED; 2208c2ecf20Sopenharmony_ciextern pgprot_t PAGE_COPY; 2218c2ecf20Sopenharmony_ciextern pgprot_t PAGE_SHARED; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci/* XXX This ugliness is for the atyfb driver's sparc mmap() support. XXX */ 2248c2ecf20Sopenharmony_ciextern unsigned long _PAGE_IE; 2258c2ecf20Sopenharmony_ciextern unsigned long _PAGE_E; 2268c2ecf20Sopenharmony_ciextern unsigned long _PAGE_CACHE; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ciextern unsigned long pg_iobits; 2298c2ecf20Sopenharmony_ciextern unsigned long _PAGE_ALL_SZ_BITS; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ciextern struct page *mem_map_zero; 2328c2ecf20Sopenharmony_ci#define ZERO_PAGE(vaddr) (mem_map_zero) 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci/* PFNs are real physical page numbers. However, mem_map only begins to record 2358c2ecf20Sopenharmony_ci * per-page information starting at pfn_base. This is to handle systems where 2368c2ecf20Sopenharmony_ci * the first physical page in the machine is at some huge physical address, 2378c2ecf20Sopenharmony_ci * such as 4GB. This is common on a partitioned E10000, for example. 2388c2ecf20Sopenharmony_ci */ 2398c2ecf20Sopenharmony_cistatic inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci unsigned long paddr = pfn << PAGE_SHIFT; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci BUILD_BUG_ON(_PAGE_SZBITS_4U != 0UL || _PAGE_SZBITS_4V != 0UL); 2448c2ecf20Sopenharmony_ci return __pte(paddr | pgprot_val(prot)); 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci#ifdef CONFIG_TRANSPARENT_HUGEPAGE 2498c2ecf20Sopenharmony_cistatic inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot) 2508c2ecf20Sopenharmony_ci{ 2518c2ecf20Sopenharmony_ci pte_t pte = pfn_pte(page_nr, pgprot); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci return __pmd(pte_val(pte)); 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ci#define mk_pmd(page, pgprot) pfn_pmd(page_to_pfn(page), (pgprot)) 2568c2ecf20Sopenharmony_ci#endif 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci/* This one can be done with two shifts. */ 2598c2ecf20Sopenharmony_cistatic inline unsigned long pte_pfn(pte_t pte) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci unsigned long ret; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci __asm__ __volatile__( 2648c2ecf20Sopenharmony_ci "\n661: sllx %1, %2, %0\n" 2658c2ecf20Sopenharmony_ci " srlx %0, %3, %0\n" 2668c2ecf20Sopenharmony_ci " .section .sun4v_2insn_patch, \"ax\"\n" 2678c2ecf20Sopenharmony_ci " .word 661b\n" 2688c2ecf20Sopenharmony_ci " sllx %1, %4, %0\n" 2698c2ecf20Sopenharmony_ci " srlx %0, %5, %0\n" 2708c2ecf20Sopenharmony_ci " .previous\n" 2718c2ecf20Sopenharmony_ci : "=r" (ret) 2728c2ecf20Sopenharmony_ci : "r" (pte_val(pte)), 2738c2ecf20Sopenharmony_ci "i" (21), "i" (21 + PAGE_SHIFT), 2748c2ecf20Sopenharmony_ci "i" (8), "i" (8 + PAGE_SHIFT)); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci return ret; 2778c2ecf20Sopenharmony_ci} 2788c2ecf20Sopenharmony_ci#define pte_page(x) pfn_to_page(pte_pfn(x)) 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_cistatic inline pte_t pte_modify(pte_t pte, pgprot_t prot) 2818c2ecf20Sopenharmony_ci{ 2828c2ecf20Sopenharmony_ci unsigned long mask, tmp; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci /* SUN4U: 0x630107ffffffec38 (negated == 0x9cfef800000013c7) 2858c2ecf20Sopenharmony_ci * SUN4V: 0x33ffffffffffee07 (negated == 0xcc000000000011f8) 2868c2ecf20Sopenharmony_ci * 2878c2ecf20Sopenharmony_ci * Even if we use negation tricks the result is still a 6 2888c2ecf20Sopenharmony_ci * instruction sequence, so don't try to play fancy and just 2898c2ecf20Sopenharmony_ci * do the most straightforward implementation. 2908c2ecf20Sopenharmony_ci * 2918c2ecf20Sopenharmony_ci * Note: We encode this into 3 sun4v 2-insn patch sequences. 2928c2ecf20Sopenharmony_ci */ 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci BUILD_BUG_ON(_PAGE_SZBITS_4U != 0UL || _PAGE_SZBITS_4V != 0UL); 2958c2ecf20Sopenharmony_ci __asm__ __volatile__( 2968c2ecf20Sopenharmony_ci "\n661: sethi %%uhi(%2), %1\n" 2978c2ecf20Sopenharmony_ci " sethi %%hi(%2), %0\n" 2988c2ecf20Sopenharmony_ci "\n662: or %1, %%ulo(%2), %1\n" 2998c2ecf20Sopenharmony_ci " or %0, %%lo(%2), %0\n" 3008c2ecf20Sopenharmony_ci "\n663: sllx %1, 32, %1\n" 3018c2ecf20Sopenharmony_ci " or %0, %1, %0\n" 3028c2ecf20Sopenharmony_ci " .section .sun4v_2insn_patch, \"ax\"\n" 3038c2ecf20Sopenharmony_ci " .word 661b\n" 3048c2ecf20Sopenharmony_ci " sethi %%uhi(%3), %1\n" 3058c2ecf20Sopenharmony_ci " sethi %%hi(%3), %0\n" 3068c2ecf20Sopenharmony_ci " .word 662b\n" 3078c2ecf20Sopenharmony_ci " or %1, %%ulo(%3), %1\n" 3088c2ecf20Sopenharmony_ci " or %0, %%lo(%3), %0\n" 3098c2ecf20Sopenharmony_ci " .word 663b\n" 3108c2ecf20Sopenharmony_ci " sllx %1, 32, %1\n" 3118c2ecf20Sopenharmony_ci " or %0, %1, %0\n" 3128c2ecf20Sopenharmony_ci " .previous\n" 3138c2ecf20Sopenharmony_ci " .section .sun_m7_2insn_patch, \"ax\"\n" 3148c2ecf20Sopenharmony_ci " .word 661b\n" 3158c2ecf20Sopenharmony_ci " sethi %%uhi(%4), %1\n" 3168c2ecf20Sopenharmony_ci " sethi %%hi(%4), %0\n" 3178c2ecf20Sopenharmony_ci " .word 662b\n" 3188c2ecf20Sopenharmony_ci " or %1, %%ulo(%4), %1\n" 3198c2ecf20Sopenharmony_ci " or %0, %%lo(%4), %0\n" 3208c2ecf20Sopenharmony_ci " .word 663b\n" 3218c2ecf20Sopenharmony_ci " sllx %1, 32, %1\n" 3228c2ecf20Sopenharmony_ci " or %0, %1, %0\n" 3238c2ecf20Sopenharmony_ci " .previous\n" 3248c2ecf20Sopenharmony_ci : "=r" (mask), "=r" (tmp) 3258c2ecf20Sopenharmony_ci : "i" (_PAGE_PADDR_4U | _PAGE_MODIFIED_4U | _PAGE_ACCESSED_4U | 3268c2ecf20Sopenharmony_ci _PAGE_CP_4U | _PAGE_CV_4U | _PAGE_E_4U | 3278c2ecf20Sopenharmony_ci _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4U), 3288c2ecf20Sopenharmony_ci "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V | 3298c2ecf20Sopenharmony_ci _PAGE_CP_4V | _PAGE_CV_4V | _PAGE_E_4V | 3308c2ecf20Sopenharmony_ci _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V), 3318c2ecf20Sopenharmony_ci "i" (_PAGE_PADDR_4V | _PAGE_MODIFIED_4V | _PAGE_ACCESSED_4V | 3328c2ecf20Sopenharmony_ci _PAGE_CP_4V | _PAGE_E_4V | 3338c2ecf20Sopenharmony_ci _PAGE_SPECIAL | _PAGE_PMD_HUGE | _PAGE_SZALL_4V)); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci return __pte((pte_val(pte) & mask) | (pgprot_val(prot) & ~mask)); 3368c2ecf20Sopenharmony_ci} 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci#ifdef CONFIG_TRANSPARENT_HUGEPAGE 3398c2ecf20Sopenharmony_cistatic inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) 3408c2ecf20Sopenharmony_ci{ 3418c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci pte = pte_modify(pte, newprot); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci return __pmd(pte_val(pte)); 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci#endif 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_cistatic inline pgprot_t pgprot_noncached(pgprot_t prot) 3508c2ecf20Sopenharmony_ci{ 3518c2ecf20Sopenharmony_ci unsigned long val = pgprot_val(prot); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci __asm__ __volatile__( 3548c2ecf20Sopenharmony_ci "\n661: andn %0, %2, %0\n" 3558c2ecf20Sopenharmony_ci " or %0, %3, %0\n" 3568c2ecf20Sopenharmony_ci " .section .sun4v_2insn_patch, \"ax\"\n" 3578c2ecf20Sopenharmony_ci " .word 661b\n" 3588c2ecf20Sopenharmony_ci " andn %0, %4, %0\n" 3598c2ecf20Sopenharmony_ci " or %0, %5, %0\n" 3608c2ecf20Sopenharmony_ci " .previous\n" 3618c2ecf20Sopenharmony_ci " .section .sun_m7_2insn_patch, \"ax\"\n" 3628c2ecf20Sopenharmony_ci " .word 661b\n" 3638c2ecf20Sopenharmony_ci " andn %0, %6, %0\n" 3648c2ecf20Sopenharmony_ci " or %0, %5, %0\n" 3658c2ecf20Sopenharmony_ci " .previous\n" 3668c2ecf20Sopenharmony_ci : "=r" (val) 3678c2ecf20Sopenharmony_ci : "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U), 3688c2ecf20Sopenharmony_ci "i" (_PAGE_CP_4V | _PAGE_CV_4V), "i" (_PAGE_E_4V), 3698c2ecf20Sopenharmony_ci "i" (_PAGE_CP_4V)); 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci return __pgprot(val); 3728c2ecf20Sopenharmony_ci} 3738c2ecf20Sopenharmony_ci/* Various pieces of code check for platform support by ifdef testing 3748c2ecf20Sopenharmony_ci * on "pgprot_noncached". That's broken and should be fixed, but for 3758c2ecf20Sopenharmony_ci * now... 3768c2ecf20Sopenharmony_ci */ 3778c2ecf20Sopenharmony_ci#define pgprot_noncached pgprot_noncached 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) 3808c2ecf20Sopenharmony_ciextern pte_t arch_make_huge_pte(pte_t entry, struct vm_area_struct *vma, 3818c2ecf20Sopenharmony_ci struct page *page, int writable); 3828c2ecf20Sopenharmony_ci#define arch_make_huge_pte arch_make_huge_pte 3838c2ecf20Sopenharmony_cistatic inline unsigned long __pte_default_huge_mask(void) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci unsigned long mask; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci __asm__ __volatile__( 3888c2ecf20Sopenharmony_ci "\n661: sethi %%uhi(%1), %0\n" 3898c2ecf20Sopenharmony_ci " sllx %0, 32, %0\n" 3908c2ecf20Sopenharmony_ci " .section .sun4v_2insn_patch, \"ax\"\n" 3918c2ecf20Sopenharmony_ci " .word 661b\n" 3928c2ecf20Sopenharmony_ci " mov %2, %0\n" 3938c2ecf20Sopenharmony_ci " nop\n" 3948c2ecf20Sopenharmony_ci " .previous\n" 3958c2ecf20Sopenharmony_ci : "=r" (mask) 3968c2ecf20Sopenharmony_ci : "i" (_PAGE_SZHUGE_4U), "i" (_PAGE_SZHUGE_4V)); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci return mask; 3998c2ecf20Sopenharmony_ci} 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_cistatic inline pte_t pte_mkhuge(pte_t pte) 4028c2ecf20Sopenharmony_ci{ 4038c2ecf20Sopenharmony_ci return __pte(pte_val(pte) | __pte_default_huge_mask()); 4048c2ecf20Sopenharmony_ci} 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_cistatic inline bool is_default_hugetlb_pte(pte_t pte) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci unsigned long mask = __pte_default_huge_mask(); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci return (pte_val(pte) & mask) == mask; 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_cistatic inline bool is_hugetlb_pmd(pmd_t pmd) 4148c2ecf20Sopenharmony_ci{ 4158c2ecf20Sopenharmony_ci return !!(pmd_val(pmd) & _PAGE_PMD_HUGE); 4168c2ecf20Sopenharmony_ci} 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_cistatic inline bool is_hugetlb_pud(pud_t pud) 4198c2ecf20Sopenharmony_ci{ 4208c2ecf20Sopenharmony_ci return !!(pud_val(pud) & _PAGE_PUD_HUGE); 4218c2ecf20Sopenharmony_ci} 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci#ifdef CONFIG_TRANSPARENT_HUGEPAGE 4248c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkhuge(pmd_t pmd) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci pte = pte_mkhuge(pte); 4298c2ecf20Sopenharmony_ci pte_val(pte) |= _PAGE_PMD_HUGE; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci return __pmd(pte_val(pte)); 4328c2ecf20Sopenharmony_ci} 4338c2ecf20Sopenharmony_ci#endif 4348c2ecf20Sopenharmony_ci#else 4358c2ecf20Sopenharmony_cistatic inline bool is_hugetlb_pte(pte_t pte) 4368c2ecf20Sopenharmony_ci{ 4378c2ecf20Sopenharmony_ci return false; 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci#endif 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_cistatic inline pte_t pte_mkdirty(pte_t pte) 4428c2ecf20Sopenharmony_ci{ 4438c2ecf20Sopenharmony_ci unsigned long val = pte_val(pte), tmp; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci __asm__ __volatile__( 4468c2ecf20Sopenharmony_ci "\n661: or %0, %3, %0\n" 4478c2ecf20Sopenharmony_ci " nop\n" 4488c2ecf20Sopenharmony_ci "\n662: nop\n" 4498c2ecf20Sopenharmony_ci " nop\n" 4508c2ecf20Sopenharmony_ci " .section .sun4v_2insn_patch, \"ax\"\n" 4518c2ecf20Sopenharmony_ci " .word 661b\n" 4528c2ecf20Sopenharmony_ci " sethi %%uhi(%4), %1\n" 4538c2ecf20Sopenharmony_ci " sllx %1, 32, %1\n" 4548c2ecf20Sopenharmony_ci " .word 662b\n" 4558c2ecf20Sopenharmony_ci " or %1, %%lo(%4), %1\n" 4568c2ecf20Sopenharmony_ci " or %0, %1, %0\n" 4578c2ecf20Sopenharmony_ci " .previous\n" 4588c2ecf20Sopenharmony_ci : "=r" (val), "=r" (tmp) 4598c2ecf20Sopenharmony_ci : "0" (val), "i" (_PAGE_MODIFIED_4U | _PAGE_W_4U), 4608c2ecf20Sopenharmony_ci "i" (_PAGE_MODIFIED_4V | _PAGE_W_4V)); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci return __pte(val); 4638c2ecf20Sopenharmony_ci} 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_cistatic inline pte_t pte_mkclean(pte_t pte) 4668c2ecf20Sopenharmony_ci{ 4678c2ecf20Sopenharmony_ci unsigned long val = pte_val(pte), tmp; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci __asm__ __volatile__( 4708c2ecf20Sopenharmony_ci "\n661: andn %0, %3, %0\n" 4718c2ecf20Sopenharmony_ci " nop\n" 4728c2ecf20Sopenharmony_ci "\n662: nop\n" 4738c2ecf20Sopenharmony_ci " nop\n" 4748c2ecf20Sopenharmony_ci " .section .sun4v_2insn_patch, \"ax\"\n" 4758c2ecf20Sopenharmony_ci " .word 661b\n" 4768c2ecf20Sopenharmony_ci " sethi %%uhi(%4), %1\n" 4778c2ecf20Sopenharmony_ci " sllx %1, 32, %1\n" 4788c2ecf20Sopenharmony_ci " .word 662b\n" 4798c2ecf20Sopenharmony_ci " or %1, %%lo(%4), %1\n" 4808c2ecf20Sopenharmony_ci " andn %0, %1, %0\n" 4818c2ecf20Sopenharmony_ci " .previous\n" 4828c2ecf20Sopenharmony_ci : "=r" (val), "=r" (tmp) 4838c2ecf20Sopenharmony_ci : "0" (val), "i" (_PAGE_MODIFIED_4U | _PAGE_W_4U), 4848c2ecf20Sopenharmony_ci "i" (_PAGE_MODIFIED_4V | _PAGE_W_4V)); 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci return __pte(val); 4878c2ecf20Sopenharmony_ci} 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_cistatic inline pte_t pte_mkwrite(pte_t pte) 4908c2ecf20Sopenharmony_ci{ 4918c2ecf20Sopenharmony_ci unsigned long val = pte_val(pte), mask; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci __asm__ __volatile__( 4948c2ecf20Sopenharmony_ci "\n661: mov %1, %0\n" 4958c2ecf20Sopenharmony_ci " nop\n" 4968c2ecf20Sopenharmony_ci " .section .sun4v_2insn_patch, \"ax\"\n" 4978c2ecf20Sopenharmony_ci " .word 661b\n" 4988c2ecf20Sopenharmony_ci " sethi %%uhi(%2), %0\n" 4998c2ecf20Sopenharmony_ci " sllx %0, 32, %0\n" 5008c2ecf20Sopenharmony_ci " .previous\n" 5018c2ecf20Sopenharmony_ci : "=r" (mask) 5028c2ecf20Sopenharmony_ci : "i" (_PAGE_WRITE_4U), "i" (_PAGE_WRITE_4V)); 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_ci return __pte(val | mask); 5058c2ecf20Sopenharmony_ci} 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_cistatic inline pte_t pte_wrprotect(pte_t pte) 5088c2ecf20Sopenharmony_ci{ 5098c2ecf20Sopenharmony_ci unsigned long val = pte_val(pte), tmp; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci __asm__ __volatile__( 5128c2ecf20Sopenharmony_ci "\n661: andn %0, %3, %0\n" 5138c2ecf20Sopenharmony_ci " nop\n" 5148c2ecf20Sopenharmony_ci "\n662: nop\n" 5158c2ecf20Sopenharmony_ci " nop\n" 5168c2ecf20Sopenharmony_ci " .section .sun4v_2insn_patch, \"ax\"\n" 5178c2ecf20Sopenharmony_ci " .word 661b\n" 5188c2ecf20Sopenharmony_ci " sethi %%uhi(%4), %1\n" 5198c2ecf20Sopenharmony_ci " sllx %1, 32, %1\n" 5208c2ecf20Sopenharmony_ci " .word 662b\n" 5218c2ecf20Sopenharmony_ci " or %1, %%lo(%4), %1\n" 5228c2ecf20Sopenharmony_ci " andn %0, %1, %0\n" 5238c2ecf20Sopenharmony_ci " .previous\n" 5248c2ecf20Sopenharmony_ci : "=r" (val), "=r" (tmp) 5258c2ecf20Sopenharmony_ci : "0" (val), "i" (_PAGE_WRITE_4U | _PAGE_W_4U), 5268c2ecf20Sopenharmony_ci "i" (_PAGE_WRITE_4V | _PAGE_W_4V)); 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci return __pte(val); 5298c2ecf20Sopenharmony_ci} 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_cistatic inline pte_t pte_mkold(pte_t pte) 5328c2ecf20Sopenharmony_ci{ 5338c2ecf20Sopenharmony_ci unsigned long mask; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci __asm__ __volatile__( 5368c2ecf20Sopenharmony_ci "\n661: mov %1, %0\n" 5378c2ecf20Sopenharmony_ci " nop\n" 5388c2ecf20Sopenharmony_ci " .section .sun4v_2insn_patch, \"ax\"\n" 5398c2ecf20Sopenharmony_ci " .word 661b\n" 5408c2ecf20Sopenharmony_ci " sethi %%uhi(%2), %0\n" 5418c2ecf20Sopenharmony_ci " sllx %0, 32, %0\n" 5428c2ecf20Sopenharmony_ci " .previous\n" 5438c2ecf20Sopenharmony_ci : "=r" (mask) 5448c2ecf20Sopenharmony_ci : "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V)); 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci mask |= _PAGE_R; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci return __pte(pte_val(pte) & ~mask); 5498c2ecf20Sopenharmony_ci} 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_cistatic inline pte_t pte_mkyoung(pte_t pte) 5528c2ecf20Sopenharmony_ci{ 5538c2ecf20Sopenharmony_ci unsigned long mask; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci __asm__ __volatile__( 5568c2ecf20Sopenharmony_ci "\n661: mov %1, %0\n" 5578c2ecf20Sopenharmony_ci " nop\n" 5588c2ecf20Sopenharmony_ci " .section .sun4v_2insn_patch, \"ax\"\n" 5598c2ecf20Sopenharmony_ci " .word 661b\n" 5608c2ecf20Sopenharmony_ci " sethi %%uhi(%2), %0\n" 5618c2ecf20Sopenharmony_ci " sllx %0, 32, %0\n" 5628c2ecf20Sopenharmony_ci " .previous\n" 5638c2ecf20Sopenharmony_ci : "=r" (mask) 5648c2ecf20Sopenharmony_ci : "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V)); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci mask |= _PAGE_R; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci return __pte(pte_val(pte) | mask); 5698c2ecf20Sopenharmony_ci} 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_cistatic inline pte_t pte_mkspecial(pte_t pte) 5728c2ecf20Sopenharmony_ci{ 5738c2ecf20Sopenharmony_ci pte_val(pte) |= _PAGE_SPECIAL; 5748c2ecf20Sopenharmony_ci return pte; 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_cistatic inline pte_t pte_mkmcd(pte_t pte) 5788c2ecf20Sopenharmony_ci{ 5798c2ecf20Sopenharmony_ci pte_val(pte) |= _PAGE_MCD_4V; 5808c2ecf20Sopenharmony_ci return pte; 5818c2ecf20Sopenharmony_ci} 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_cistatic inline pte_t pte_mknotmcd(pte_t pte) 5848c2ecf20Sopenharmony_ci{ 5858c2ecf20Sopenharmony_ci pte_val(pte) &= ~_PAGE_MCD_4V; 5868c2ecf20Sopenharmony_ci return pte; 5878c2ecf20Sopenharmony_ci} 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_cistatic inline unsigned long pte_young(pte_t pte) 5908c2ecf20Sopenharmony_ci{ 5918c2ecf20Sopenharmony_ci unsigned long mask; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci __asm__ __volatile__( 5948c2ecf20Sopenharmony_ci "\n661: mov %1, %0\n" 5958c2ecf20Sopenharmony_ci " nop\n" 5968c2ecf20Sopenharmony_ci " .section .sun4v_2insn_patch, \"ax\"\n" 5978c2ecf20Sopenharmony_ci " .word 661b\n" 5988c2ecf20Sopenharmony_ci " sethi %%uhi(%2), %0\n" 5998c2ecf20Sopenharmony_ci " sllx %0, 32, %0\n" 6008c2ecf20Sopenharmony_ci " .previous\n" 6018c2ecf20Sopenharmony_ci : "=r" (mask) 6028c2ecf20Sopenharmony_ci : "i" (_PAGE_ACCESSED_4U), "i" (_PAGE_ACCESSED_4V)); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci return (pte_val(pte) & mask); 6058c2ecf20Sopenharmony_ci} 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_cistatic inline unsigned long pte_dirty(pte_t pte) 6088c2ecf20Sopenharmony_ci{ 6098c2ecf20Sopenharmony_ci unsigned long mask; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci __asm__ __volatile__( 6128c2ecf20Sopenharmony_ci "\n661: mov %1, %0\n" 6138c2ecf20Sopenharmony_ci " nop\n" 6148c2ecf20Sopenharmony_ci " .section .sun4v_2insn_patch, \"ax\"\n" 6158c2ecf20Sopenharmony_ci " .word 661b\n" 6168c2ecf20Sopenharmony_ci " sethi %%uhi(%2), %0\n" 6178c2ecf20Sopenharmony_ci " sllx %0, 32, %0\n" 6188c2ecf20Sopenharmony_ci " .previous\n" 6198c2ecf20Sopenharmony_ci : "=r" (mask) 6208c2ecf20Sopenharmony_ci : "i" (_PAGE_MODIFIED_4U), "i" (_PAGE_MODIFIED_4V)); 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci return (pte_val(pte) & mask); 6238c2ecf20Sopenharmony_ci} 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_cistatic inline unsigned long pte_write(pte_t pte) 6268c2ecf20Sopenharmony_ci{ 6278c2ecf20Sopenharmony_ci unsigned long mask; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci __asm__ __volatile__( 6308c2ecf20Sopenharmony_ci "\n661: mov %1, %0\n" 6318c2ecf20Sopenharmony_ci " nop\n" 6328c2ecf20Sopenharmony_ci " .section .sun4v_2insn_patch, \"ax\"\n" 6338c2ecf20Sopenharmony_ci " .word 661b\n" 6348c2ecf20Sopenharmony_ci " sethi %%uhi(%2), %0\n" 6358c2ecf20Sopenharmony_ci " sllx %0, 32, %0\n" 6368c2ecf20Sopenharmony_ci " .previous\n" 6378c2ecf20Sopenharmony_ci : "=r" (mask) 6388c2ecf20Sopenharmony_ci : "i" (_PAGE_WRITE_4U), "i" (_PAGE_WRITE_4V)); 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci return (pte_val(pte) & mask); 6418c2ecf20Sopenharmony_ci} 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_cistatic inline unsigned long pte_exec(pte_t pte) 6448c2ecf20Sopenharmony_ci{ 6458c2ecf20Sopenharmony_ci unsigned long mask; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci __asm__ __volatile__( 6488c2ecf20Sopenharmony_ci "\n661: sethi %%hi(%1), %0\n" 6498c2ecf20Sopenharmony_ci " .section .sun4v_1insn_patch, \"ax\"\n" 6508c2ecf20Sopenharmony_ci " .word 661b\n" 6518c2ecf20Sopenharmony_ci " mov %2, %0\n" 6528c2ecf20Sopenharmony_ci " .previous\n" 6538c2ecf20Sopenharmony_ci : "=r" (mask) 6548c2ecf20Sopenharmony_ci : "i" (_PAGE_EXEC_4U), "i" (_PAGE_EXEC_4V)); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci return (pte_val(pte) & mask); 6578c2ecf20Sopenharmony_ci} 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_cistatic inline unsigned long pte_present(pte_t pte) 6608c2ecf20Sopenharmony_ci{ 6618c2ecf20Sopenharmony_ci unsigned long val = pte_val(pte); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci __asm__ __volatile__( 6648c2ecf20Sopenharmony_ci "\n661: and %0, %2, %0\n" 6658c2ecf20Sopenharmony_ci " .section .sun4v_1insn_patch, \"ax\"\n" 6668c2ecf20Sopenharmony_ci " .word 661b\n" 6678c2ecf20Sopenharmony_ci " and %0, %3, %0\n" 6688c2ecf20Sopenharmony_ci " .previous\n" 6698c2ecf20Sopenharmony_ci : "=r" (val) 6708c2ecf20Sopenharmony_ci : "0" (val), "i" (_PAGE_PRESENT_4U), "i" (_PAGE_PRESENT_4V)); 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci return val; 6738c2ecf20Sopenharmony_ci} 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci#define pte_accessible pte_accessible 6768c2ecf20Sopenharmony_cistatic inline unsigned long pte_accessible(struct mm_struct *mm, pte_t a) 6778c2ecf20Sopenharmony_ci{ 6788c2ecf20Sopenharmony_ci return pte_val(a) & _PAGE_VALID; 6798c2ecf20Sopenharmony_ci} 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_cistatic inline unsigned long pte_special(pte_t pte) 6828c2ecf20Sopenharmony_ci{ 6838c2ecf20Sopenharmony_ci return pte_val(pte) & _PAGE_SPECIAL; 6848c2ecf20Sopenharmony_ci} 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci#define pmd_leaf pmd_large 6878c2ecf20Sopenharmony_cistatic inline unsigned long pmd_large(pmd_t pmd) 6888c2ecf20Sopenharmony_ci{ 6898c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci return pte_val(pte) & _PAGE_PMD_HUGE; 6928c2ecf20Sopenharmony_ci} 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_cistatic inline unsigned long pmd_pfn(pmd_t pmd) 6958c2ecf20Sopenharmony_ci{ 6968c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci return pte_pfn(pte); 6998c2ecf20Sopenharmony_ci} 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci#define pmd_write pmd_write 7028c2ecf20Sopenharmony_cistatic inline unsigned long pmd_write(pmd_t pmd) 7038c2ecf20Sopenharmony_ci{ 7048c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci return pte_write(pte); 7078c2ecf20Sopenharmony_ci} 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci#define pud_write(pud) pte_write(__pte(pud_val(pud))) 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci#ifdef CONFIG_TRANSPARENT_HUGEPAGE 7128c2ecf20Sopenharmony_cistatic inline unsigned long pmd_dirty(pmd_t pmd) 7138c2ecf20Sopenharmony_ci{ 7148c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci return pte_dirty(pte); 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_cistatic inline unsigned long pmd_young(pmd_t pmd) 7208c2ecf20Sopenharmony_ci{ 7218c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci return pte_young(pte); 7248c2ecf20Sopenharmony_ci} 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_cistatic inline unsigned long pmd_trans_huge(pmd_t pmd) 7278c2ecf20Sopenharmony_ci{ 7288c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci return pte_val(pte) & _PAGE_PMD_HUGE; 7318c2ecf20Sopenharmony_ci} 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkold(pmd_t pmd) 7348c2ecf20Sopenharmony_ci{ 7358c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci pte = pte_mkold(pte); 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci return __pmd(pte_val(pte)); 7408c2ecf20Sopenharmony_ci} 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_cistatic inline pmd_t pmd_wrprotect(pmd_t pmd) 7438c2ecf20Sopenharmony_ci{ 7448c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci pte = pte_wrprotect(pte); 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci return __pmd(pte_val(pte)); 7498c2ecf20Sopenharmony_ci} 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkdirty(pmd_t pmd) 7528c2ecf20Sopenharmony_ci{ 7538c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci pte = pte_mkdirty(pte); 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci return __pmd(pte_val(pte)); 7588c2ecf20Sopenharmony_ci} 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkclean(pmd_t pmd) 7618c2ecf20Sopenharmony_ci{ 7628c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci pte = pte_mkclean(pte); 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci return __pmd(pte_val(pte)); 7678c2ecf20Sopenharmony_ci} 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkyoung(pmd_t pmd) 7708c2ecf20Sopenharmony_ci{ 7718c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci pte = pte_mkyoung(pte); 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_ci return __pmd(pte_val(pte)); 7768c2ecf20Sopenharmony_ci} 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_cistatic inline pmd_t pmd_mkwrite(pmd_t pmd) 7798c2ecf20Sopenharmony_ci{ 7808c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci pte = pte_mkwrite(pte); 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci return __pmd(pte_val(pte)); 7858c2ecf20Sopenharmony_ci} 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_cistatic inline pgprot_t pmd_pgprot(pmd_t entry) 7888c2ecf20Sopenharmony_ci{ 7898c2ecf20Sopenharmony_ci unsigned long val = pmd_val(entry); 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci return __pgprot(val); 7928c2ecf20Sopenharmony_ci} 7938c2ecf20Sopenharmony_ci#endif 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_cistatic inline int pmd_present(pmd_t pmd) 7968c2ecf20Sopenharmony_ci{ 7978c2ecf20Sopenharmony_ci return pmd_val(pmd) != 0UL; 7988c2ecf20Sopenharmony_ci} 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci#define pmd_none(pmd) (!pmd_val(pmd)) 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci/* pmd_bad() is only called on non-trans-huge PMDs. Our encoding is 8038c2ecf20Sopenharmony_ci * very simple, it's just the physical address. PTE tables are of 8048c2ecf20Sopenharmony_ci * size PAGE_SIZE so make sure the sub-PAGE_SIZE bits are clear and 8058c2ecf20Sopenharmony_ci * the top bits outside of the range of any physical address size we 8068c2ecf20Sopenharmony_ci * support are clear as well. We also validate the physical itself. 8078c2ecf20Sopenharmony_ci */ 8088c2ecf20Sopenharmony_ci#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK) 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci#define pud_none(pud) (!pud_val(pud)) 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci#define pud_bad(pud) (pud_val(pud) & ~PAGE_MASK) 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci#define p4d_none(p4d) (!p4d_val(p4d)) 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci#define p4d_bad(p4d) (p4d_val(p4d) & ~PAGE_MASK) 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci#ifdef CONFIG_TRANSPARENT_HUGEPAGE 8198c2ecf20Sopenharmony_civoid set_pmd_at(struct mm_struct *mm, unsigned long addr, 8208c2ecf20Sopenharmony_ci pmd_t *pmdp, pmd_t pmd); 8218c2ecf20Sopenharmony_ci#else 8228c2ecf20Sopenharmony_cistatic inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, 8238c2ecf20Sopenharmony_ci pmd_t *pmdp, pmd_t pmd) 8248c2ecf20Sopenharmony_ci{ 8258c2ecf20Sopenharmony_ci *pmdp = pmd; 8268c2ecf20Sopenharmony_ci} 8278c2ecf20Sopenharmony_ci#endif 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_cistatic inline void pmd_set(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep) 8308c2ecf20Sopenharmony_ci{ 8318c2ecf20Sopenharmony_ci unsigned long val = __pa((unsigned long) (ptep)); 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci pmd_val(*pmdp) = val; 8348c2ecf20Sopenharmony_ci} 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci#define pud_set(pudp, pmdp) \ 8378c2ecf20Sopenharmony_ci (pud_val(*(pudp)) = (__pa((unsigned long) (pmdp)))) 8388c2ecf20Sopenharmony_cistatic inline unsigned long pmd_page_vaddr(pmd_t pmd) 8398c2ecf20Sopenharmony_ci{ 8408c2ecf20Sopenharmony_ci pte_t pte = __pte(pmd_val(pmd)); 8418c2ecf20Sopenharmony_ci unsigned long pfn; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci pfn = pte_pfn(pte); 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_ci return ((unsigned long) __va(pfn << PAGE_SHIFT)); 8468c2ecf20Sopenharmony_ci} 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_cistatic inline pmd_t *pud_pgtable(pud_t pud) 8498c2ecf20Sopenharmony_ci{ 8508c2ecf20Sopenharmony_ci pte_t pte = __pte(pud_val(pud)); 8518c2ecf20Sopenharmony_ci unsigned long pfn; 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci pfn = pte_pfn(pte); 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci return ((pmd_t *) __va(pfn << PAGE_SHIFT)); 8568c2ecf20Sopenharmony_ci} 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci#define pmd_page(pmd) virt_to_page((void *)pmd_page_vaddr(pmd)) 8598c2ecf20Sopenharmony_ci#define pud_page(pud) virt_to_page((void *)pud_pgtable(pud)) 8608c2ecf20Sopenharmony_ci#define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0UL) 8618c2ecf20Sopenharmony_ci#define pud_present(pud) (pud_val(pud) != 0U) 8628c2ecf20Sopenharmony_ci#define pud_clear(pudp) (pud_val(*(pudp)) = 0UL) 8638c2ecf20Sopenharmony_ci#define p4d_pgtable(p4d) \ 8648c2ecf20Sopenharmony_ci ((pud_t *) __va(p4d_val(p4d))) 8658c2ecf20Sopenharmony_ci#define p4d_present(p4d) (p4d_val(p4d) != 0U) 8668c2ecf20Sopenharmony_ci#define p4d_clear(p4dp) (p4d_val(*(p4dp)) = 0UL) 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci/* only used by the stubbed out hugetlb gup code, should never be called */ 8698c2ecf20Sopenharmony_ci#define p4d_page(p4d) NULL 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci#define pud_leaf pud_large 8728c2ecf20Sopenharmony_cistatic inline unsigned long pud_large(pud_t pud) 8738c2ecf20Sopenharmony_ci{ 8748c2ecf20Sopenharmony_ci pte_t pte = __pte(pud_val(pud)); 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci return pte_val(pte) & _PAGE_PMD_HUGE; 8778c2ecf20Sopenharmony_ci} 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_cistatic inline unsigned long pud_pfn(pud_t pud) 8808c2ecf20Sopenharmony_ci{ 8818c2ecf20Sopenharmony_ci pte_t pte = __pte(pud_val(pud)); 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci return pte_pfn(pte); 8848c2ecf20Sopenharmony_ci} 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci/* Same in both SUN4V and SUN4U. */ 8878c2ecf20Sopenharmony_ci#define pte_none(pte) (!pte_val(pte)) 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci#define p4d_set(p4dp, pudp) \ 8908c2ecf20Sopenharmony_ci (p4d_val(*(p4dp)) = (__pa((unsigned long) (pudp)))) 8918c2ecf20Sopenharmony_ci 8928c2ecf20Sopenharmony_ci/* We cannot include <linux/mm_types.h> at this point yet: */ 8938c2ecf20Sopenharmony_ciextern struct mm_struct init_mm; 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci/* Actual page table PTE updates. */ 8968c2ecf20Sopenharmony_civoid tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, 8978c2ecf20Sopenharmony_ci pte_t *ptep, pte_t orig, int fullmm, 8988c2ecf20Sopenharmony_ci unsigned int hugepage_shift); 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_cistatic void maybe_tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, 9018c2ecf20Sopenharmony_ci pte_t *ptep, pte_t orig, int fullmm, 9028c2ecf20Sopenharmony_ci unsigned int hugepage_shift) 9038c2ecf20Sopenharmony_ci{ 9048c2ecf20Sopenharmony_ci /* It is more efficient to let flush_tlb_kernel_range() 9058c2ecf20Sopenharmony_ci * handle init_mm tlb flushes. 9068c2ecf20Sopenharmony_ci * 9078c2ecf20Sopenharmony_ci * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U 9088c2ecf20Sopenharmony_ci * and SUN4V pte layout, so this inline test is fine. 9098c2ecf20Sopenharmony_ci */ 9108c2ecf20Sopenharmony_ci if (likely(mm != &init_mm) && pte_accessible(mm, orig)) 9118c2ecf20Sopenharmony_ci tlb_batch_add(mm, vaddr, ptep, orig, fullmm, hugepage_shift); 9128c2ecf20Sopenharmony_ci} 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR 9158c2ecf20Sopenharmony_cistatic inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, 9168c2ecf20Sopenharmony_ci unsigned long addr, 9178c2ecf20Sopenharmony_ci pmd_t *pmdp) 9188c2ecf20Sopenharmony_ci{ 9198c2ecf20Sopenharmony_ci pmd_t pmd = *pmdp; 9208c2ecf20Sopenharmony_ci set_pmd_at(mm, addr, pmdp, __pmd(0UL)); 9218c2ecf20Sopenharmony_ci return pmd; 9228c2ecf20Sopenharmony_ci} 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_cistatic inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, 9258c2ecf20Sopenharmony_ci pte_t *ptep, pte_t pte, int fullmm) 9268c2ecf20Sopenharmony_ci{ 9278c2ecf20Sopenharmony_ci pte_t orig = *ptep; 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci *ptep = pte; 9308c2ecf20Sopenharmony_ci maybe_tlb_batch_add(mm, addr, ptep, orig, fullmm, PAGE_SHIFT); 9318c2ecf20Sopenharmony_ci} 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci#define set_pte_at(mm,addr,ptep,pte) \ 9348c2ecf20Sopenharmony_ci __set_pte_at((mm), (addr), (ptep), (pte), 0) 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci#define pte_clear(mm,addr,ptep) \ 9378c2ecf20Sopenharmony_ci set_pte_at((mm), (addr), (ptep), __pte(0UL)) 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PTE_CLEAR_NOT_PRESENT_FULL 9408c2ecf20Sopenharmony_ci#define pte_clear_not_present_full(mm,addr,ptep,fullmm) \ 9418c2ecf20Sopenharmony_ci __set_pte_at((mm), (addr), (ptep), __pte(0UL), (fullmm)) 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci#ifdef DCACHE_ALIASING_POSSIBLE 9448c2ecf20Sopenharmony_ci#define __HAVE_ARCH_MOVE_PTE 9458c2ecf20Sopenharmony_ci#define move_pte(pte, prot, old_addr, new_addr) \ 9468c2ecf20Sopenharmony_ci({ \ 9478c2ecf20Sopenharmony_ci pte_t newpte = (pte); \ 9488c2ecf20Sopenharmony_ci if (tlb_type != hypervisor && pte_present(pte)) { \ 9498c2ecf20Sopenharmony_ci unsigned long this_pfn = pte_pfn(pte); \ 9508c2ecf20Sopenharmony_ci \ 9518c2ecf20Sopenharmony_ci if (pfn_valid(this_pfn) && \ 9528c2ecf20Sopenharmony_ci (((old_addr) ^ (new_addr)) & (1 << 13))) \ 9538c2ecf20Sopenharmony_ci flush_dcache_page_all(current->mm, \ 9548c2ecf20Sopenharmony_ci pfn_to_page(this_pfn)); \ 9558c2ecf20Sopenharmony_ci } \ 9568c2ecf20Sopenharmony_ci newpte; \ 9578c2ecf20Sopenharmony_ci}) 9588c2ecf20Sopenharmony_ci#endif 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ciextern pgd_t swapper_pg_dir[PTRS_PER_PGD]; 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_civoid paging_init(void); 9638c2ecf20Sopenharmony_ciunsigned long find_ecache_flush_span(unsigned long size); 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_cistruct seq_file; 9668c2ecf20Sopenharmony_civoid mmu_info(struct seq_file *); 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_cistruct vm_area_struct; 9698c2ecf20Sopenharmony_civoid update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *); 9708c2ecf20Sopenharmony_ci#ifdef CONFIG_TRANSPARENT_HUGEPAGE 9718c2ecf20Sopenharmony_civoid update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, 9728c2ecf20Sopenharmony_ci pmd_t *pmd); 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PMDP_INVALIDATE 9758c2ecf20Sopenharmony_ciextern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, 9768c2ecf20Sopenharmony_ci pmd_t *pmdp); 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PGTABLE_DEPOSIT 9798c2ecf20Sopenharmony_civoid pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, 9808c2ecf20Sopenharmony_ci pgtable_t pgtable); 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci#define __HAVE_ARCH_PGTABLE_WITHDRAW 9838c2ecf20Sopenharmony_cipgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp); 9848c2ecf20Sopenharmony_ci#endif 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci/* Encode and de-code a swap entry */ 9878c2ecf20Sopenharmony_ci#define __swp_type(entry) (((entry).val >> PAGE_SHIFT) & 0xffUL) 9888c2ecf20Sopenharmony_ci#define __swp_offset(entry) ((entry).val >> (PAGE_SHIFT + 8UL)) 9898c2ecf20Sopenharmony_ci#define __swp_entry(type, offset) \ 9908c2ecf20Sopenharmony_ci ( (swp_entry_t) \ 9918c2ecf20Sopenharmony_ci { \ 9928c2ecf20Sopenharmony_ci (((long)(type) << PAGE_SHIFT) | \ 9938c2ecf20Sopenharmony_ci ((long)(offset) << (PAGE_SHIFT + 8UL))) \ 9948c2ecf20Sopenharmony_ci } ) 9958c2ecf20Sopenharmony_ci#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) 9968c2ecf20Sopenharmony_ci#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) 9978c2ecf20Sopenharmony_ci 9988c2ecf20Sopenharmony_ciint page_in_phys_avail(unsigned long paddr); 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci/* 10018c2ecf20Sopenharmony_ci * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in 10028c2ecf20Sopenharmony_ci * its high 4 bits. These macros/functions put it there or get it from there. 10038c2ecf20Sopenharmony_ci */ 10048c2ecf20Sopenharmony_ci#define MK_IOSPACE_PFN(space, pfn) (pfn | (space << (BITS_PER_LONG - 4))) 10058c2ecf20Sopenharmony_ci#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4)) 10068c2ecf20Sopenharmony_ci#define GET_PFN(pfn) (pfn & 0x0fffffffffffffffUL) 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ciint remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long, 10098c2ecf20Sopenharmony_ci unsigned long, pgprot_t); 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_civoid adi_restore_tags(struct mm_struct *mm, struct vm_area_struct *vma, 10128c2ecf20Sopenharmony_ci unsigned long addr, pte_t pte); 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ciint adi_save_tags(struct mm_struct *mm, struct vm_area_struct *vma, 10158c2ecf20Sopenharmony_ci unsigned long addr, pte_t oldpte); 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci#define __HAVE_ARCH_DO_SWAP_PAGE 10188c2ecf20Sopenharmony_cistatic inline void arch_do_swap_page(struct mm_struct *mm, 10198c2ecf20Sopenharmony_ci struct vm_area_struct *vma, 10208c2ecf20Sopenharmony_ci unsigned long addr, 10218c2ecf20Sopenharmony_ci pte_t pte, pte_t oldpte) 10228c2ecf20Sopenharmony_ci{ 10238c2ecf20Sopenharmony_ci /* If this is a new page being mapped in, there can be no 10248c2ecf20Sopenharmony_ci * ADI tags stored away for this page. Skip looking for 10258c2ecf20Sopenharmony_ci * stored tags 10268c2ecf20Sopenharmony_ci */ 10278c2ecf20Sopenharmony_ci if (pte_none(oldpte)) 10288c2ecf20Sopenharmony_ci return; 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci if (adi_state.enabled && (pte_val(pte) & _PAGE_MCD_4V)) 10318c2ecf20Sopenharmony_ci adi_restore_tags(mm, vma, addr, pte); 10328c2ecf20Sopenharmony_ci} 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci#define __HAVE_ARCH_UNMAP_ONE 10358c2ecf20Sopenharmony_cistatic inline int arch_unmap_one(struct mm_struct *mm, 10368c2ecf20Sopenharmony_ci struct vm_area_struct *vma, 10378c2ecf20Sopenharmony_ci unsigned long addr, pte_t oldpte) 10388c2ecf20Sopenharmony_ci{ 10398c2ecf20Sopenharmony_ci if (adi_state.enabled && (pte_val(oldpte) & _PAGE_MCD_4V)) 10408c2ecf20Sopenharmony_ci return adi_save_tags(mm, vma, addr, oldpte); 10418c2ecf20Sopenharmony_ci return 0; 10428c2ecf20Sopenharmony_ci} 10438c2ecf20Sopenharmony_ci 10448c2ecf20Sopenharmony_cistatic inline int io_remap_pfn_range(struct vm_area_struct *vma, 10458c2ecf20Sopenharmony_ci unsigned long from, unsigned long pfn, 10468c2ecf20Sopenharmony_ci unsigned long size, pgprot_t prot) 10478c2ecf20Sopenharmony_ci{ 10488c2ecf20Sopenharmony_ci unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT; 10498c2ecf20Sopenharmony_ci int space = GET_IOSPACE(pfn); 10508c2ecf20Sopenharmony_ci unsigned long phys_base; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci phys_base = offset | (((unsigned long) space) << 32UL); 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot); 10558c2ecf20Sopenharmony_ci} 10568c2ecf20Sopenharmony_ci#define io_remap_pfn_range io_remap_pfn_range 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_cistatic inline unsigned long __untagged_addr(unsigned long start) 10598c2ecf20Sopenharmony_ci{ 10608c2ecf20Sopenharmony_ci if (adi_capable()) { 10618c2ecf20Sopenharmony_ci long addr = start; 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci /* If userspace has passed a versioned address, kernel 10648c2ecf20Sopenharmony_ci * will not find it in the VMAs since it does not store 10658c2ecf20Sopenharmony_ci * the version tags in the list of VMAs. Storing version 10668c2ecf20Sopenharmony_ci * tags in list of VMAs is impractical since they can be 10678c2ecf20Sopenharmony_ci * changed any time from userspace without dropping into 10688c2ecf20Sopenharmony_ci * kernel. Any address search in VMAs will be done with 10698c2ecf20Sopenharmony_ci * non-versioned addresses. Ensure the ADI version bits 10708c2ecf20Sopenharmony_ci * are dropped here by sign extending the last bit before 10718c2ecf20Sopenharmony_ci * ADI bits. IOMMU does not implement version tags. 10728c2ecf20Sopenharmony_ci */ 10738c2ecf20Sopenharmony_ci return (addr << (long)adi_nbits()) >> (long)adi_nbits(); 10748c2ecf20Sopenharmony_ci } 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci return start; 10778c2ecf20Sopenharmony_ci} 10788c2ecf20Sopenharmony_ci#define untagged_addr(addr) \ 10798c2ecf20Sopenharmony_ci ((__typeof__(addr))(__untagged_addr((unsigned long)(addr)))) 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_cistatic inline bool pte_access_permitted(pte_t pte, bool write) 10828c2ecf20Sopenharmony_ci{ 10838c2ecf20Sopenharmony_ci u64 prot; 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci if (tlb_type == hypervisor) { 10868c2ecf20Sopenharmony_ci prot = _PAGE_PRESENT_4V | _PAGE_P_4V; 10878c2ecf20Sopenharmony_ci if (write) 10888c2ecf20Sopenharmony_ci prot |= _PAGE_WRITE_4V; 10898c2ecf20Sopenharmony_ci } else { 10908c2ecf20Sopenharmony_ci prot = _PAGE_PRESENT_4U | _PAGE_P_4U; 10918c2ecf20Sopenharmony_ci if (write) 10928c2ecf20Sopenharmony_ci prot |= _PAGE_WRITE_4U; 10938c2ecf20Sopenharmony_ci } 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci return (pte_val(pte) & (prot | _PAGE_SPECIAL)) == prot; 10968c2ecf20Sopenharmony_ci} 10978c2ecf20Sopenharmony_ci#define pte_access_permitted pte_access_permitted 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci#include <asm/tlbflush.h> 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci/* We provide our own get_unmapped_area to cope with VA holes and 11028c2ecf20Sopenharmony_ci * SHM area cache aliasing for userland. 11038c2ecf20Sopenharmony_ci */ 11048c2ecf20Sopenharmony_ci#define HAVE_ARCH_UNMAPPED_AREA 11058c2ecf20Sopenharmony_ci#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci/* We provide a special get_unmapped_area for framebuffer mmaps to try and use 11088c2ecf20Sopenharmony_ci * the largest alignment possible such that larget PTEs can be used. 11098c2ecf20Sopenharmony_ci */ 11108c2ecf20Sopenharmony_ciunsigned long get_fb_unmapped_area(struct file *filp, unsigned long, 11118c2ecf20Sopenharmony_ci unsigned long, unsigned long, 11128c2ecf20Sopenharmony_ci unsigned long); 11138c2ecf20Sopenharmony_ci#define HAVE_ARCH_FB_UNMAPPED_AREA 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_civoid sun4v_register_fault_status(void); 11168c2ecf20Sopenharmony_civoid sun4v_ktsb_register(void); 11178c2ecf20Sopenharmony_civoid __init cheetah_ecache_flush_init(void); 11188c2ecf20Sopenharmony_civoid sun4v_patch_tlb_handlers(void); 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ciextern unsigned long cmdline_memory_size; 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ciasmlinkage void do_sparc64_fault(struct pt_regs *regs); 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci#endif /* !(__ASSEMBLY__) */ 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci#endif /* !(_SPARC64_PGTABLE_H) */ 1127