162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _ASM_POWERPC_PGTABLE_H
362306a36Sopenharmony_ci#define _ASM_POWERPC_PGTABLE_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#ifndef __ASSEMBLY__
662306a36Sopenharmony_ci#include <linux/mmdebug.h>
762306a36Sopenharmony_ci#include <linux/mmzone.h>
862306a36Sopenharmony_ci#include <asm/processor.h>		/* For TASK_SIZE */
962306a36Sopenharmony_ci#include <asm/mmu.h>
1062306a36Sopenharmony_ci#include <asm/page.h>
1162306a36Sopenharmony_ci#include <asm/tlbflush.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistruct mm_struct;
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
1862306a36Sopenharmony_ci#include <asm/book3s/pgtable.h>
1962306a36Sopenharmony_ci#else
2062306a36Sopenharmony_ci#include <asm/nohash/pgtable.h>
2162306a36Sopenharmony_ci#endif /* !CONFIG_PPC_BOOK3S */
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/*
2462306a36Sopenharmony_ci * Protection used for kernel text. We want the debuggers to be able to
2562306a36Sopenharmony_ci * set breakpoints anywhere, so don't write protect the kernel text
2662306a36Sopenharmony_ci * on platforms where such control is possible.
2762306a36Sopenharmony_ci */
2862306a36Sopenharmony_ci#if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) || \
2962306a36Sopenharmony_ci	defined(CONFIG_KPROBES) || defined(CONFIG_DYNAMIC_FTRACE)
3062306a36Sopenharmony_ci#define PAGE_KERNEL_TEXT	PAGE_KERNEL_X
3162306a36Sopenharmony_ci#else
3262306a36Sopenharmony_ci#define PAGE_KERNEL_TEXT	PAGE_KERNEL_ROX
3362306a36Sopenharmony_ci#endif
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/* Make modules code happy. We don't set RO yet */
3662306a36Sopenharmony_ci#define PAGE_KERNEL_EXEC	PAGE_KERNEL_X
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/* Advertise special mapping type for AGP */
3962306a36Sopenharmony_ci#define PAGE_AGP		(PAGE_KERNEL_NC)
4062306a36Sopenharmony_ci#define HAVE_PAGE_AGP
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#ifndef __ASSEMBLY__
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_civoid set_ptes(struct mm_struct *mm, unsigned long addr, pte_t *ptep,
4562306a36Sopenharmony_ci		pte_t pte, unsigned int nr);
4662306a36Sopenharmony_ci#define set_ptes set_ptes
4762306a36Sopenharmony_ci#define update_mmu_cache(vma, addr, ptep) \
4862306a36Sopenharmony_ci	update_mmu_cache_range(NULL, vma, addr, ptep, 1)
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#ifndef MAX_PTRS_PER_PGD
5162306a36Sopenharmony_ci#define MAX_PTRS_PER_PGD PTRS_PER_PGD
5262306a36Sopenharmony_ci#endif
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/* Keep these as a macros to avoid include dependency mess */
5562306a36Sopenharmony_ci#define pte_page(x)		pfn_to_page(pte_pfn(x))
5662306a36Sopenharmony_ci#define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic inline unsigned long pte_pfn(pte_t pte)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	return (pte_val(pte) & PTE_RPN_MASK) >> PTE_RPN_SHIFT;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/*
6462306a36Sopenharmony_ci * Select all bits except the pfn
6562306a36Sopenharmony_ci */
6662306a36Sopenharmony_cistatic inline pgprot_t pte_pgprot(pte_t pte)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	unsigned long pte_flags;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	pte_flags = pte_val(pte) & ~PTE_RPN_MASK;
7162306a36Sopenharmony_ci	return __pgprot(pte_flags);
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci#ifndef pmd_page_vaddr
7562306a36Sopenharmony_cistatic inline const void *pmd_page_vaddr(pmd_t pmd)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	return __va(pmd_val(pmd) & ~PMD_MASKED_BITS);
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci#define pmd_page_vaddr pmd_page_vaddr
8062306a36Sopenharmony_ci#endif
8162306a36Sopenharmony_ci/*
8262306a36Sopenharmony_ci * ZERO_PAGE is a global shared page that is always zero: used
8362306a36Sopenharmony_ci * for zero-mapped memory areas etc..
8462306a36Sopenharmony_ci */
8562306a36Sopenharmony_ciextern unsigned long empty_zero_page[];
8662306a36Sopenharmony_ci#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ciextern pgd_t swapper_pg_dir[];
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ciextern void paging_init(void);
9162306a36Sopenharmony_civoid poking_init(void);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ciextern unsigned long ioremap_bot;
9462306a36Sopenharmony_ciextern const pgprot_t protection_map[16];
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci#ifndef CONFIG_TRANSPARENT_HUGEPAGE
9762306a36Sopenharmony_ci#define pmd_large(pmd)		0
9862306a36Sopenharmony_ci#endif
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci/* can we use this in kvm */
10162306a36Sopenharmony_ciunsigned long vmalloc_to_phys(void *vmalloc_addr);
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_civoid pgtable_cache_add(unsigned int shift);
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cipte_t *early_pte_alloc_kernel(pmd_t *pmdp, unsigned long va);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci#if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_PPC32)
10862306a36Sopenharmony_civoid mark_initmem_nx(void);
10962306a36Sopenharmony_ci#else
11062306a36Sopenharmony_cistatic inline void mark_initmem_nx(void) { }
11162306a36Sopenharmony_ci#endif
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci/*
11462306a36Sopenharmony_ci * When used, PTE_FRAG_NR is defined in subarch pgtable.h
11562306a36Sopenharmony_ci * so we are sure it is included when arriving here.
11662306a36Sopenharmony_ci */
11762306a36Sopenharmony_ci#ifdef PTE_FRAG_NR
11862306a36Sopenharmony_cistatic inline void *pte_frag_get(mm_context_t *ctx)
11962306a36Sopenharmony_ci{
12062306a36Sopenharmony_ci	return ctx->pte_frag;
12162306a36Sopenharmony_ci}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cistatic inline void pte_frag_set(mm_context_t *ctx, void *p)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	ctx->pte_frag = p;
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci#else
12862306a36Sopenharmony_ci#define PTE_FRAG_NR		1
12962306a36Sopenharmony_ci#define PTE_FRAG_SIZE_SHIFT	PAGE_SHIFT
13062306a36Sopenharmony_ci#define PTE_FRAG_SIZE		(1UL << PTE_FRAG_SIZE_SHIFT)
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic inline void *pte_frag_get(mm_context_t *ctx)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	return NULL;
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistatic inline void pte_frag_set(mm_context_t *ctx, void *p)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci#endif
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci#ifndef pmd_is_leaf
14362306a36Sopenharmony_ci#define pmd_is_leaf pmd_is_leaf
14462306a36Sopenharmony_cistatic inline bool pmd_is_leaf(pmd_t pmd)
14562306a36Sopenharmony_ci{
14662306a36Sopenharmony_ci	return false;
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci#endif
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci#ifndef pud_is_leaf
15162306a36Sopenharmony_ci#define pud_is_leaf pud_is_leaf
15262306a36Sopenharmony_cistatic inline bool pud_is_leaf(pud_t pud)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	return false;
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci#endif
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci#ifndef p4d_is_leaf
15962306a36Sopenharmony_ci#define p4d_is_leaf p4d_is_leaf
16062306a36Sopenharmony_cistatic inline bool p4d_is_leaf(p4d_t p4d)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	return false;
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci#endif
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci#define pmd_pgtable pmd_pgtable
16762306a36Sopenharmony_cistatic inline pgtable_t pmd_pgtable(pmd_t pmd)
16862306a36Sopenharmony_ci{
16962306a36Sopenharmony_ci	return (pgtable_t)pmd_page_vaddr(pmd);
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci#ifdef CONFIG_PPC64
17362306a36Sopenharmony_ciint __meminit vmemmap_populated(unsigned long vmemmap_addr, int vmemmap_map_size);
17462306a36Sopenharmony_cibool altmap_cross_boundary(struct vmem_altmap *altmap, unsigned long start,
17562306a36Sopenharmony_ci			   unsigned long page_size);
17662306a36Sopenharmony_ci/*
17762306a36Sopenharmony_ci * mm/memory_hotplug.c:mhp_supports_memmap_on_memory goes into details
17862306a36Sopenharmony_ci * some of the restrictions. We don't check for PMD_SIZE because our
17962306a36Sopenharmony_ci * vmemmap allocation code can fallback correctly. The pageblock
18062306a36Sopenharmony_ci * alignment requirement is met using altmap->reserve blocks.
18162306a36Sopenharmony_ci */
18262306a36Sopenharmony_ci#define arch_supports_memmap_on_memory arch_supports_memmap_on_memory
18362306a36Sopenharmony_cistatic inline bool arch_supports_memmap_on_memory(unsigned long vmemmap_size)
18462306a36Sopenharmony_ci{
18562306a36Sopenharmony_ci	if (!radix_enabled())
18662306a36Sopenharmony_ci		return false;
18762306a36Sopenharmony_ci	/*
18862306a36Sopenharmony_ci	 * With 4K page size and 2M PMD_SIZE, we can align
18962306a36Sopenharmony_ci	 * things better with memory block size value
19062306a36Sopenharmony_ci	 * starting from 128MB. Hence align things with PMD_SIZE.
19162306a36Sopenharmony_ci	 */
19262306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_PPC_4K_PAGES))
19362306a36Sopenharmony_ci		return IS_ALIGNED(vmemmap_size, PMD_SIZE);
19462306a36Sopenharmony_ci	return true;
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci#endif /* _ASM_POWERPC_PGTABLE_H */
202