18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _ASM_POWERPC_BOOK3S_64_HASH_4K_H
38c2ecf20Sopenharmony_ci#define _ASM_POWERPC_BOOK3S_64_HASH_4K_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#define H_PTE_INDEX_SIZE  9  // size: 8B << 9 = 4KB, maps: 2^9 x   4KB =   2MB
68c2ecf20Sopenharmony_ci#define H_PMD_INDEX_SIZE  7  // size: 8B << 7 = 1KB, maps: 2^7 x   2MB = 256MB
78c2ecf20Sopenharmony_ci#define H_PUD_INDEX_SIZE  9  // size: 8B << 9 = 4KB, maps: 2^9 x 256MB = 128GB
88c2ecf20Sopenharmony_ci#define H_PGD_INDEX_SIZE  9  // size: 8B << 9 = 4KB, maps: 2^9 x 128GB =  64TB
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci/*
118c2ecf20Sopenharmony_ci * Each context is 512TB. But on 4k we restrict our max TASK size to 64TB
128c2ecf20Sopenharmony_ci * Hence also limit max EA bits to 64TB.
138c2ecf20Sopenharmony_ci */
148c2ecf20Sopenharmony_ci#define MAX_EA_BITS_PER_CONTEXT		46
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/*
188c2ecf20Sopenharmony_ci * Our page table limit us to 64TB. For 64TB physical memory, we only need 64GB
198c2ecf20Sopenharmony_ci * of vmemmap space. To better support sparse memory layout, we use 61TB
208c2ecf20Sopenharmony_ci * linear map range, 1TB of vmalloc, 1TB of I/O and 1TB of vmememmap.
218c2ecf20Sopenharmony_ci */
228c2ecf20Sopenharmony_ci#define REGION_SHIFT		(40)
238c2ecf20Sopenharmony_ci#define H_KERN_MAP_SIZE		(ASM_CONST(1) << REGION_SHIFT)
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/*
268c2ecf20Sopenharmony_ci * Limits the linear mapping range
278c2ecf20Sopenharmony_ci */
288c2ecf20Sopenharmony_ci#define H_MAX_PHYSMEM_BITS	46
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci/*
318c2ecf20Sopenharmony_ci * Define the address range of the kernel non-linear virtual area (61TB)
328c2ecf20Sopenharmony_ci */
338c2ecf20Sopenharmony_ci#define H_KERN_VIRT_START	ASM_CONST(0xc0003d0000000000)
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
368c2ecf20Sopenharmony_ci#define H_PTE_TABLE_SIZE	(sizeof(pte_t) << H_PTE_INDEX_SIZE)
378c2ecf20Sopenharmony_ci#define H_PMD_TABLE_SIZE	(sizeof(pmd_t) << H_PMD_INDEX_SIZE)
388c2ecf20Sopenharmony_ci#define H_PUD_TABLE_SIZE	(sizeof(pud_t) << H_PUD_INDEX_SIZE)
398c2ecf20Sopenharmony_ci#define H_PGD_TABLE_SIZE	(sizeof(pgd_t) << H_PGD_INDEX_SIZE)
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define H_PAGE_F_GIX_SHIFT	_PAGE_PA_MAX
428c2ecf20Sopenharmony_ci#define H_PAGE_F_SECOND		_RPAGE_PKEY_BIT0 /* HPTE is in 2ndary HPTEG */
438c2ecf20Sopenharmony_ci#define H_PAGE_F_GIX		(_RPAGE_RPN43 | _RPAGE_RPN42 | _RPAGE_RPN41)
448c2ecf20Sopenharmony_ci#define H_PAGE_BUSY		_RPAGE_RSV1
458c2ecf20Sopenharmony_ci#define H_PAGE_HASHPTE		_RPAGE_PKEY_BIT4
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/* PTE flags to conserve for HPTE identification */
488c2ecf20Sopenharmony_ci#define _PAGE_HPTEFLAGS (H_PAGE_BUSY | H_PAGE_HASHPTE | \
498c2ecf20Sopenharmony_ci			 H_PAGE_F_SECOND | H_PAGE_F_GIX)
508c2ecf20Sopenharmony_ci/*
518c2ecf20Sopenharmony_ci * Not supported by 4k linux page size
528c2ecf20Sopenharmony_ci */
538c2ecf20Sopenharmony_ci#define H_PAGE_4K_PFN	0x0
548c2ecf20Sopenharmony_ci#define H_PAGE_THP_HUGE 0x0
558c2ecf20Sopenharmony_ci#define H_PAGE_COMBO	0x0
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci/* 8 bytes per each pte entry */
588c2ecf20Sopenharmony_ci#define H_PTE_FRAG_SIZE_SHIFT  (H_PTE_INDEX_SIZE + 3)
598c2ecf20Sopenharmony_ci#define H_PTE_FRAG_NR	(PAGE_SIZE >> H_PTE_FRAG_SIZE_SHIFT)
608c2ecf20Sopenharmony_ci#define H_PMD_FRAG_SIZE_SHIFT  (H_PMD_INDEX_SIZE + 3)
618c2ecf20Sopenharmony_ci#define H_PMD_FRAG_NR	(PAGE_SIZE >> H_PMD_FRAG_SIZE_SHIFT)
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci/* memory key bits, only 8 keys supported */
648c2ecf20Sopenharmony_ci#define H_PTE_PKEY_BIT4	0
658c2ecf20Sopenharmony_ci#define H_PTE_PKEY_BIT3	0
668c2ecf20Sopenharmony_ci#define H_PTE_PKEY_BIT2	_RPAGE_PKEY_BIT3
678c2ecf20Sopenharmony_ci#define H_PTE_PKEY_BIT1	_RPAGE_PKEY_BIT2
688c2ecf20Sopenharmony_ci#define H_PTE_PKEY_BIT0	_RPAGE_PKEY_BIT1
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci/*
728c2ecf20Sopenharmony_ci * On all 4K setups, remap_4k_pfn() equates to remap_pfn_range()
738c2ecf20Sopenharmony_ci */
748c2ecf20Sopenharmony_ci#define remap_4k_pfn(vma, addr, pfn, prot)	\
758c2ecf20Sopenharmony_ci	remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, (prot))
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci#ifdef CONFIG_HUGETLB_PAGE
788c2ecf20Sopenharmony_cistatic inline int hash__hugepd_ok(hugepd_t hpd)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	unsigned long hpdval = hpd_val(hpd);
818c2ecf20Sopenharmony_ci	/*
828c2ecf20Sopenharmony_ci	 * if it is not a pte and have hugepd shift mask
838c2ecf20Sopenharmony_ci	 * set, then it is a hugepd directory pointer
848c2ecf20Sopenharmony_ci	 */
858c2ecf20Sopenharmony_ci	if (!(hpdval & _PAGE_PTE) && (hpdval & _PAGE_PRESENT) &&
868c2ecf20Sopenharmony_ci	    ((hpdval & HUGEPD_SHIFT_MASK) != 0))
878c2ecf20Sopenharmony_ci		return true;
888c2ecf20Sopenharmony_ci	return false;
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci#endif
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci/*
938c2ecf20Sopenharmony_ci * 4K PTE format is different from 64K PTE format. Saving the hash_slot is just
948c2ecf20Sopenharmony_ci * a matter of returning the PTE bits that need to be modified. On 64K PTE,
958c2ecf20Sopenharmony_ci * things are a little more involved and hence needs many more parameters to
968c2ecf20Sopenharmony_ci * accomplish the same. However we want to abstract this out from the caller by
978c2ecf20Sopenharmony_ci * keeping the prototype consistent across the two formats.
988c2ecf20Sopenharmony_ci */
998c2ecf20Sopenharmony_cistatic inline unsigned long pte_set_hidx(pte_t *ptep, real_pte_t rpte,
1008c2ecf20Sopenharmony_ci					 unsigned int subpg_index, unsigned long hidx,
1018c2ecf20Sopenharmony_ci					 int offset)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	return (hidx << H_PAGE_F_GIX_SHIFT) &
1048c2ecf20Sopenharmony_ci		(H_PAGE_F_SECOND | H_PAGE_F_GIX);
1058c2ecf20Sopenharmony_ci}
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci#ifdef CONFIG_TRANSPARENT_HUGEPAGE
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_cistatic inline char *get_hpte_slot_array(pmd_t *pmdp)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	BUG();
1128c2ecf20Sopenharmony_ci	return NULL;
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic inline unsigned int hpte_valid(unsigned char *hpte_slot_array, int index)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	BUG();
1188c2ecf20Sopenharmony_ci	return 0;
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic inline unsigned int hpte_hash_index(unsigned char *hpte_slot_array,
1228c2ecf20Sopenharmony_ci					   int index)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	BUG();
1258c2ecf20Sopenharmony_ci	return 0;
1268c2ecf20Sopenharmony_ci}
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistatic inline void mark_hpte_slot_valid(unsigned char *hpte_slot_array,
1298c2ecf20Sopenharmony_ci					unsigned int index, unsigned int hidx)
1308c2ecf20Sopenharmony_ci{
1318c2ecf20Sopenharmony_ci	BUG();
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistatic inline int hash__pmd_trans_huge(pmd_t pmd)
1358c2ecf20Sopenharmony_ci{
1368c2ecf20Sopenharmony_ci	return 0;
1378c2ecf20Sopenharmony_ci}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic inline int hash__pmd_same(pmd_t pmd_a, pmd_t pmd_b)
1408c2ecf20Sopenharmony_ci{
1418c2ecf20Sopenharmony_ci	BUG();
1428c2ecf20Sopenharmony_ci	return 0;
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic inline pmd_t hash__pmd_mkhuge(pmd_t pmd)
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci	BUG();
1488c2ecf20Sopenharmony_ci	return pmd;
1498c2ecf20Sopenharmony_ci}
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ciextern unsigned long hash__pmd_hugepage_update(struct mm_struct *mm,
1528c2ecf20Sopenharmony_ci					   unsigned long addr, pmd_t *pmdp,
1538c2ecf20Sopenharmony_ci					   unsigned long clr, unsigned long set);
1548c2ecf20Sopenharmony_ciextern pmd_t hash__pmdp_collapse_flush(struct vm_area_struct *vma,
1558c2ecf20Sopenharmony_ci				   unsigned long address, pmd_t *pmdp);
1568c2ecf20Sopenharmony_ciextern void hash__pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp,
1578c2ecf20Sopenharmony_ci					 pgtable_t pgtable);
1588c2ecf20Sopenharmony_ciextern pgtable_t hash__pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
1598c2ecf20Sopenharmony_ciextern pmd_t hash__pmdp_huge_get_and_clear(struct mm_struct *mm,
1608c2ecf20Sopenharmony_ci				       unsigned long addr, pmd_t *pmdp);
1618c2ecf20Sopenharmony_ciextern int hash__has_transparent_hugepage(void);
1628c2ecf20Sopenharmony_ci#endif
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cistatic inline pmd_t hash__pmd_mkdevmap(pmd_t pmd)
1658c2ecf20Sopenharmony_ci{
1668c2ecf20Sopenharmony_ci	BUG();
1678c2ecf20Sopenharmony_ci	return pmd;
1688c2ecf20Sopenharmony_ci}
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci#endif /* _ASM_POWERPC_BOOK3S_64_HASH_4K_H */
173