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