162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _ASM_POWERPC_BOOK3S_64_HASH_4K_H
362306a36Sopenharmony_ci#define _ASM_POWERPC_BOOK3S_64_HASH_4K_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#define H_PTE_INDEX_SIZE  9  // size: 8B << 9 = 4KB, maps: 2^9 x   4KB =   2MB
662306a36Sopenharmony_ci#define H_PMD_INDEX_SIZE  7  // size: 8B << 7 = 1KB, maps: 2^7 x   2MB = 256MB
762306a36Sopenharmony_ci#define H_PUD_INDEX_SIZE  9  // size: 8B << 9 = 4KB, maps: 2^9 x 256MB = 128GB
862306a36Sopenharmony_ci#define H_PGD_INDEX_SIZE  9  // size: 8B << 9 = 4KB, maps: 2^9 x 128GB =  64TB
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/*
1162306a36Sopenharmony_ci * Each context is 512TB. But on 4k we restrict our max TASK size to 64TB
1262306a36Sopenharmony_ci * Hence also limit max EA bits to 64TB.
1362306a36Sopenharmony_ci */
1462306a36Sopenharmony_ci#define MAX_EA_BITS_PER_CONTEXT		46
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/*
1862306a36Sopenharmony_ci * Our page table limit us to 64TB. For 64TB physical memory, we only need 64GB
1962306a36Sopenharmony_ci * of vmemmap space. To better support sparse memory layout, we use 61TB
2062306a36Sopenharmony_ci * linear map range, 1TB of vmalloc, 1TB of I/O and 1TB of vmememmap.
2162306a36Sopenharmony_ci */
2262306a36Sopenharmony_ci#define REGION_SHIFT		(40)
2362306a36Sopenharmony_ci#define H_KERN_MAP_SIZE		(ASM_CONST(1) << REGION_SHIFT)
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/*
2662306a36Sopenharmony_ci * Limits the linear mapping range
2762306a36Sopenharmony_ci */
2862306a36Sopenharmony_ci#define H_MAX_PHYSMEM_BITS	46
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/*
3162306a36Sopenharmony_ci * Define the address range of the kernel non-linear virtual area (61TB)
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_ci#define H_KERN_VIRT_START	ASM_CONST(0xc0003d0000000000)
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#ifndef __ASSEMBLY__
3662306a36Sopenharmony_ci#define H_PTE_TABLE_SIZE	(sizeof(pte_t) << H_PTE_INDEX_SIZE)
3762306a36Sopenharmony_ci#define H_PMD_TABLE_SIZE	(sizeof(pmd_t) << H_PMD_INDEX_SIZE)
3862306a36Sopenharmony_ci#define H_PUD_TABLE_SIZE	(sizeof(pud_t) << H_PUD_INDEX_SIZE)
3962306a36Sopenharmony_ci#define H_PGD_TABLE_SIZE	(sizeof(pgd_t) << H_PGD_INDEX_SIZE)
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#define H_PAGE_F_GIX_SHIFT	_PAGE_PA_MAX
4262306a36Sopenharmony_ci#define H_PAGE_F_SECOND		_RPAGE_PKEY_BIT0 /* HPTE is in 2ndary HPTEG */
4362306a36Sopenharmony_ci#define H_PAGE_F_GIX		(_RPAGE_RPN43 | _RPAGE_RPN42 | _RPAGE_RPN41)
4462306a36Sopenharmony_ci#define H_PAGE_BUSY		_RPAGE_RSV1
4562306a36Sopenharmony_ci#define H_PAGE_HASHPTE		_RPAGE_PKEY_BIT4
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci/* PTE flags to conserve for HPTE identification */
4862306a36Sopenharmony_ci#define _PAGE_HPTEFLAGS (H_PAGE_BUSY | H_PAGE_HASHPTE | \
4962306a36Sopenharmony_ci			 H_PAGE_F_SECOND | H_PAGE_F_GIX)
5062306a36Sopenharmony_ci/*
5162306a36Sopenharmony_ci * Not supported by 4k linux page size
5262306a36Sopenharmony_ci */
5362306a36Sopenharmony_ci#define H_PAGE_4K_PFN	0x0
5462306a36Sopenharmony_ci#define H_PAGE_THP_HUGE 0x0
5562306a36Sopenharmony_ci#define H_PAGE_COMBO	0x0
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/* 8 bytes per each pte entry */
5862306a36Sopenharmony_ci#define H_PTE_FRAG_SIZE_SHIFT  (H_PTE_INDEX_SIZE + 3)
5962306a36Sopenharmony_ci#define H_PTE_FRAG_NR	(PAGE_SIZE >> H_PTE_FRAG_SIZE_SHIFT)
6062306a36Sopenharmony_ci#define H_PMD_FRAG_SIZE_SHIFT  (H_PMD_INDEX_SIZE + 3)
6162306a36Sopenharmony_ci#define H_PMD_FRAG_NR	(PAGE_SIZE >> H_PMD_FRAG_SIZE_SHIFT)
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci/* memory key bits, only 8 keys supported */
6462306a36Sopenharmony_ci#define H_PTE_PKEY_BIT4	0
6562306a36Sopenharmony_ci#define H_PTE_PKEY_BIT3	0
6662306a36Sopenharmony_ci#define H_PTE_PKEY_BIT2	_RPAGE_PKEY_BIT3
6762306a36Sopenharmony_ci#define H_PTE_PKEY_BIT1	_RPAGE_PKEY_BIT2
6862306a36Sopenharmony_ci#define H_PTE_PKEY_BIT0	_RPAGE_PKEY_BIT1
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/*
7262306a36Sopenharmony_ci * On all 4K setups, remap_4k_pfn() equates to remap_pfn_range()
7362306a36Sopenharmony_ci */
7462306a36Sopenharmony_ci#define remap_4k_pfn(vma, addr, pfn, prot)	\
7562306a36Sopenharmony_ci	remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, (prot))
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci#ifdef CONFIG_HUGETLB_PAGE
7862306a36Sopenharmony_cistatic inline int hash__hugepd_ok(hugepd_t hpd)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	unsigned long hpdval = hpd_val(hpd);
8162306a36Sopenharmony_ci	/*
8262306a36Sopenharmony_ci	 * if it is not a pte and have hugepd shift mask
8362306a36Sopenharmony_ci	 * set, then it is a hugepd directory pointer
8462306a36Sopenharmony_ci	 */
8562306a36Sopenharmony_ci	if (!(hpdval & _PAGE_PTE) && (hpdval & _PAGE_PRESENT) &&
8662306a36Sopenharmony_ci	    ((hpdval & HUGEPD_SHIFT_MASK) != 0))
8762306a36Sopenharmony_ci		return true;
8862306a36Sopenharmony_ci	return false;
8962306a36Sopenharmony_ci}
9062306a36Sopenharmony_ci#endif
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci/*
9362306a36Sopenharmony_ci * 4K PTE format is different from 64K PTE format. Saving the hash_slot is just
9462306a36Sopenharmony_ci * a matter of returning the PTE bits that need to be modified. On 64K PTE,
9562306a36Sopenharmony_ci * things are a little more involved and hence needs many more parameters to
9662306a36Sopenharmony_ci * accomplish the same. However we want to abstract this out from the caller by
9762306a36Sopenharmony_ci * keeping the prototype consistent across the two formats.
9862306a36Sopenharmony_ci */
9962306a36Sopenharmony_cistatic inline unsigned long pte_set_hidx(pte_t *ptep, real_pte_t rpte,
10062306a36Sopenharmony_ci					 unsigned int subpg_index, unsigned long hidx,
10162306a36Sopenharmony_ci					 int offset)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	return (hidx << H_PAGE_F_GIX_SHIFT) &
10462306a36Sopenharmony_ci		(H_PAGE_F_SECOND | H_PAGE_F_GIX);
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci#ifdef CONFIG_TRANSPARENT_HUGEPAGE
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic inline char *get_hpte_slot_array(pmd_t *pmdp)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	BUG();
11262306a36Sopenharmony_ci	return NULL;
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic inline unsigned int hpte_valid(unsigned char *hpte_slot_array, int index)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	BUG();
11862306a36Sopenharmony_ci	return 0;
11962306a36Sopenharmony_ci}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistatic inline unsigned int hpte_hash_index(unsigned char *hpte_slot_array,
12262306a36Sopenharmony_ci					   int index)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	BUG();
12562306a36Sopenharmony_ci	return 0;
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistatic inline void mark_hpte_slot_valid(unsigned char *hpte_slot_array,
12962306a36Sopenharmony_ci					unsigned int index, unsigned int hidx)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	BUG();
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistatic inline int hash__pmd_trans_huge(pmd_t pmd)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	return 0;
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic inline pmd_t hash__pmd_mkhuge(pmd_t pmd)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	BUG();
14262306a36Sopenharmony_ci	return pmd;
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ciextern unsigned long hash__pmd_hugepage_update(struct mm_struct *mm,
14662306a36Sopenharmony_ci					   unsigned long addr, pmd_t *pmdp,
14762306a36Sopenharmony_ci					   unsigned long clr, unsigned long set);
14862306a36Sopenharmony_ciextern pmd_t hash__pmdp_collapse_flush(struct vm_area_struct *vma,
14962306a36Sopenharmony_ci				   unsigned long address, pmd_t *pmdp);
15062306a36Sopenharmony_ciextern void hash__pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
15162306a36Sopenharmony_ci					 pgtable_t pgtable);
15262306a36Sopenharmony_ciextern pgtable_t hash__pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
15362306a36Sopenharmony_ciextern pmd_t hash__pmdp_huge_get_and_clear(struct mm_struct *mm,
15462306a36Sopenharmony_ci				       unsigned long addr, pmd_t *pmdp);
15562306a36Sopenharmony_ciextern int hash__has_transparent_hugepage(void);
15662306a36Sopenharmony_ci#endif
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_cistatic inline pmd_t hash__pmd_mkdevmap(pmd_t pmd)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	BUG();
16162306a36Sopenharmony_ci	return pmd;
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci#endif /* _ASM_POWERPC_BOOK3S_64_HASH_4K_H */
167