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