162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _ASM_POWERPC_BOOK3S_64_PGTABLE_H_
362306a36Sopenharmony_ci#define _ASM_POWERPC_BOOK3S_64_PGTABLE_H_
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <asm-generic/pgtable-nop4d.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __ASSEMBLY__
862306a36Sopenharmony_ci#include <linux/mmdebug.h>
962306a36Sopenharmony_ci#include <linux/bug.h>
1062306a36Sopenharmony_ci#include <linux/sizes.h>
1162306a36Sopenharmony_ci#endif
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci/*
1462306a36Sopenharmony_ci * Common bits between hash and Radix page table
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define _PAGE_EXEC		0x00001 /* execute permission */
1862306a36Sopenharmony_ci#define _PAGE_WRITE		0x00002 /* write access allowed */
1962306a36Sopenharmony_ci#define _PAGE_READ		0x00004	/* read access allowed */
2062306a36Sopenharmony_ci#define _PAGE_RW		(_PAGE_READ | _PAGE_WRITE)
2162306a36Sopenharmony_ci#define _PAGE_RWX		(_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC)
2262306a36Sopenharmony_ci#define _PAGE_PRIVILEGED	0x00008 /* kernel access only */
2362306a36Sopenharmony_ci#define _PAGE_SAO		0x00010 /* Strong access order */
2462306a36Sopenharmony_ci#define _PAGE_NON_IDEMPOTENT	0x00020 /* non idempotent memory */
2562306a36Sopenharmony_ci#define _PAGE_TOLERANT		0x00030 /* tolerant memory, cache inhibited */
2662306a36Sopenharmony_ci#define _PAGE_DIRTY		0x00080 /* C: page changed */
2762306a36Sopenharmony_ci#define _PAGE_ACCESSED		0x00100 /* R: page referenced */
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci * Software bits
3062306a36Sopenharmony_ci */
3162306a36Sopenharmony_ci#define _RPAGE_SW0		0x2000000000000000UL
3262306a36Sopenharmony_ci#define _RPAGE_SW1		0x00800
3362306a36Sopenharmony_ci#define _RPAGE_SW2		0x00400
3462306a36Sopenharmony_ci#define _RPAGE_SW3		0x00200
3562306a36Sopenharmony_ci#define _RPAGE_RSV1		0x00040UL
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define _RPAGE_PKEY_BIT4	0x1000000000000000UL
3862306a36Sopenharmony_ci#define _RPAGE_PKEY_BIT3	0x0800000000000000UL
3962306a36Sopenharmony_ci#define _RPAGE_PKEY_BIT2	0x0400000000000000UL
4062306a36Sopenharmony_ci#define _RPAGE_PKEY_BIT1	0x0200000000000000UL
4162306a36Sopenharmony_ci#define _RPAGE_PKEY_BIT0	0x0100000000000000UL
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#define _PAGE_PTE		0x4000000000000000UL	/* distinguishes PTEs from pointers */
4462306a36Sopenharmony_ci#define _PAGE_PRESENT		0x8000000000000000UL	/* pte contains a translation */
4562306a36Sopenharmony_ci/*
4662306a36Sopenharmony_ci * We need to mark a pmd pte invalid while splitting. We can do that by clearing
4762306a36Sopenharmony_ci * the _PAGE_PRESENT bit. But then that will be taken as a swap pte. In order to
4862306a36Sopenharmony_ci * differentiate between two use a SW field when invalidating.
4962306a36Sopenharmony_ci *
5062306a36Sopenharmony_ci * We do that temporary invalidate for regular pte entry in ptep_set_access_flags
5162306a36Sopenharmony_ci *
5262306a36Sopenharmony_ci * This is used only when _PAGE_PRESENT is cleared.
5362306a36Sopenharmony_ci */
5462306a36Sopenharmony_ci#define _PAGE_INVALID		_RPAGE_SW0
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/*
5762306a36Sopenharmony_ci * Top and bottom bits of RPN which can be used by hash
5862306a36Sopenharmony_ci * translation mode, because we expect them to be zero
5962306a36Sopenharmony_ci * otherwise.
6062306a36Sopenharmony_ci */
6162306a36Sopenharmony_ci#define _RPAGE_RPN0		0x01000
6262306a36Sopenharmony_ci#define _RPAGE_RPN1		0x02000
6362306a36Sopenharmony_ci#define _RPAGE_RPN43		0x0080000000000000UL
6462306a36Sopenharmony_ci#define _RPAGE_RPN42		0x0040000000000000UL
6562306a36Sopenharmony_ci#define _RPAGE_RPN41		0x0020000000000000UL
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci/* Max physical address bit as per radix table */
6862306a36Sopenharmony_ci#define _RPAGE_PA_MAX		56
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/*
7162306a36Sopenharmony_ci * Max physical address bit we will use for now.
7262306a36Sopenharmony_ci *
7362306a36Sopenharmony_ci * This is mostly a hardware limitation and for now Power9 has
7462306a36Sopenharmony_ci * a 51 bit limit.
7562306a36Sopenharmony_ci *
7662306a36Sopenharmony_ci * This is different from the number of physical bit required to address
7762306a36Sopenharmony_ci * the last byte of memory. That is defined by MAX_PHYSMEM_BITS.
7862306a36Sopenharmony_ci * MAX_PHYSMEM_BITS is a linux limitation imposed by the maximum
7962306a36Sopenharmony_ci * number of sections we can support (SECTIONS_SHIFT).
8062306a36Sopenharmony_ci *
8162306a36Sopenharmony_ci * This is different from Radix page table limitation above and
8262306a36Sopenharmony_ci * should always be less than that. The limit is done such that
8362306a36Sopenharmony_ci * we can overload the bits between _RPAGE_PA_MAX and _PAGE_PA_MAX
8462306a36Sopenharmony_ci * for hash linux page table specific bits.
8562306a36Sopenharmony_ci *
8662306a36Sopenharmony_ci * In order to be compatible with future hardware generations we keep
8762306a36Sopenharmony_ci * some offsets and limit this for now to 53
8862306a36Sopenharmony_ci */
8962306a36Sopenharmony_ci#define _PAGE_PA_MAX		53
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci#define _PAGE_SOFT_DIRTY	_RPAGE_SW3 /* software: software dirty tracking */
9262306a36Sopenharmony_ci#define _PAGE_SPECIAL		_RPAGE_SW2 /* software: special page */
9362306a36Sopenharmony_ci#define _PAGE_DEVMAP		_RPAGE_SW1 /* software: ZONE_DEVICE page */
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/*
9662306a36Sopenharmony_ci * Drivers request for cache inhibited pte mapping using _PAGE_NO_CACHE
9762306a36Sopenharmony_ci * Instead of fixing all of them, add an alternate define which
9862306a36Sopenharmony_ci * maps CI pte mapping.
9962306a36Sopenharmony_ci */
10062306a36Sopenharmony_ci#define _PAGE_NO_CACHE		_PAGE_TOLERANT
10162306a36Sopenharmony_ci/*
10262306a36Sopenharmony_ci * We support _RPAGE_PA_MAX bit real address in pte. On the linux side
10362306a36Sopenharmony_ci * we are limited by _PAGE_PA_MAX. Clear everything above _PAGE_PA_MAX
10462306a36Sopenharmony_ci * and every thing below PAGE_SHIFT;
10562306a36Sopenharmony_ci */
10662306a36Sopenharmony_ci#define PTE_RPN_MASK	(((1UL << _PAGE_PA_MAX) - 1) & (PAGE_MASK))
10762306a36Sopenharmony_ci#define PTE_RPN_SHIFT	PAGE_SHIFT
10862306a36Sopenharmony_ci/*
10962306a36Sopenharmony_ci * set of bits not changed in pmd_modify. Even though we have hash specific bits
11062306a36Sopenharmony_ci * in here, on radix we expect them to be zero.
11162306a36Sopenharmony_ci */
11262306a36Sopenharmony_ci#define _HPAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
11362306a36Sopenharmony_ci			 _PAGE_ACCESSED | H_PAGE_THP_HUGE | _PAGE_PTE | \
11462306a36Sopenharmony_ci			 _PAGE_SOFT_DIRTY | _PAGE_DEVMAP)
11562306a36Sopenharmony_ci/*
11662306a36Sopenharmony_ci * user access blocked by key
11762306a36Sopenharmony_ci */
11862306a36Sopenharmony_ci#define _PAGE_KERNEL_RW		(_PAGE_PRIVILEGED | _PAGE_RW | _PAGE_DIRTY)
11962306a36Sopenharmony_ci#define _PAGE_KERNEL_RO		 (_PAGE_PRIVILEGED | _PAGE_READ)
12062306a36Sopenharmony_ci#define _PAGE_KERNEL_ROX	 (_PAGE_PRIVILEGED | _PAGE_READ | _PAGE_EXEC)
12162306a36Sopenharmony_ci#define _PAGE_KERNEL_RWX	(_PAGE_PRIVILEGED | _PAGE_DIRTY | _PAGE_RW | _PAGE_EXEC)
12262306a36Sopenharmony_ci/*
12362306a36Sopenharmony_ci * _PAGE_CHG_MASK masks of bits that are to be preserved across
12462306a36Sopenharmony_ci * pgprot changes
12562306a36Sopenharmony_ci */
12662306a36Sopenharmony_ci#define _PAGE_CHG_MASK	(PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
12762306a36Sopenharmony_ci			 _PAGE_ACCESSED | _PAGE_SPECIAL | _PAGE_PTE |	\
12862306a36Sopenharmony_ci			 _PAGE_SOFT_DIRTY | _PAGE_DEVMAP)
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci/*
13162306a36Sopenharmony_ci * We define 2 sets of base prot bits, one for basic pages (ie,
13262306a36Sopenharmony_ci * cacheable kernel and user pages) and one for non cacheable
13362306a36Sopenharmony_ci * pages. We always set _PAGE_COHERENT when SMP is enabled or
13462306a36Sopenharmony_ci * the processor might need it for DMA coherency.
13562306a36Sopenharmony_ci */
13662306a36Sopenharmony_ci#define _PAGE_BASE_NC	(_PAGE_PRESENT | _PAGE_ACCESSED)
13762306a36Sopenharmony_ci#define _PAGE_BASE	(_PAGE_BASE_NC)
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci/* Permission masks used to generate the __P and __S table,
14062306a36Sopenharmony_ci *
14162306a36Sopenharmony_ci * Note:__pgprot is defined in arch/powerpc/include/asm/page.h
14262306a36Sopenharmony_ci *
14362306a36Sopenharmony_ci * Write permissions imply read permissions for now (we could make write-only
14462306a36Sopenharmony_ci * pages on BookE but we don't bother for now). Execute permission control is
14562306a36Sopenharmony_ci * possible on platforms that define _PAGE_EXEC
14662306a36Sopenharmony_ci */
14762306a36Sopenharmony_ci#define PAGE_NONE	__pgprot(_PAGE_BASE | _PAGE_PRIVILEGED)
14862306a36Sopenharmony_ci#define PAGE_SHARED	__pgprot(_PAGE_BASE | _PAGE_RW)
14962306a36Sopenharmony_ci#define PAGE_SHARED_X	__pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_EXEC)
15062306a36Sopenharmony_ci#define PAGE_COPY	__pgprot(_PAGE_BASE | _PAGE_READ)
15162306a36Sopenharmony_ci#define PAGE_COPY_X	__pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC)
15262306a36Sopenharmony_ci#define PAGE_READONLY	__pgprot(_PAGE_BASE | _PAGE_READ)
15362306a36Sopenharmony_ci#define PAGE_READONLY_X	__pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_EXEC)
15462306a36Sopenharmony_ci/* Radix only, Hash uses PAGE_READONLY_X + execute-only pkey instead */
15562306a36Sopenharmony_ci#define PAGE_EXECONLY	__pgprot(_PAGE_BASE | _PAGE_EXEC)
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci/* Permission masks used for kernel mappings */
15862306a36Sopenharmony_ci#define PAGE_KERNEL	__pgprot(_PAGE_BASE | _PAGE_KERNEL_RW)
15962306a36Sopenharmony_ci#define PAGE_KERNEL_NC	__pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | _PAGE_TOLERANT)
16062306a36Sopenharmony_ci#define PAGE_KERNEL_NCG	__pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | _PAGE_NON_IDEMPOTENT)
16162306a36Sopenharmony_ci#define PAGE_KERNEL_X	__pgprot(_PAGE_BASE | _PAGE_KERNEL_RWX)
16262306a36Sopenharmony_ci#define PAGE_KERNEL_RO	__pgprot(_PAGE_BASE | _PAGE_KERNEL_RO)
16362306a36Sopenharmony_ci#define PAGE_KERNEL_ROX	__pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX)
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci#ifndef __ASSEMBLY__
16662306a36Sopenharmony_ci/*
16762306a36Sopenharmony_ci * page table defines
16862306a36Sopenharmony_ci */
16962306a36Sopenharmony_ciextern unsigned long __pte_index_size;
17062306a36Sopenharmony_ciextern unsigned long __pmd_index_size;
17162306a36Sopenharmony_ciextern unsigned long __pud_index_size;
17262306a36Sopenharmony_ciextern unsigned long __pgd_index_size;
17362306a36Sopenharmony_ciextern unsigned long __pud_cache_index;
17462306a36Sopenharmony_ci#define PTE_INDEX_SIZE  __pte_index_size
17562306a36Sopenharmony_ci#define PMD_INDEX_SIZE  __pmd_index_size
17662306a36Sopenharmony_ci#define PUD_INDEX_SIZE  __pud_index_size
17762306a36Sopenharmony_ci#define PGD_INDEX_SIZE  __pgd_index_size
17862306a36Sopenharmony_ci/* pmd table use page table fragments */
17962306a36Sopenharmony_ci#define PMD_CACHE_INDEX  0
18062306a36Sopenharmony_ci#define PUD_CACHE_INDEX __pud_cache_index
18162306a36Sopenharmony_ci/*
18262306a36Sopenharmony_ci * Because of use of pte fragments and THP, size of page table
18362306a36Sopenharmony_ci * are not always derived out of index size above.
18462306a36Sopenharmony_ci */
18562306a36Sopenharmony_ciextern unsigned long __pte_table_size;
18662306a36Sopenharmony_ciextern unsigned long __pmd_table_size;
18762306a36Sopenharmony_ciextern unsigned long __pud_table_size;
18862306a36Sopenharmony_ciextern unsigned long __pgd_table_size;
18962306a36Sopenharmony_ci#define PTE_TABLE_SIZE	__pte_table_size
19062306a36Sopenharmony_ci#define PMD_TABLE_SIZE	__pmd_table_size
19162306a36Sopenharmony_ci#define PUD_TABLE_SIZE	__pud_table_size
19262306a36Sopenharmony_ci#define PGD_TABLE_SIZE	__pgd_table_size
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ciextern unsigned long __pmd_val_bits;
19562306a36Sopenharmony_ciextern unsigned long __pud_val_bits;
19662306a36Sopenharmony_ciextern unsigned long __pgd_val_bits;
19762306a36Sopenharmony_ci#define PMD_VAL_BITS	__pmd_val_bits
19862306a36Sopenharmony_ci#define PUD_VAL_BITS	__pud_val_bits
19962306a36Sopenharmony_ci#define PGD_VAL_BITS	__pgd_val_bits
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ciextern unsigned long __pte_frag_nr;
20262306a36Sopenharmony_ci#define PTE_FRAG_NR __pte_frag_nr
20362306a36Sopenharmony_ciextern unsigned long __pte_frag_size_shift;
20462306a36Sopenharmony_ci#define PTE_FRAG_SIZE_SHIFT __pte_frag_size_shift
20562306a36Sopenharmony_ci#define PTE_FRAG_SIZE (1UL << PTE_FRAG_SIZE_SHIFT)
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ciextern unsigned long __pmd_frag_nr;
20862306a36Sopenharmony_ci#define PMD_FRAG_NR __pmd_frag_nr
20962306a36Sopenharmony_ciextern unsigned long __pmd_frag_size_shift;
21062306a36Sopenharmony_ci#define PMD_FRAG_SIZE_SHIFT __pmd_frag_size_shift
21162306a36Sopenharmony_ci#define PMD_FRAG_SIZE (1UL << PMD_FRAG_SIZE_SHIFT)
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci#define PTRS_PER_PTE	(1 << PTE_INDEX_SIZE)
21462306a36Sopenharmony_ci#define PTRS_PER_PMD	(1 << PMD_INDEX_SIZE)
21562306a36Sopenharmony_ci#define PTRS_PER_PUD	(1 << PUD_INDEX_SIZE)
21662306a36Sopenharmony_ci#define PTRS_PER_PGD	(1 << PGD_INDEX_SIZE)
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci#define MAX_PTRS_PER_PTE ((H_PTRS_PER_PTE > R_PTRS_PER_PTE) ? H_PTRS_PER_PTE : R_PTRS_PER_PTE)
21962306a36Sopenharmony_ci#define MAX_PTRS_PER_PMD ((H_PTRS_PER_PMD > R_PTRS_PER_PMD) ? H_PTRS_PER_PMD : R_PTRS_PER_PMD)
22062306a36Sopenharmony_ci#define MAX_PTRS_PER_PUD ((H_PTRS_PER_PUD > R_PTRS_PER_PUD) ? H_PTRS_PER_PUD : R_PTRS_PER_PUD)
22162306a36Sopenharmony_ci#define MAX_PTRS_PER_PGD	(1 << (H_PGD_INDEX_SIZE > RADIX_PGD_INDEX_SIZE ? \
22262306a36Sopenharmony_ci				       H_PGD_INDEX_SIZE : RADIX_PGD_INDEX_SIZE))
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci/* PMD_SHIFT determines what a second-level page table entry can map */
22562306a36Sopenharmony_ci#define PMD_SHIFT	(PAGE_SHIFT + PTE_INDEX_SIZE)
22662306a36Sopenharmony_ci#define PMD_SIZE	(1UL << PMD_SHIFT)
22762306a36Sopenharmony_ci#define PMD_MASK	(~(PMD_SIZE-1))
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci/* PUD_SHIFT determines what a third-level page table entry can map */
23062306a36Sopenharmony_ci#define PUD_SHIFT	(PMD_SHIFT + PMD_INDEX_SIZE)
23162306a36Sopenharmony_ci#define PUD_SIZE	(1UL << PUD_SHIFT)
23262306a36Sopenharmony_ci#define PUD_MASK	(~(PUD_SIZE-1))
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
23562306a36Sopenharmony_ci#define PGDIR_SHIFT	(PUD_SHIFT + PUD_INDEX_SIZE)
23662306a36Sopenharmony_ci#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
23762306a36Sopenharmony_ci#define PGDIR_MASK	(~(PGDIR_SIZE-1))
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci/* Bits to mask out from a PMD to get to the PTE page */
24062306a36Sopenharmony_ci#define PMD_MASKED_BITS		0xc0000000000000ffUL
24162306a36Sopenharmony_ci/* Bits to mask out from a PUD to get to the PMD page */
24262306a36Sopenharmony_ci#define PUD_MASKED_BITS		0xc0000000000000ffUL
24362306a36Sopenharmony_ci/* Bits to mask out from a PGD to get to the PUD page */
24462306a36Sopenharmony_ci#define P4D_MASKED_BITS		0xc0000000000000ffUL
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci/*
24762306a36Sopenharmony_ci * Used as an indicator for rcu callback functions
24862306a36Sopenharmony_ci */
24962306a36Sopenharmony_cienum pgtable_index {
25062306a36Sopenharmony_ci	PTE_INDEX = 0,
25162306a36Sopenharmony_ci	PMD_INDEX,
25262306a36Sopenharmony_ci	PUD_INDEX,
25362306a36Sopenharmony_ci	PGD_INDEX,
25462306a36Sopenharmony_ci	/*
25562306a36Sopenharmony_ci	 * Below are used with 4k page size and hugetlb
25662306a36Sopenharmony_ci	 */
25762306a36Sopenharmony_ci	HTLB_16M_INDEX,
25862306a36Sopenharmony_ci	HTLB_16G_INDEX,
25962306a36Sopenharmony_ci};
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ciextern unsigned long __vmalloc_start;
26262306a36Sopenharmony_ciextern unsigned long __vmalloc_end;
26362306a36Sopenharmony_ci#define VMALLOC_START	__vmalloc_start
26462306a36Sopenharmony_ci#define VMALLOC_END	__vmalloc_end
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cistatic inline unsigned int ioremap_max_order(void)
26762306a36Sopenharmony_ci{
26862306a36Sopenharmony_ci	if (radix_enabled())
26962306a36Sopenharmony_ci		return PUD_SHIFT;
27062306a36Sopenharmony_ci	return 7 + PAGE_SHIFT; /* default from linux/vmalloc.h */
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci#define IOREMAP_MAX_ORDER ioremap_max_order()
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ciextern unsigned long __kernel_virt_start;
27562306a36Sopenharmony_ciextern unsigned long __kernel_io_start;
27662306a36Sopenharmony_ciextern unsigned long __kernel_io_end;
27762306a36Sopenharmony_ci#define KERN_VIRT_START __kernel_virt_start
27862306a36Sopenharmony_ci#define KERN_IO_START  __kernel_io_start
27962306a36Sopenharmony_ci#define KERN_IO_END __kernel_io_end
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ciextern struct page *vmemmap;
28262306a36Sopenharmony_ciextern unsigned long pci_io_base;
28362306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci#include <asm/book3s/64/hash.h>
28662306a36Sopenharmony_ci#include <asm/book3s/64/radix.h>
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci#if H_MAX_PHYSMEM_BITS > R_MAX_PHYSMEM_BITS
28962306a36Sopenharmony_ci#define  MAX_PHYSMEM_BITS	H_MAX_PHYSMEM_BITS
29062306a36Sopenharmony_ci#else
29162306a36Sopenharmony_ci#define  MAX_PHYSMEM_BITS	R_MAX_PHYSMEM_BITS
29262306a36Sopenharmony_ci#endif
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci#ifdef CONFIG_PPC_64K_PAGES
29662306a36Sopenharmony_ci#include <asm/book3s/64/pgtable-64k.h>
29762306a36Sopenharmony_ci#else
29862306a36Sopenharmony_ci#include <asm/book3s/64/pgtable-4k.h>
29962306a36Sopenharmony_ci#endif
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci#include <asm/barrier.h>
30262306a36Sopenharmony_ci/*
30362306a36Sopenharmony_ci * IO space itself carved into the PIO region (ISA and PHB IO space) and
30462306a36Sopenharmony_ci * the ioremap space
30562306a36Sopenharmony_ci *
30662306a36Sopenharmony_ci *  ISA_IO_BASE = KERN_IO_START, 64K reserved area
30762306a36Sopenharmony_ci *  PHB_IO_BASE = ISA_IO_BASE + 64K to ISA_IO_BASE + 2G, PHB IO spaces
30862306a36Sopenharmony_ci * IOREMAP_BASE = ISA_IO_BASE + 2G to VMALLOC_START + PGTABLE_RANGE
30962306a36Sopenharmony_ci */
31062306a36Sopenharmony_ci#define FULL_IO_SIZE	0x80000000ul
31162306a36Sopenharmony_ci#define  ISA_IO_BASE	(KERN_IO_START)
31262306a36Sopenharmony_ci#define  ISA_IO_END	(KERN_IO_START + 0x10000ul)
31362306a36Sopenharmony_ci#define  PHB_IO_BASE	(ISA_IO_END)
31462306a36Sopenharmony_ci#define  PHB_IO_END	(KERN_IO_START + FULL_IO_SIZE)
31562306a36Sopenharmony_ci#define IOREMAP_BASE	(PHB_IO_END)
31662306a36Sopenharmony_ci#define IOREMAP_START	(ioremap_bot)
31762306a36Sopenharmony_ci#define IOREMAP_END	(KERN_IO_END - FIXADDR_SIZE)
31862306a36Sopenharmony_ci#define FIXADDR_SIZE	SZ_32M
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci#ifndef __ASSEMBLY__
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci/*
32362306a36Sopenharmony_ci * This is the default implementation of various PTE accessors, it's
32462306a36Sopenharmony_ci * used in all cases except Book3S with 64K pages where we have a
32562306a36Sopenharmony_ci * concept of sub-pages
32662306a36Sopenharmony_ci */
32762306a36Sopenharmony_ci#ifndef __real_pte
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci#define __real_pte(e, p, o)		((real_pte_t){(e)})
33062306a36Sopenharmony_ci#define __rpte_to_pte(r)	((r).pte)
33162306a36Sopenharmony_ci#define __rpte_to_hidx(r,index)	(pte_val(__rpte_to_pte(r)) >> H_PAGE_F_GIX_SHIFT)
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci#define pte_iterate_hashed_subpages(rpte, psize, va, index, shift)       \
33462306a36Sopenharmony_ci	do {							         \
33562306a36Sopenharmony_ci		index = 0;					         \
33662306a36Sopenharmony_ci		shift = mmu_psize_defs[psize].shift;		         \
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci#define pte_iterate_hashed_end() } while(0)
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci/*
34162306a36Sopenharmony_ci * We expect this to be called only for user addresses or kernel virtual
34262306a36Sopenharmony_ci * addresses other than the linear mapping.
34362306a36Sopenharmony_ci */
34462306a36Sopenharmony_ci#define pte_pagesize_index(mm, addr, pte)	MMU_PAGE_4K
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci#endif /* __real_pte */
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_cistatic inline unsigned long pte_update(struct mm_struct *mm, unsigned long addr,
34962306a36Sopenharmony_ci				       pte_t *ptep, unsigned long clr,
35062306a36Sopenharmony_ci				       unsigned long set, int huge)
35162306a36Sopenharmony_ci{
35262306a36Sopenharmony_ci	if (radix_enabled())
35362306a36Sopenharmony_ci		return radix__pte_update(mm, addr, ptep, clr, set, huge);
35462306a36Sopenharmony_ci	return hash__pte_update(mm, addr, ptep, clr, set, huge);
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci/*
35762306a36Sopenharmony_ci * For hash even if we have _PAGE_ACCESSED = 0, we do a pte_update.
35862306a36Sopenharmony_ci * We currently remove entries from the hashtable regardless of whether
35962306a36Sopenharmony_ci * the entry was young or dirty.
36062306a36Sopenharmony_ci *
36162306a36Sopenharmony_ci * We should be more intelligent about this but for the moment we override
36262306a36Sopenharmony_ci * these functions and force a tlb flush unconditionally
36362306a36Sopenharmony_ci * For radix: H_PAGE_HASHPTE should be zero. Hence we can use the same
36462306a36Sopenharmony_ci * function for both hash and radix.
36562306a36Sopenharmony_ci */
36662306a36Sopenharmony_cistatic inline int __ptep_test_and_clear_young(struct mm_struct *mm,
36762306a36Sopenharmony_ci					      unsigned long addr, pte_t *ptep)
36862306a36Sopenharmony_ci{
36962306a36Sopenharmony_ci	unsigned long old;
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	if ((pte_raw(*ptep) & cpu_to_be64(_PAGE_ACCESSED | H_PAGE_HASHPTE)) == 0)
37262306a36Sopenharmony_ci		return 0;
37362306a36Sopenharmony_ci	old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
37462306a36Sopenharmony_ci	return (old & _PAGE_ACCESSED) != 0;
37562306a36Sopenharmony_ci}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
37862306a36Sopenharmony_ci#define ptep_test_and_clear_young(__vma, __addr, __ptep)	\
37962306a36Sopenharmony_ci({								\
38062306a36Sopenharmony_ci	__ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \
38162306a36Sopenharmony_ci})
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci/*
38462306a36Sopenharmony_ci * On Book3S CPUs, clearing the accessed bit without a TLB flush
38562306a36Sopenharmony_ci * doesn't cause data corruption. [ It could cause incorrect
38662306a36Sopenharmony_ci * page aging and the (mistaken) reclaim of hot pages, but the
38762306a36Sopenharmony_ci * chance of that should be relatively low. ]
38862306a36Sopenharmony_ci *
38962306a36Sopenharmony_ci * So as a performance optimization don't flush the TLB when
39062306a36Sopenharmony_ci * clearing the accessed bit, it will eventually be flushed by
39162306a36Sopenharmony_ci * a context switch or a VM operation anyway. [ In the rare
39262306a36Sopenharmony_ci * event of it not getting flushed for a long time the delay
39362306a36Sopenharmony_ci * shouldn't really matter because there's no real memory
39462306a36Sopenharmony_ci * pressure for swapout to react to. ]
39562306a36Sopenharmony_ci *
39662306a36Sopenharmony_ci * Note: this optimisation also exists in pte_needs_flush() and
39762306a36Sopenharmony_ci * huge_pmd_needs_flush().
39862306a36Sopenharmony_ci */
39962306a36Sopenharmony_ci#define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
40062306a36Sopenharmony_ci#define ptep_clear_flush_young ptep_test_and_clear_young
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci#define __HAVE_ARCH_PMDP_CLEAR_YOUNG_FLUSH
40362306a36Sopenharmony_ci#define pmdp_clear_flush_young pmdp_test_and_clear_young
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_cistatic inline int pte_write(pte_t pte)
40662306a36Sopenharmony_ci{
40762306a36Sopenharmony_ci	return !!(pte_raw(pte) & cpu_to_be64(_PAGE_WRITE));
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_cistatic inline int pte_read(pte_t pte)
41162306a36Sopenharmony_ci{
41262306a36Sopenharmony_ci	return !!(pte_raw(pte) & cpu_to_be64(_PAGE_READ));
41362306a36Sopenharmony_ci}
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci#define __HAVE_ARCH_PTEP_SET_WRPROTECT
41662306a36Sopenharmony_cistatic inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
41762306a36Sopenharmony_ci				      pte_t *ptep)
41862306a36Sopenharmony_ci{
41962306a36Sopenharmony_ci	if (pte_write(*ptep))
42062306a36Sopenharmony_ci		pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 0);
42162306a36Sopenharmony_ci}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci#define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
42462306a36Sopenharmony_cistatic inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
42562306a36Sopenharmony_ci					   unsigned long addr, pte_t *ptep)
42662306a36Sopenharmony_ci{
42762306a36Sopenharmony_ci	if (pte_write(*ptep))
42862306a36Sopenharmony_ci		pte_update(mm, addr, ptep, _PAGE_WRITE, 0, 1);
42962306a36Sopenharmony_ci}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
43262306a36Sopenharmony_cistatic inline pte_t ptep_get_and_clear(struct mm_struct *mm,
43362306a36Sopenharmony_ci				       unsigned long addr, pte_t *ptep)
43462306a36Sopenharmony_ci{
43562306a36Sopenharmony_ci	unsigned long old = pte_update(mm, addr, ptep, ~0UL, 0, 0);
43662306a36Sopenharmony_ci	return __pte(old);
43762306a36Sopenharmony_ci}
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci#define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL
44062306a36Sopenharmony_cistatic inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
44162306a36Sopenharmony_ci					    unsigned long addr,
44262306a36Sopenharmony_ci					    pte_t *ptep, int full)
44362306a36Sopenharmony_ci{
44462306a36Sopenharmony_ci	if (full && radix_enabled()) {
44562306a36Sopenharmony_ci		/*
44662306a36Sopenharmony_ci		 * We know that this is a full mm pte clear and
44762306a36Sopenharmony_ci		 * hence can be sure there is no parallel set_pte.
44862306a36Sopenharmony_ci		 */
44962306a36Sopenharmony_ci		return radix__ptep_get_and_clear_full(mm, addr, ptep, full);
45062306a36Sopenharmony_ci	}
45162306a36Sopenharmony_ci	return ptep_get_and_clear(mm, addr, ptep);
45262306a36Sopenharmony_ci}
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_cistatic inline void pte_clear(struct mm_struct *mm, unsigned long addr,
45662306a36Sopenharmony_ci			     pte_t * ptep)
45762306a36Sopenharmony_ci{
45862306a36Sopenharmony_ci	pte_update(mm, addr, ptep, ~0UL, 0, 0);
45962306a36Sopenharmony_ci}
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_cistatic inline int pte_dirty(pte_t pte)
46262306a36Sopenharmony_ci{
46362306a36Sopenharmony_ci	return !!(pte_raw(pte) & cpu_to_be64(_PAGE_DIRTY));
46462306a36Sopenharmony_ci}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_cistatic inline int pte_young(pte_t pte)
46762306a36Sopenharmony_ci{
46862306a36Sopenharmony_ci	return !!(pte_raw(pte) & cpu_to_be64(_PAGE_ACCESSED));
46962306a36Sopenharmony_ci}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_cistatic inline int pte_special(pte_t pte)
47262306a36Sopenharmony_ci{
47362306a36Sopenharmony_ci	return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SPECIAL));
47462306a36Sopenharmony_ci}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_cistatic inline bool pte_exec(pte_t pte)
47762306a36Sopenharmony_ci{
47862306a36Sopenharmony_ci	return !!(pte_raw(pte) & cpu_to_be64(_PAGE_EXEC));
47962306a36Sopenharmony_ci}
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
48362306a36Sopenharmony_cistatic inline bool pte_soft_dirty(pte_t pte)
48462306a36Sopenharmony_ci{
48562306a36Sopenharmony_ci	return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SOFT_DIRTY));
48662306a36Sopenharmony_ci}
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_cistatic inline pte_t pte_mksoft_dirty(pte_t pte)
48962306a36Sopenharmony_ci{
49062306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SOFT_DIRTY));
49162306a36Sopenharmony_ci}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_cistatic inline pte_t pte_clear_soft_dirty(pte_t pte)
49462306a36Sopenharmony_ci{
49562306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_SOFT_DIRTY));
49662306a36Sopenharmony_ci}
49762306a36Sopenharmony_ci#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci#ifdef CONFIG_NUMA_BALANCING
50062306a36Sopenharmony_cistatic inline int pte_protnone(pte_t pte)
50162306a36Sopenharmony_ci{
50262306a36Sopenharmony_ci	return (pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_PTE | _PAGE_RWX)) ==
50362306a36Sopenharmony_ci		cpu_to_be64(_PAGE_PRESENT | _PAGE_PTE);
50462306a36Sopenharmony_ci}
50562306a36Sopenharmony_ci#endif /* CONFIG_NUMA_BALANCING */
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_cistatic inline bool pte_hw_valid(pte_t pte)
50862306a36Sopenharmony_ci{
50962306a36Sopenharmony_ci	return (pte_raw(pte) & cpu_to_be64(_PAGE_PRESENT | _PAGE_PTE)) ==
51062306a36Sopenharmony_ci		cpu_to_be64(_PAGE_PRESENT | _PAGE_PTE);
51162306a36Sopenharmony_ci}
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_cistatic inline int pte_present(pte_t pte)
51462306a36Sopenharmony_ci{
51562306a36Sopenharmony_ci	/*
51662306a36Sopenharmony_ci	 * A pte is considerent present if _PAGE_PRESENT is set.
51762306a36Sopenharmony_ci	 * We also need to consider the pte present which is marked
51862306a36Sopenharmony_ci	 * invalid during ptep_set_access_flags. Hence we look for _PAGE_INVALID
51962306a36Sopenharmony_ci	 * if we find _PAGE_PRESENT cleared.
52062306a36Sopenharmony_ci	 */
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	if (pte_hw_valid(pte))
52362306a36Sopenharmony_ci		return true;
52462306a36Sopenharmony_ci	return (pte_raw(pte) & cpu_to_be64(_PAGE_INVALID | _PAGE_PTE)) ==
52562306a36Sopenharmony_ci		cpu_to_be64(_PAGE_INVALID | _PAGE_PTE);
52662306a36Sopenharmony_ci}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci#ifdef CONFIG_PPC_MEM_KEYS
52962306a36Sopenharmony_ciextern bool arch_pte_access_permitted(u64 pte, bool write, bool execute);
53062306a36Sopenharmony_ci#else
53162306a36Sopenharmony_cistatic inline bool arch_pte_access_permitted(u64 pte, bool write, bool execute)
53262306a36Sopenharmony_ci{
53362306a36Sopenharmony_ci	return true;
53462306a36Sopenharmony_ci}
53562306a36Sopenharmony_ci#endif /* CONFIG_PPC_MEM_KEYS */
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_cistatic inline bool pte_user(pte_t pte)
53862306a36Sopenharmony_ci{
53962306a36Sopenharmony_ci	return !(pte_raw(pte) & cpu_to_be64(_PAGE_PRIVILEGED));
54062306a36Sopenharmony_ci}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci#define pte_access_permitted pte_access_permitted
54362306a36Sopenharmony_cistatic inline bool pte_access_permitted(pte_t pte, bool write)
54462306a36Sopenharmony_ci{
54562306a36Sopenharmony_ci	/*
54662306a36Sopenharmony_ci	 * _PAGE_READ is needed for any access and will be
54762306a36Sopenharmony_ci	 * cleared for PROT_NONE
54862306a36Sopenharmony_ci	 */
54962306a36Sopenharmony_ci	if (!pte_present(pte) || !pte_user(pte) || !pte_read(pte))
55062306a36Sopenharmony_ci		return false;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	if (write && !pte_write(pte))
55362306a36Sopenharmony_ci		return false;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	return arch_pte_access_permitted(pte_val(pte), write, 0);
55662306a36Sopenharmony_ci}
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci/*
55962306a36Sopenharmony_ci * Conversion functions: convert a page and protection to a page entry,
56062306a36Sopenharmony_ci * and a page entry and page directory to the page they refer to.
56162306a36Sopenharmony_ci *
56262306a36Sopenharmony_ci * Even if PTEs can be unsigned long long, a PFN is always an unsigned
56362306a36Sopenharmony_ci * long for now.
56462306a36Sopenharmony_ci */
56562306a36Sopenharmony_cistatic inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	VM_BUG_ON(pfn >> (64 - PAGE_SHIFT));
56862306a36Sopenharmony_ci	VM_BUG_ON((pfn << PAGE_SHIFT) & ~PTE_RPN_MASK);
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	return __pte(((pte_basic_t)pfn << PAGE_SHIFT) | pgprot_val(pgprot) | _PAGE_PTE);
57162306a36Sopenharmony_ci}
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci/* Generic modifiers for PTE bits */
57462306a36Sopenharmony_cistatic inline pte_t pte_wrprotect(pte_t pte)
57562306a36Sopenharmony_ci{
57662306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_WRITE));
57762306a36Sopenharmony_ci}
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_cistatic inline pte_t pte_exprotect(pte_t pte)
58062306a36Sopenharmony_ci{
58162306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_EXEC));
58262306a36Sopenharmony_ci}
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_cistatic inline pte_t pte_mkclean(pte_t pte)
58562306a36Sopenharmony_ci{
58662306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_DIRTY));
58762306a36Sopenharmony_ci}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_cistatic inline pte_t pte_mkold(pte_t pte)
59062306a36Sopenharmony_ci{
59162306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_ACCESSED));
59262306a36Sopenharmony_ci}
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_cistatic inline pte_t pte_mkexec(pte_t pte)
59562306a36Sopenharmony_ci{
59662306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_EXEC));
59762306a36Sopenharmony_ci}
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_cistatic inline pte_t pte_mkwrite_novma(pte_t pte)
60062306a36Sopenharmony_ci{
60162306a36Sopenharmony_ci	/*
60262306a36Sopenharmony_ci	 * write implies read, hence set both
60362306a36Sopenharmony_ci	 */
60462306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_RW));
60562306a36Sopenharmony_ci}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_cistatic inline pte_t pte_mkdirty(pte_t pte)
60862306a36Sopenharmony_ci{
60962306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_DIRTY | _PAGE_SOFT_DIRTY));
61062306a36Sopenharmony_ci}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_cistatic inline pte_t pte_mkyoung(pte_t pte)
61362306a36Sopenharmony_ci{
61462306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_ACCESSED));
61562306a36Sopenharmony_ci}
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_cistatic inline pte_t pte_mkspecial(pte_t pte)
61862306a36Sopenharmony_ci{
61962306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SPECIAL));
62062306a36Sopenharmony_ci}
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_cistatic inline pte_t pte_mkhuge(pte_t pte)
62362306a36Sopenharmony_ci{
62462306a36Sopenharmony_ci	return pte;
62562306a36Sopenharmony_ci}
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_cistatic inline pte_t pte_mkdevmap(pte_t pte)
62862306a36Sopenharmony_ci{
62962306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SPECIAL | _PAGE_DEVMAP));
63062306a36Sopenharmony_ci}
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_cistatic inline pte_t pte_mkprivileged(pte_t pte)
63362306a36Sopenharmony_ci{
63462306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_PRIVILEGED));
63562306a36Sopenharmony_ci}
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_cistatic inline pte_t pte_mkuser(pte_t pte)
63862306a36Sopenharmony_ci{
63962306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_PRIVILEGED));
64062306a36Sopenharmony_ci}
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci/*
64362306a36Sopenharmony_ci * This is potentially called with a pmd as the argument, in which case it's not
64462306a36Sopenharmony_ci * safe to check _PAGE_DEVMAP unless we also confirm that _PAGE_PTE is set.
64562306a36Sopenharmony_ci * That's because the bit we use for _PAGE_DEVMAP is not reserved for software
64662306a36Sopenharmony_ci * use in page directory entries (ie. non-ptes).
64762306a36Sopenharmony_ci */
64862306a36Sopenharmony_cistatic inline int pte_devmap(pte_t pte)
64962306a36Sopenharmony_ci{
65062306a36Sopenharmony_ci	u64 mask = cpu_to_be64(_PAGE_DEVMAP | _PAGE_PTE);
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	return (pte_raw(pte) & mask) == mask;
65362306a36Sopenharmony_ci}
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_cistatic inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
65662306a36Sopenharmony_ci{
65762306a36Sopenharmony_ci	/* FIXME!! check whether this need to be a conditional */
65862306a36Sopenharmony_ci	return __pte_raw((pte_raw(pte) & cpu_to_be64(_PAGE_CHG_MASK)) |
65962306a36Sopenharmony_ci			 cpu_to_be64(pgprot_val(newprot)));
66062306a36Sopenharmony_ci}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci/* Encode and de-code a swap entry */
66362306a36Sopenharmony_ci#define MAX_SWAPFILES_CHECK() do { \
66462306a36Sopenharmony_ci	BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS); \
66562306a36Sopenharmony_ci	/*							\
66662306a36Sopenharmony_ci	 * Don't have overlapping bits with _PAGE_HPTEFLAGS	\
66762306a36Sopenharmony_ci	 * We filter HPTEFLAGS on set_pte.			\
66862306a36Sopenharmony_ci	 */							\
66962306a36Sopenharmony_ci	BUILD_BUG_ON(_PAGE_HPTEFLAGS & SWP_TYPE_MASK); \
67062306a36Sopenharmony_ci	BUILD_BUG_ON(_PAGE_HPTEFLAGS & _PAGE_SWP_SOFT_DIRTY);	\
67162306a36Sopenharmony_ci	BUILD_BUG_ON(_PAGE_HPTEFLAGS & _PAGE_SWP_EXCLUSIVE);	\
67262306a36Sopenharmony_ci	} while (0)
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci#define SWP_TYPE_BITS 5
67562306a36Sopenharmony_ci#define SWP_TYPE_MASK		((1UL << SWP_TYPE_BITS) - 1)
67662306a36Sopenharmony_ci#define __swp_type(x)		((x).val & SWP_TYPE_MASK)
67762306a36Sopenharmony_ci#define __swp_offset(x)		(((x).val & PTE_RPN_MASK) >> PAGE_SHIFT)
67862306a36Sopenharmony_ci#define __swp_entry(type, offset)	((swp_entry_t) { \
67962306a36Sopenharmony_ci				(type) | (((offset) << PAGE_SHIFT) & PTE_RPN_MASK)})
68062306a36Sopenharmony_ci/*
68162306a36Sopenharmony_ci * swp_entry_t must be independent of pte bits. We build a swp_entry_t from
68262306a36Sopenharmony_ci * swap type and offset we get from swap and convert that to pte to find a
68362306a36Sopenharmony_ci * matching pte in linux page table.
68462306a36Sopenharmony_ci * Clear bits not found in swap entries here.
68562306a36Sopenharmony_ci */
68662306a36Sopenharmony_ci#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val((pte)) & ~_PAGE_PTE })
68762306a36Sopenharmony_ci#define __swp_entry_to_pte(x)	__pte((x).val | _PAGE_PTE)
68862306a36Sopenharmony_ci#define __pmd_to_swp_entry(pmd)	(__pte_to_swp_entry(pmd_pte(pmd)))
68962306a36Sopenharmony_ci#define __swp_entry_to_pmd(x)	(pte_pmd(__swp_entry_to_pte(x)))
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci#ifdef CONFIG_MEM_SOFT_DIRTY
69262306a36Sopenharmony_ci#define _PAGE_SWP_SOFT_DIRTY	_PAGE_SOFT_DIRTY
69362306a36Sopenharmony_ci#else
69462306a36Sopenharmony_ci#define _PAGE_SWP_SOFT_DIRTY	0UL
69562306a36Sopenharmony_ci#endif /* CONFIG_MEM_SOFT_DIRTY */
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci#define _PAGE_SWP_EXCLUSIVE	_PAGE_NON_IDEMPOTENT
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
70062306a36Sopenharmony_cistatic inline pte_t pte_swp_mksoft_dirty(pte_t pte)
70162306a36Sopenharmony_ci{
70262306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SWP_SOFT_DIRTY));
70362306a36Sopenharmony_ci}
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_cistatic inline bool pte_swp_soft_dirty(pte_t pte)
70662306a36Sopenharmony_ci{
70762306a36Sopenharmony_ci	return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SWP_SOFT_DIRTY));
70862306a36Sopenharmony_ci}
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_cistatic inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
71162306a36Sopenharmony_ci{
71262306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_SWP_SOFT_DIRTY));
71362306a36Sopenharmony_ci}
71462306a36Sopenharmony_ci#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_cistatic inline pte_t pte_swp_mkexclusive(pte_t pte)
71762306a36Sopenharmony_ci{
71862306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_SWP_EXCLUSIVE));
71962306a36Sopenharmony_ci}
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_cistatic inline int pte_swp_exclusive(pte_t pte)
72262306a36Sopenharmony_ci{
72362306a36Sopenharmony_ci	return !!(pte_raw(pte) & cpu_to_be64(_PAGE_SWP_EXCLUSIVE));
72462306a36Sopenharmony_ci}
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_cistatic inline pte_t pte_swp_clear_exclusive(pte_t pte)
72762306a36Sopenharmony_ci{
72862306a36Sopenharmony_ci	return __pte_raw(pte_raw(pte) & cpu_to_be64(~_PAGE_SWP_EXCLUSIVE));
72962306a36Sopenharmony_ci}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_cistatic inline bool check_pte_access(unsigned long access, unsigned long ptev)
73262306a36Sopenharmony_ci{
73362306a36Sopenharmony_ci	/*
73462306a36Sopenharmony_ci	 * This check for _PAGE_RWX and _PAGE_PRESENT bits
73562306a36Sopenharmony_ci	 */
73662306a36Sopenharmony_ci	if (access & ~ptev)
73762306a36Sopenharmony_ci		return false;
73862306a36Sopenharmony_ci	/*
73962306a36Sopenharmony_ci	 * This check for access to privilege space
74062306a36Sopenharmony_ci	 */
74162306a36Sopenharmony_ci	if ((access & _PAGE_PRIVILEGED) != (ptev & _PAGE_PRIVILEGED))
74262306a36Sopenharmony_ci		return false;
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	return true;
74562306a36Sopenharmony_ci}
74662306a36Sopenharmony_ci/*
74762306a36Sopenharmony_ci * Generic functions with hash/radix callbacks
74862306a36Sopenharmony_ci */
74962306a36Sopenharmony_ci
75062306a36Sopenharmony_cistatic inline void __ptep_set_access_flags(struct vm_area_struct *vma,
75162306a36Sopenharmony_ci					   pte_t *ptep, pte_t entry,
75262306a36Sopenharmony_ci					   unsigned long address,
75362306a36Sopenharmony_ci					   int psize)
75462306a36Sopenharmony_ci{
75562306a36Sopenharmony_ci	if (radix_enabled())
75662306a36Sopenharmony_ci		return radix__ptep_set_access_flags(vma, ptep, entry,
75762306a36Sopenharmony_ci						    address, psize);
75862306a36Sopenharmony_ci	return hash__ptep_set_access_flags(ptep, entry);
75962306a36Sopenharmony_ci}
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci#define __HAVE_ARCH_PTE_SAME
76262306a36Sopenharmony_cistatic inline int pte_same(pte_t pte_a, pte_t pte_b)
76362306a36Sopenharmony_ci{
76462306a36Sopenharmony_ci	if (radix_enabled())
76562306a36Sopenharmony_ci		return radix__pte_same(pte_a, pte_b);
76662306a36Sopenharmony_ci	return hash__pte_same(pte_a, pte_b);
76762306a36Sopenharmony_ci}
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_cistatic inline int pte_none(pte_t pte)
77062306a36Sopenharmony_ci{
77162306a36Sopenharmony_ci	if (radix_enabled())
77262306a36Sopenharmony_ci		return radix__pte_none(pte);
77362306a36Sopenharmony_ci	return hash__pte_none(pte);
77462306a36Sopenharmony_ci}
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_cistatic inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
77762306a36Sopenharmony_ci				pte_t *ptep, pte_t pte, int percpu)
77862306a36Sopenharmony_ci{
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_ci	VM_WARN_ON(!(pte_raw(pte) & cpu_to_be64(_PAGE_PTE)));
78162306a36Sopenharmony_ci	/*
78262306a36Sopenharmony_ci	 * Keep the _PAGE_PTE added till we are sure we handle _PAGE_PTE
78362306a36Sopenharmony_ci	 * in all the callers.
78462306a36Sopenharmony_ci	 */
78562306a36Sopenharmony_ci	pte = __pte_raw(pte_raw(pte) | cpu_to_be64(_PAGE_PTE));
78662306a36Sopenharmony_ci
78762306a36Sopenharmony_ci	if (radix_enabled())
78862306a36Sopenharmony_ci		return radix__set_pte_at(mm, addr, ptep, pte, percpu);
78962306a36Sopenharmony_ci	return hash__set_pte_at(mm, addr, ptep, pte, percpu);
79062306a36Sopenharmony_ci}
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci#define _PAGE_CACHE_CTL	(_PAGE_SAO | _PAGE_NON_IDEMPOTENT | _PAGE_TOLERANT)
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci#define pgprot_noncached pgprot_noncached
79562306a36Sopenharmony_cistatic inline pgprot_t pgprot_noncached(pgprot_t prot)
79662306a36Sopenharmony_ci{
79762306a36Sopenharmony_ci	return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) |
79862306a36Sopenharmony_ci			_PAGE_NON_IDEMPOTENT);
79962306a36Sopenharmony_ci}
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci#define pgprot_noncached_wc pgprot_noncached_wc
80262306a36Sopenharmony_cistatic inline pgprot_t pgprot_noncached_wc(pgprot_t prot)
80362306a36Sopenharmony_ci{
80462306a36Sopenharmony_ci	return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) |
80562306a36Sopenharmony_ci			_PAGE_TOLERANT);
80662306a36Sopenharmony_ci}
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci#define pgprot_cached pgprot_cached
80962306a36Sopenharmony_cistatic inline pgprot_t pgprot_cached(pgprot_t prot)
81062306a36Sopenharmony_ci{
81162306a36Sopenharmony_ci	return __pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL));
81262306a36Sopenharmony_ci}
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci#define pgprot_writecombine pgprot_writecombine
81562306a36Sopenharmony_cistatic inline pgprot_t pgprot_writecombine(pgprot_t prot)
81662306a36Sopenharmony_ci{
81762306a36Sopenharmony_ci	return pgprot_noncached_wc(prot);
81862306a36Sopenharmony_ci}
81962306a36Sopenharmony_ci/*
82062306a36Sopenharmony_ci * check a pte mapping have cache inhibited property
82162306a36Sopenharmony_ci */
82262306a36Sopenharmony_cistatic inline bool pte_ci(pte_t pte)
82362306a36Sopenharmony_ci{
82462306a36Sopenharmony_ci	__be64 pte_v = pte_raw(pte);
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	if (((pte_v & cpu_to_be64(_PAGE_CACHE_CTL)) == cpu_to_be64(_PAGE_TOLERANT)) ||
82762306a36Sopenharmony_ci	    ((pte_v & cpu_to_be64(_PAGE_CACHE_CTL)) == cpu_to_be64(_PAGE_NON_IDEMPOTENT)))
82862306a36Sopenharmony_ci		return true;
82962306a36Sopenharmony_ci	return false;
83062306a36Sopenharmony_ci}
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_cistatic inline void pmd_clear(pmd_t *pmdp)
83362306a36Sopenharmony_ci{
83462306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_DEBUG_VM) && !radix_enabled()) {
83562306a36Sopenharmony_ci		/*
83662306a36Sopenharmony_ci		 * Don't use this if we can possibly have a hash page table
83762306a36Sopenharmony_ci		 * entry mapping this.
83862306a36Sopenharmony_ci		 */
83962306a36Sopenharmony_ci		WARN_ON((pmd_val(*pmdp) & (H_PAGE_HASHPTE | _PAGE_PTE)) == (H_PAGE_HASHPTE | _PAGE_PTE));
84062306a36Sopenharmony_ci	}
84162306a36Sopenharmony_ci	*pmdp = __pmd(0);
84262306a36Sopenharmony_ci}
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_cistatic inline int pmd_none(pmd_t pmd)
84562306a36Sopenharmony_ci{
84662306a36Sopenharmony_ci	return !pmd_raw(pmd);
84762306a36Sopenharmony_ci}
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_cistatic inline int pmd_present(pmd_t pmd)
85062306a36Sopenharmony_ci{
85162306a36Sopenharmony_ci	/*
85262306a36Sopenharmony_ci	 * A pmd is considerent present if _PAGE_PRESENT is set.
85362306a36Sopenharmony_ci	 * We also need to consider the pmd present which is marked
85462306a36Sopenharmony_ci	 * invalid during a split. Hence we look for _PAGE_INVALID
85562306a36Sopenharmony_ci	 * if we find _PAGE_PRESENT cleared.
85662306a36Sopenharmony_ci	 */
85762306a36Sopenharmony_ci	if (pmd_raw(pmd) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID))
85862306a36Sopenharmony_ci		return true;
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci	return false;
86162306a36Sopenharmony_ci}
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_cistatic inline int pmd_is_serializing(pmd_t pmd)
86462306a36Sopenharmony_ci{
86562306a36Sopenharmony_ci	/*
86662306a36Sopenharmony_ci	 * If the pmd is undergoing a split, the _PAGE_PRESENT bit is clear
86762306a36Sopenharmony_ci	 * and _PAGE_INVALID is set (see pmd_present, pmdp_invalidate).
86862306a36Sopenharmony_ci	 *
86962306a36Sopenharmony_ci	 * This condition may also occur when flushing a pmd while flushing
87062306a36Sopenharmony_ci	 * it (see ptep_modify_prot_start), so callers must ensure this
87162306a36Sopenharmony_ci	 * case is fine as well.
87262306a36Sopenharmony_ci	 */
87362306a36Sopenharmony_ci	if ((pmd_raw(pmd) & cpu_to_be64(_PAGE_PRESENT | _PAGE_INVALID)) ==
87462306a36Sopenharmony_ci						cpu_to_be64(_PAGE_INVALID))
87562306a36Sopenharmony_ci		return true;
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	return false;
87862306a36Sopenharmony_ci}
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_cistatic inline int pmd_bad(pmd_t pmd)
88162306a36Sopenharmony_ci{
88262306a36Sopenharmony_ci	if (radix_enabled())
88362306a36Sopenharmony_ci		return radix__pmd_bad(pmd);
88462306a36Sopenharmony_ci	return hash__pmd_bad(pmd);
88562306a36Sopenharmony_ci}
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_cistatic inline void pud_clear(pud_t *pudp)
88862306a36Sopenharmony_ci{
88962306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_DEBUG_VM) && !radix_enabled()) {
89062306a36Sopenharmony_ci		/*
89162306a36Sopenharmony_ci		 * Don't use this if we can possibly have a hash page table
89262306a36Sopenharmony_ci		 * entry mapping this.
89362306a36Sopenharmony_ci		 */
89462306a36Sopenharmony_ci		WARN_ON((pud_val(*pudp) & (H_PAGE_HASHPTE | _PAGE_PTE)) == (H_PAGE_HASHPTE | _PAGE_PTE));
89562306a36Sopenharmony_ci	}
89662306a36Sopenharmony_ci	*pudp = __pud(0);
89762306a36Sopenharmony_ci}
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_cistatic inline int pud_none(pud_t pud)
90062306a36Sopenharmony_ci{
90162306a36Sopenharmony_ci	return !pud_raw(pud);
90262306a36Sopenharmony_ci}
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_cistatic inline int pud_present(pud_t pud)
90562306a36Sopenharmony_ci{
90662306a36Sopenharmony_ci	return !!(pud_raw(pud) & cpu_to_be64(_PAGE_PRESENT));
90762306a36Sopenharmony_ci}
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ciextern struct page *pud_page(pud_t pud);
91062306a36Sopenharmony_ciextern struct page *pmd_page(pmd_t pmd);
91162306a36Sopenharmony_cistatic inline pte_t pud_pte(pud_t pud)
91262306a36Sopenharmony_ci{
91362306a36Sopenharmony_ci	return __pte_raw(pud_raw(pud));
91462306a36Sopenharmony_ci}
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_cistatic inline pud_t pte_pud(pte_t pte)
91762306a36Sopenharmony_ci{
91862306a36Sopenharmony_ci	return __pud_raw(pte_raw(pte));
91962306a36Sopenharmony_ci}
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_cistatic inline pte_t *pudp_ptep(pud_t *pud)
92262306a36Sopenharmony_ci{
92362306a36Sopenharmony_ci	return (pte_t *)pud;
92462306a36Sopenharmony_ci}
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci#define pud_pfn(pud)		pte_pfn(pud_pte(pud))
92762306a36Sopenharmony_ci#define pud_dirty(pud)		pte_dirty(pud_pte(pud))
92862306a36Sopenharmony_ci#define pud_young(pud)		pte_young(pud_pte(pud))
92962306a36Sopenharmony_ci#define pud_mkold(pud)		pte_pud(pte_mkold(pud_pte(pud)))
93062306a36Sopenharmony_ci#define pud_wrprotect(pud)	pte_pud(pte_wrprotect(pud_pte(pud)))
93162306a36Sopenharmony_ci#define pud_mkdirty(pud)	pte_pud(pte_mkdirty(pud_pte(pud)))
93262306a36Sopenharmony_ci#define pud_mkclean(pud)	pte_pud(pte_mkclean(pud_pte(pud)))
93362306a36Sopenharmony_ci#define pud_mkyoung(pud)	pte_pud(pte_mkyoung(pud_pte(pud)))
93462306a36Sopenharmony_ci#define pud_mkwrite(pud)	pte_pud(pte_mkwrite_novma(pud_pte(pud)))
93562306a36Sopenharmony_ci#define pud_write(pud)		pte_write(pud_pte(pud))
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
93862306a36Sopenharmony_ci#define pud_soft_dirty(pmd)    pte_soft_dirty(pud_pte(pud))
93962306a36Sopenharmony_ci#define pud_mksoft_dirty(pmd)  pte_pud(pte_mksoft_dirty(pud_pte(pud)))
94062306a36Sopenharmony_ci#define pud_clear_soft_dirty(pmd) pte_pud(pte_clear_soft_dirty(pud_pte(pud)))
94162306a36Sopenharmony_ci#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_cistatic inline int pud_bad(pud_t pud)
94462306a36Sopenharmony_ci{
94562306a36Sopenharmony_ci	if (radix_enabled())
94662306a36Sopenharmony_ci		return radix__pud_bad(pud);
94762306a36Sopenharmony_ci	return hash__pud_bad(pud);
94862306a36Sopenharmony_ci}
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci#define pud_access_permitted pud_access_permitted
95162306a36Sopenharmony_cistatic inline bool pud_access_permitted(pud_t pud, bool write)
95262306a36Sopenharmony_ci{
95362306a36Sopenharmony_ci	return pte_access_permitted(pud_pte(pud), write);
95462306a36Sopenharmony_ci}
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci#define __p4d_raw(x)	((p4d_t) { __pgd_raw(x) })
95762306a36Sopenharmony_cistatic inline __be64 p4d_raw(p4d_t x)
95862306a36Sopenharmony_ci{
95962306a36Sopenharmony_ci	return pgd_raw(x.pgd);
96062306a36Sopenharmony_ci}
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci#define p4d_write(p4d)		pte_write(p4d_pte(p4d))
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_cistatic inline void p4d_clear(p4d_t *p4dp)
96562306a36Sopenharmony_ci{
96662306a36Sopenharmony_ci	*p4dp = __p4d(0);
96762306a36Sopenharmony_ci}
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_cistatic inline int p4d_none(p4d_t p4d)
97062306a36Sopenharmony_ci{
97162306a36Sopenharmony_ci	return !p4d_raw(p4d);
97262306a36Sopenharmony_ci}
97362306a36Sopenharmony_ci
97462306a36Sopenharmony_cistatic inline int p4d_present(p4d_t p4d)
97562306a36Sopenharmony_ci{
97662306a36Sopenharmony_ci	return !!(p4d_raw(p4d) & cpu_to_be64(_PAGE_PRESENT));
97762306a36Sopenharmony_ci}
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_cistatic inline pte_t p4d_pte(p4d_t p4d)
98062306a36Sopenharmony_ci{
98162306a36Sopenharmony_ci	return __pte_raw(p4d_raw(p4d));
98262306a36Sopenharmony_ci}
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_cistatic inline p4d_t pte_p4d(pte_t pte)
98562306a36Sopenharmony_ci{
98662306a36Sopenharmony_ci	return __p4d_raw(pte_raw(pte));
98762306a36Sopenharmony_ci}
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_cistatic inline int p4d_bad(p4d_t p4d)
99062306a36Sopenharmony_ci{
99162306a36Sopenharmony_ci	if (radix_enabled())
99262306a36Sopenharmony_ci		return radix__p4d_bad(p4d);
99362306a36Sopenharmony_ci	return hash__p4d_bad(p4d);
99462306a36Sopenharmony_ci}
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci#define p4d_access_permitted p4d_access_permitted
99762306a36Sopenharmony_cistatic inline bool p4d_access_permitted(p4d_t p4d, bool write)
99862306a36Sopenharmony_ci{
99962306a36Sopenharmony_ci	return pte_access_permitted(p4d_pte(p4d), write);
100062306a36Sopenharmony_ci}
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ciextern struct page *p4d_page(p4d_t p4d);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci/* Pointers in the page table tree are physical addresses */
100562306a36Sopenharmony_ci#define __pgtable_ptr_val(ptr)	__pa(ptr)
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_cistatic inline pud_t *p4d_pgtable(p4d_t p4d)
100862306a36Sopenharmony_ci{
100962306a36Sopenharmony_ci	return (pud_t *)__va(p4d_val(p4d) & ~P4D_MASKED_BITS);
101062306a36Sopenharmony_ci}
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_cistatic inline pmd_t *pud_pgtable(pud_t pud)
101362306a36Sopenharmony_ci{
101462306a36Sopenharmony_ci	return (pmd_t *)__va(pud_val(pud) & ~PUD_MASKED_BITS);
101562306a36Sopenharmony_ci}
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci#define pte_ERROR(e) \
101862306a36Sopenharmony_ci	pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
101962306a36Sopenharmony_ci#define pmd_ERROR(e) \
102062306a36Sopenharmony_ci	pr_err("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
102162306a36Sopenharmony_ci#define pud_ERROR(e) \
102262306a36Sopenharmony_ci	pr_err("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pud_val(e))
102362306a36Sopenharmony_ci#define pgd_ERROR(e) \
102462306a36Sopenharmony_ci	pr_err("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_cistatic inline int map_kernel_page(unsigned long ea, unsigned long pa, pgprot_t prot)
102762306a36Sopenharmony_ci{
102862306a36Sopenharmony_ci	if (radix_enabled()) {
102962306a36Sopenharmony_ci#if defined(CONFIG_PPC_RADIX_MMU) && defined(DEBUG_VM)
103062306a36Sopenharmony_ci		unsigned long page_size = 1 << mmu_psize_defs[mmu_io_psize].shift;
103162306a36Sopenharmony_ci		WARN((page_size != PAGE_SIZE), "I/O page size != PAGE_SIZE");
103262306a36Sopenharmony_ci#endif
103362306a36Sopenharmony_ci		return radix__map_kernel_page(ea, pa, prot, PAGE_SIZE);
103462306a36Sopenharmony_ci	}
103562306a36Sopenharmony_ci	return hash__map_kernel_page(ea, pa, prot);
103662306a36Sopenharmony_ci}
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_civoid unmap_kernel_page(unsigned long va);
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_cistatic inline int __meminit vmemmap_create_mapping(unsigned long start,
104162306a36Sopenharmony_ci						   unsigned long page_size,
104262306a36Sopenharmony_ci						   unsigned long phys)
104362306a36Sopenharmony_ci{
104462306a36Sopenharmony_ci	if (radix_enabled())
104562306a36Sopenharmony_ci		return radix__vmemmap_create_mapping(start, page_size, phys);
104662306a36Sopenharmony_ci	return hash__vmemmap_create_mapping(start, page_size, phys);
104762306a36Sopenharmony_ci}
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_ci#ifdef CONFIG_MEMORY_HOTPLUG
105062306a36Sopenharmony_cistatic inline void vmemmap_remove_mapping(unsigned long start,
105162306a36Sopenharmony_ci					  unsigned long page_size)
105262306a36Sopenharmony_ci{
105362306a36Sopenharmony_ci	if (radix_enabled())
105462306a36Sopenharmony_ci		return radix__vmemmap_remove_mapping(start, page_size);
105562306a36Sopenharmony_ci	return hash__vmemmap_remove_mapping(start, page_size);
105662306a36Sopenharmony_ci}
105762306a36Sopenharmony_ci#endif
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE)
106062306a36Sopenharmony_cistatic inline void __kernel_map_pages(struct page *page, int numpages, int enable)
106162306a36Sopenharmony_ci{
106262306a36Sopenharmony_ci	if (radix_enabled())
106362306a36Sopenharmony_ci		radix__kernel_map_pages(page, numpages, enable);
106462306a36Sopenharmony_ci	else
106562306a36Sopenharmony_ci		hash__kernel_map_pages(page, numpages, enable);
106662306a36Sopenharmony_ci}
106762306a36Sopenharmony_ci#endif
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_cistatic inline pte_t pmd_pte(pmd_t pmd)
107062306a36Sopenharmony_ci{
107162306a36Sopenharmony_ci	return __pte_raw(pmd_raw(pmd));
107262306a36Sopenharmony_ci}
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_cistatic inline pmd_t pte_pmd(pte_t pte)
107562306a36Sopenharmony_ci{
107662306a36Sopenharmony_ci	return __pmd_raw(pte_raw(pte));
107762306a36Sopenharmony_ci}
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_cistatic inline pte_t *pmdp_ptep(pmd_t *pmd)
108062306a36Sopenharmony_ci{
108162306a36Sopenharmony_ci	return (pte_t *)pmd;
108262306a36Sopenharmony_ci}
108362306a36Sopenharmony_ci#define pmd_pfn(pmd)		pte_pfn(pmd_pte(pmd))
108462306a36Sopenharmony_ci#define pmd_dirty(pmd)		pte_dirty(pmd_pte(pmd))
108562306a36Sopenharmony_ci#define pmd_young(pmd)		pte_young(pmd_pte(pmd))
108662306a36Sopenharmony_ci#define pmd_mkold(pmd)		pte_pmd(pte_mkold(pmd_pte(pmd)))
108762306a36Sopenharmony_ci#define pmd_wrprotect(pmd)	pte_pmd(pte_wrprotect(pmd_pte(pmd)))
108862306a36Sopenharmony_ci#define pmd_mkdirty(pmd)	pte_pmd(pte_mkdirty(pmd_pte(pmd)))
108962306a36Sopenharmony_ci#define pmd_mkclean(pmd)	pte_pmd(pte_mkclean(pmd_pte(pmd)))
109062306a36Sopenharmony_ci#define pmd_mkyoung(pmd)	pte_pmd(pte_mkyoung(pmd_pte(pmd)))
109162306a36Sopenharmony_ci#define pmd_mkwrite_novma(pmd)	pte_pmd(pte_mkwrite_novma(pmd_pte(pmd)))
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
109462306a36Sopenharmony_ci#define pmd_soft_dirty(pmd)    pte_soft_dirty(pmd_pte(pmd))
109562306a36Sopenharmony_ci#define pmd_mksoft_dirty(pmd)  pte_pmd(pte_mksoft_dirty(pmd_pte(pmd)))
109662306a36Sopenharmony_ci#define pmd_clear_soft_dirty(pmd) pte_pmd(pte_clear_soft_dirty(pmd_pte(pmd)))
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
109962306a36Sopenharmony_ci#define pmd_swp_mksoft_dirty(pmd)	pte_pmd(pte_swp_mksoft_dirty(pmd_pte(pmd)))
110062306a36Sopenharmony_ci#define pmd_swp_soft_dirty(pmd)		pte_swp_soft_dirty(pmd_pte(pmd))
110162306a36Sopenharmony_ci#define pmd_swp_clear_soft_dirty(pmd)	pte_pmd(pte_swp_clear_soft_dirty(pmd_pte(pmd)))
110262306a36Sopenharmony_ci#endif
110362306a36Sopenharmony_ci#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci#ifdef CONFIG_NUMA_BALANCING
110662306a36Sopenharmony_cistatic inline int pmd_protnone(pmd_t pmd)
110762306a36Sopenharmony_ci{
110862306a36Sopenharmony_ci	return pte_protnone(pmd_pte(pmd));
110962306a36Sopenharmony_ci}
111062306a36Sopenharmony_ci#endif /* CONFIG_NUMA_BALANCING */
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci#define pmd_write(pmd)		pte_write(pmd_pte(pmd))
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci#define pmd_access_permitted pmd_access_permitted
111562306a36Sopenharmony_cistatic inline bool pmd_access_permitted(pmd_t pmd, bool write)
111662306a36Sopenharmony_ci{
111762306a36Sopenharmony_ci	/*
111862306a36Sopenharmony_ci	 * pmdp_invalidate sets this combination (which is not caught by
111962306a36Sopenharmony_ci	 * !pte_present() check in pte_access_permitted), to prevent
112062306a36Sopenharmony_ci	 * lock-free lookups, as part of the serialize_against_pte_lookup()
112162306a36Sopenharmony_ci	 * synchronisation.
112262306a36Sopenharmony_ci	 *
112362306a36Sopenharmony_ci	 * This also catches the case where the PTE's hardware PRESENT bit is
112462306a36Sopenharmony_ci	 * cleared while TLB is flushed, which is suboptimal but should not
112562306a36Sopenharmony_ci	 * be frequent.
112662306a36Sopenharmony_ci	 */
112762306a36Sopenharmony_ci	if (pmd_is_serializing(pmd))
112862306a36Sopenharmony_ci		return false;
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	return pte_access_permitted(pmd_pte(pmd), write);
113162306a36Sopenharmony_ci}
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_ci#ifdef CONFIG_TRANSPARENT_HUGEPAGE
113462306a36Sopenharmony_ciextern pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot);
113562306a36Sopenharmony_ciextern pud_t pfn_pud(unsigned long pfn, pgprot_t pgprot);
113662306a36Sopenharmony_ciextern pmd_t mk_pmd(struct page *page, pgprot_t pgprot);
113762306a36Sopenharmony_ciextern pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot);
113862306a36Sopenharmony_ciextern void set_pmd_at(struct mm_struct *mm, unsigned long addr,
113962306a36Sopenharmony_ci		       pmd_t *pmdp, pmd_t pmd);
114062306a36Sopenharmony_ciextern void set_pud_at(struct mm_struct *mm, unsigned long addr,
114162306a36Sopenharmony_ci		       pud_t *pudp, pud_t pud);
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_cistatic inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
114462306a36Sopenharmony_ci					unsigned long addr, pmd_t *pmd)
114562306a36Sopenharmony_ci{
114662306a36Sopenharmony_ci}
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_cistatic inline void update_mmu_cache_pud(struct vm_area_struct *vma,
114962306a36Sopenharmony_ci					unsigned long addr, pud_t *pud)
115062306a36Sopenharmony_ci{
115162306a36Sopenharmony_ci}
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ciextern int hash__has_transparent_hugepage(void);
115462306a36Sopenharmony_cistatic inline int has_transparent_hugepage(void)
115562306a36Sopenharmony_ci{
115662306a36Sopenharmony_ci	if (radix_enabled())
115762306a36Sopenharmony_ci		return radix__has_transparent_hugepage();
115862306a36Sopenharmony_ci	return hash__has_transparent_hugepage();
115962306a36Sopenharmony_ci}
116062306a36Sopenharmony_ci#define has_transparent_hugepage has_transparent_hugepage
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_cistatic inline int has_transparent_pud_hugepage(void)
116362306a36Sopenharmony_ci{
116462306a36Sopenharmony_ci	if (radix_enabled())
116562306a36Sopenharmony_ci		return radix__has_transparent_pud_hugepage();
116662306a36Sopenharmony_ci	return 0;
116762306a36Sopenharmony_ci}
116862306a36Sopenharmony_ci#define has_transparent_pud_hugepage has_transparent_pud_hugepage
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_cistatic inline unsigned long
117162306a36Sopenharmony_cipmd_hugepage_update(struct mm_struct *mm, unsigned long addr, pmd_t *pmdp,
117262306a36Sopenharmony_ci		    unsigned long clr, unsigned long set)
117362306a36Sopenharmony_ci{
117462306a36Sopenharmony_ci	if (radix_enabled())
117562306a36Sopenharmony_ci		return radix__pmd_hugepage_update(mm, addr, pmdp, clr, set);
117662306a36Sopenharmony_ci	return hash__pmd_hugepage_update(mm, addr, pmdp, clr, set);
117762306a36Sopenharmony_ci}
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_cistatic inline unsigned long
118062306a36Sopenharmony_cipud_hugepage_update(struct mm_struct *mm, unsigned long addr, pud_t *pudp,
118162306a36Sopenharmony_ci		    unsigned long clr, unsigned long set)
118262306a36Sopenharmony_ci{
118362306a36Sopenharmony_ci	if (radix_enabled())
118462306a36Sopenharmony_ci		return radix__pud_hugepage_update(mm, addr, pudp, clr, set);
118562306a36Sopenharmony_ci	BUG();
118662306a36Sopenharmony_ci	return pud_val(*pudp);
118762306a36Sopenharmony_ci}
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_ci/*
119062306a36Sopenharmony_ci * returns true for pmd migration entries, THP, devmap, hugetlb
119162306a36Sopenharmony_ci * But compile time dependent on THP config
119262306a36Sopenharmony_ci */
119362306a36Sopenharmony_cistatic inline int pmd_large(pmd_t pmd)
119462306a36Sopenharmony_ci{
119562306a36Sopenharmony_ci	return !!(pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE));
119662306a36Sopenharmony_ci}
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_cistatic inline int pud_large(pud_t pud)
119962306a36Sopenharmony_ci{
120062306a36Sopenharmony_ci	return !!(pud_raw(pud) & cpu_to_be64(_PAGE_PTE));
120162306a36Sopenharmony_ci}
120262306a36Sopenharmony_ci
120362306a36Sopenharmony_ci/*
120462306a36Sopenharmony_ci * For radix we should always find H_PAGE_HASHPTE zero. Hence
120562306a36Sopenharmony_ci * the below will work for radix too
120662306a36Sopenharmony_ci */
120762306a36Sopenharmony_cistatic inline int __pmdp_test_and_clear_young(struct mm_struct *mm,
120862306a36Sopenharmony_ci					      unsigned long addr, pmd_t *pmdp)
120962306a36Sopenharmony_ci{
121062306a36Sopenharmony_ci	unsigned long old;
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	if ((pmd_raw(*pmdp) & cpu_to_be64(_PAGE_ACCESSED | H_PAGE_HASHPTE)) == 0)
121362306a36Sopenharmony_ci		return 0;
121462306a36Sopenharmony_ci	old = pmd_hugepage_update(mm, addr, pmdp, _PAGE_ACCESSED, 0);
121562306a36Sopenharmony_ci	return ((old & _PAGE_ACCESSED) != 0);
121662306a36Sopenharmony_ci}
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_cistatic inline int __pudp_test_and_clear_young(struct mm_struct *mm,
121962306a36Sopenharmony_ci					      unsigned long addr, pud_t *pudp)
122062306a36Sopenharmony_ci{
122162306a36Sopenharmony_ci	unsigned long old;
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci	if ((pud_raw(*pudp) & cpu_to_be64(_PAGE_ACCESSED | H_PAGE_HASHPTE)) == 0)
122462306a36Sopenharmony_ci		return 0;
122562306a36Sopenharmony_ci	old = pud_hugepage_update(mm, addr, pudp, _PAGE_ACCESSED, 0);
122662306a36Sopenharmony_ci	return ((old & _PAGE_ACCESSED) != 0);
122762306a36Sopenharmony_ci}
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ci#define __HAVE_ARCH_PMDP_SET_WRPROTECT
123062306a36Sopenharmony_cistatic inline void pmdp_set_wrprotect(struct mm_struct *mm, unsigned long addr,
123162306a36Sopenharmony_ci				      pmd_t *pmdp)
123262306a36Sopenharmony_ci{
123362306a36Sopenharmony_ci	if (pmd_write(*pmdp))
123462306a36Sopenharmony_ci		pmd_hugepage_update(mm, addr, pmdp, _PAGE_WRITE, 0);
123562306a36Sopenharmony_ci}
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci#define __HAVE_ARCH_PUDP_SET_WRPROTECT
123862306a36Sopenharmony_cistatic inline void pudp_set_wrprotect(struct mm_struct *mm, unsigned long addr,
123962306a36Sopenharmony_ci				      pud_t *pudp)
124062306a36Sopenharmony_ci{
124162306a36Sopenharmony_ci	if (pud_write(*pudp))
124262306a36Sopenharmony_ci		pud_hugepage_update(mm, addr, pudp, _PAGE_WRITE, 0);
124362306a36Sopenharmony_ci}
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci/*
124662306a36Sopenharmony_ci * Only returns true for a THP. False for pmd migration entry.
124762306a36Sopenharmony_ci * We also need to return true when we come across a pte that
124862306a36Sopenharmony_ci * in between a thp split. While splitting THP, we mark the pmd
124962306a36Sopenharmony_ci * invalid (pmdp_invalidate()) before we set it with pte page
125062306a36Sopenharmony_ci * address. A pmd_trans_huge() check against a pmd entry during that time
125162306a36Sopenharmony_ci * should return true.
125262306a36Sopenharmony_ci * We should not call this on a hugetlb entry. We should check for HugeTLB
125362306a36Sopenharmony_ci * entry using vma->vm_flags
125462306a36Sopenharmony_ci * The page table walk rule is explained in Documentation/mm/transhuge.rst
125562306a36Sopenharmony_ci */
125662306a36Sopenharmony_cistatic inline int pmd_trans_huge(pmd_t pmd)
125762306a36Sopenharmony_ci{
125862306a36Sopenharmony_ci	if (!pmd_present(pmd))
125962306a36Sopenharmony_ci		return false;
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci	if (radix_enabled())
126262306a36Sopenharmony_ci		return radix__pmd_trans_huge(pmd);
126362306a36Sopenharmony_ci	return hash__pmd_trans_huge(pmd);
126462306a36Sopenharmony_ci}
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_cistatic inline int pud_trans_huge(pud_t pud)
126762306a36Sopenharmony_ci{
126862306a36Sopenharmony_ci	if (!pud_present(pud))
126962306a36Sopenharmony_ci		return false;
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_ci	if (radix_enabled())
127262306a36Sopenharmony_ci		return radix__pud_trans_huge(pud);
127362306a36Sopenharmony_ci	return 0;
127462306a36Sopenharmony_ci}
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci#define __HAVE_ARCH_PMD_SAME
127862306a36Sopenharmony_cistatic inline int pmd_same(pmd_t pmd_a, pmd_t pmd_b)
127962306a36Sopenharmony_ci{
128062306a36Sopenharmony_ci	if (radix_enabled())
128162306a36Sopenharmony_ci		return radix__pmd_same(pmd_a, pmd_b);
128262306a36Sopenharmony_ci	return hash__pmd_same(pmd_a, pmd_b);
128362306a36Sopenharmony_ci}
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci#define pud_same pud_same
128662306a36Sopenharmony_cistatic inline int pud_same(pud_t pud_a, pud_t pud_b)
128762306a36Sopenharmony_ci{
128862306a36Sopenharmony_ci	if (radix_enabled())
128962306a36Sopenharmony_ci		return radix__pud_same(pud_a, pud_b);
129062306a36Sopenharmony_ci	return hash__pud_same(pud_a, pud_b);
129162306a36Sopenharmony_ci}
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_cistatic inline pmd_t __pmd_mkhuge(pmd_t pmd)
129562306a36Sopenharmony_ci{
129662306a36Sopenharmony_ci	if (radix_enabled())
129762306a36Sopenharmony_ci		return radix__pmd_mkhuge(pmd);
129862306a36Sopenharmony_ci	return hash__pmd_mkhuge(pmd);
129962306a36Sopenharmony_ci}
130062306a36Sopenharmony_ci
130162306a36Sopenharmony_cistatic inline pud_t __pud_mkhuge(pud_t pud)
130262306a36Sopenharmony_ci{
130362306a36Sopenharmony_ci	if (radix_enabled())
130462306a36Sopenharmony_ci		return radix__pud_mkhuge(pud);
130562306a36Sopenharmony_ci	BUG();
130662306a36Sopenharmony_ci	return pud;
130762306a36Sopenharmony_ci}
130862306a36Sopenharmony_ci
130962306a36Sopenharmony_ci/*
131062306a36Sopenharmony_ci * pfn_pmd return a pmd_t that can be used as pmd pte entry.
131162306a36Sopenharmony_ci */
131262306a36Sopenharmony_cistatic inline pmd_t pmd_mkhuge(pmd_t pmd)
131362306a36Sopenharmony_ci{
131462306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_VM
131562306a36Sopenharmony_ci	if (radix_enabled())
131662306a36Sopenharmony_ci		WARN_ON((pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE)) == 0);
131762306a36Sopenharmony_ci	else
131862306a36Sopenharmony_ci		WARN_ON((pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE | H_PAGE_THP_HUGE)) !=
131962306a36Sopenharmony_ci			cpu_to_be64(_PAGE_PTE | H_PAGE_THP_HUGE));
132062306a36Sopenharmony_ci#endif
132162306a36Sopenharmony_ci	return pmd;
132262306a36Sopenharmony_ci}
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_cistatic inline pud_t pud_mkhuge(pud_t pud)
132562306a36Sopenharmony_ci{
132662306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_VM
132762306a36Sopenharmony_ci	if (radix_enabled())
132862306a36Sopenharmony_ci		WARN_ON((pud_raw(pud) & cpu_to_be64(_PAGE_PTE)) == 0);
132962306a36Sopenharmony_ci	else
133062306a36Sopenharmony_ci		WARN_ON(1);
133162306a36Sopenharmony_ci#endif
133262306a36Sopenharmony_ci	return pud;
133362306a36Sopenharmony_ci}
133462306a36Sopenharmony_ci
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci#define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
133762306a36Sopenharmony_ciextern int pmdp_set_access_flags(struct vm_area_struct *vma,
133862306a36Sopenharmony_ci				 unsigned long address, pmd_t *pmdp,
133962306a36Sopenharmony_ci				 pmd_t entry, int dirty);
134062306a36Sopenharmony_ci#define __HAVE_ARCH_PUDP_SET_ACCESS_FLAGS
134162306a36Sopenharmony_ciextern int pudp_set_access_flags(struct vm_area_struct *vma,
134262306a36Sopenharmony_ci				 unsigned long address, pud_t *pudp,
134362306a36Sopenharmony_ci				 pud_t entry, int dirty);
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci#define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG
134662306a36Sopenharmony_ciextern int pmdp_test_and_clear_young(struct vm_area_struct *vma,
134762306a36Sopenharmony_ci				     unsigned long address, pmd_t *pmdp);
134862306a36Sopenharmony_ci#define __HAVE_ARCH_PUDP_TEST_AND_CLEAR_YOUNG
134962306a36Sopenharmony_ciextern int pudp_test_and_clear_young(struct vm_area_struct *vma,
135062306a36Sopenharmony_ci				     unsigned long address, pud_t *pudp);
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_ci#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
135462306a36Sopenharmony_cistatic inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
135562306a36Sopenharmony_ci					    unsigned long addr, pmd_t *pmdp)
135662306a36Sopenharmony_ci{
135762306a36Sopenharmony_ci	if (radix_enabled())
135862306a36Sopenharmony_ci		return radix__pmdp_huge_get_and_clear(mm, addr, pmdp);
135962306a36Sopenharmony_ci	return hash__pmdp_huge_get_and_clear(mm, addr, pmdp);
136062306a36Sopenharmony_ci}
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci#define __HAVE_ARCH_PUDP_HUGE_GET_AND_CLEAR
136362306a36Sopenharmony_cistatic inline pud_t pudp_huge_get_and_clear(struct mm_struct *mm,
136462306a36Sopenharmony_ci					    unsigned long addr, pud_t *pudp)
136562306a36Sopenharmony_ci{
136662306a36Sopenharmony_ci	if (radix_enabled())
136762306a36Sopenharmony_ci		return radix__pudp_huge_get_and_clear(mm, addr, pudp);
136862306a36Sopenharmony_ci	BUG();
136962306a36Sopenharmony_ci	return *pudp;
137062306a36Sopenharmony_ci}
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_cistatic inline pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
137362306a36Sopenharmony_ci					unsigned long address, pmd_t *pmdp)
137462306a36Sopenharmony_ci{
137562306a36Sopenharmony_ci	if (radix_enabled())
137662306a36Sopenharmony_ci		return radix__pmdp_collapse_flush(vma, address, pmdp);
137762306a36Sopenharmony_ci	return hash__pmdp_collapse_flush(vma, address, pmdp);
137862306a36Sopenharmony_ci}
137962306a36Sopenharmony_ci#define pmdp_collapse_flush pmdp_collapse_flush
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR_FULL
138262306a36Sopenharmony_cipmd_t pmdp_huge_get_and_clear_full(struct vm_area_struct *vma,
138362306a36Sopenharmony_ci				   unsigned long addr,
138462306a36Sopenharmony_ci				   pmd_t *pmdp, int full);
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci#define __HAVE_ARCH_PUDP_HUGE_GET_AND_CLEAR_FULL
138762306a36Sopenharmony_cipud_t pudp_huge_get_and_clear_full(struct vm_area_struct *vma,
138862306a36Sopenharmony_ci				   unsigned long addr,
138962306a36Sopenharmony_ci				   pud_t *pudp, int full);
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_ci#define __HAVE_ARCH_PGTABLE_DEPOSIT
139262306a36Sopenharmony_cistatic inline void pgtable_trans_huge_deposit(struct mm_struct *mm,
139362306a36Sopenharmony_ci					      pmd_t *pmdp, pgtable_t pgtable)
139462306a36Sopenharmony_ci{
139562306a36Sopenharmony_ci	if (radix_enabled())
139662306a36Sopenharmony_ci		return radix__pgtable_trans_huge_deposit(mm, pmdp, pgtable);
139762306a36Sopenharmony_ci	return hash__pgtable_trans_huge_deposit(mm, pmdp, pgtable);
139862306a36Sopenharmony_ci}
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci#define __HAVE_ARCH_PGTABLE_WITHDRAW
140162306a36Sopenharmony_cistatic inline pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm,
140262306a36Sopenharmony_ci						    pmd_t *pmdp)
140362306a36Sopenharmony_ci{
140462306a36Sopenharmony_ci	if (radix_enabled())
140562306a36Sopenharmony_ci		return radix__pgtable_trans_huge_withdraw(mm, pmdp);
140662306a36Sopenharmony_ci	return hash__pgtable_trans_huge_withdraw(mm, pmdp);
140762306a36Sopenharmony_ci}
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ci#define __HAVE_ARCH_PMDP_INVALIDATE
141062306a36Sopenharmony_ciextern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
141162306a36Sopenharmony_ci			     pmd_t *pmdp);
141262306a36Sopenharmony_ci
141362306a36Sopenharmony_ci#define pmd_move_must_withdraw pmd_move_must_withdraw
141462306a36Sopenharmony_cistruct spinlock;
141562306a36Sopenharmony_ciextern int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
141662306a36Sopenharmony_ci				  struct spinlock *old_pmd_ptl,
141762306a36Sopenharmony_ci				  struct vm_area_struct *vma);
141862306a36Sopenharmony_ci/*
141962306a36Sopenharmony_ci * Hash translation mode use the deposited table to store hash pte
142062306a36Sopenharmony_ci * slot information.
142162306a36Sopenharmony_ci */
142262306a36Sopenharmony_ci#define arch_needs_pgtable_deposit arch_needs_pgtable_deposit
142362306a36Sopenharmony_cistatic inline bool arch_needs_pgtable_deposit(void)
142462306a36Sopenharmony_ci{
142562306a36Sopenharmony_ci	if (radix_enabled())
142662306a36Sopenharmony_ci		return false;
142762306a36Sopenharmony_ci	return true;
142862306a36Sopenharmony_ci}
142962306a36Sopenharmony_ciextern void serialize_against_pte_lookup(struct mm_struct *mm);
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_cistatic inline pmd_t pmd_mkdevmap(pmd_t pmd)
143362306a36Sopenharmony_ci{
143462306a36Sopenharmony_ci	if (radix_enabled())
143562306a36Sopenharmony_ci		return radix__pmd_mkdevmap(pmd);
143662306a36Sopenharmony_ci	return hash__pmd_mkdevmap(pmd);
143762306a36Sopenharmony_ci}
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_cistatic inline pud_t pud_mkdevmap(pud_t pud)
144062306a36Sopenharmony_ci{
144162306a36Sopenharmony_ci	if (radix_enabled())
144262306a36Sopenharmony_ci		return radix__pud_mkdevmap(pud);
144362306a36Sopenharmony_ci	BUG();
144462306a36Sopenharmony_ci	return pud;
144562306a36Sopenharmony_ci}
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_cistatic inline int pmd_devmap(pmd_t pmd)
144862306a36Sopenharmony_ci{
144962306a36Sopenharmony_ci	return pte_devmap(pmd_pte(pmd));
145062306a36Sopenharmony_ci}
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_cistatic inline int pud_devmap(pud_t pud)
145362306a36Sopenharmony_ci{
145462306a36Sopenharmony_ci	return pte_devmap(pud_pte(pud));
145562306a36Sopenharmony_ci}
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_cistatic inline int pgd_devmap(pgd_t pgd)
145862306a36Sopenharmony_ci{
145962306a36Sopenharmony_ci	return 0;
146062306a36Sopenharmony_ci}
146162306a36Sopenharmony_ci#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci#define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION
146462306a36Sopenharmony_cipte_t ptep_modify_prot_start(struct vm_area_struct *, unsigned long, pte_t *);
146562306a36Sopenharmony_civoid ptep_modify_prot_commit(struct vm_area_struct *, unsigned long,
146662306a36Sopenharmony_ci			     pte_t *, pte_t, pte_t);
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_ci/*
146962306a36Sopenharmony_ci * Returns true for a R -> RW upgrade of pte
147062306a36Sopenharmony_ci */
147162306a36Sopenharmony_cistatic inline bool is_pte_rw_upgrade(unsigned long old_val, unsigned long new_val)
147262306a36Sopenharmony_ci{
147362306a36Sopenharmony_ci	if (!(old_val & _PAGE_READ))
147462306a36Sopenharmony_ci		return false;
147562306a36Sopenharmony_ci
147662306a36Sopenharmony_ci	if ((!(old_val & _PAGE_WRITE)) && (new_val & _PAGE_WRITE))
147762306a36Sopenharmony_ci		return true;
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	return false;
148062306a36Sopenharmony_ci}
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci/*
148362306a36Sopenharmony_ci * Like pmd_huge() and pmd_large(), but works regardless of config options
148462306a36Sopenharmony_ci */
148562306a36Sopenharmony_ci#define pmd_is_leaf pmd_is_leaf
148662306a36Sopenharmony_ci#define pmd_leaf pmd_is_leaf
148762306a36Sopenharmony_cistatic inline bool pmd_is_leaf(pmd_t pmd)
148862306a36Sopenharmony_ci{
148962306a36Sopenharmony_ci	return !!(pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE));
149062306a36Sopenharmony_ci}
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci#define pud_is_leaf pud_is_leaf
149362306a36Sopenharmony_ci#define pud_leaf pud_is_leaf
149462306a36Sopenharmony_cistatic inline bool pud_is_leaf(pud_t pud)
149562306a36Sopenharmony_ci{
149662306a36Sopenharmony_ci	return !!(pud_raw(pud) & cpu_to_be64(_PAGE_PTE));
149762306a36Sopenharmony_ci}
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */
150062306a36Sopenharmony_ci#endif /* _ASM_POWERPC_BOOK3S_64_PGTABLE_H_ */
1501