0001
0002 #ifndef _ASM_POWERPC_BOOK3S_64_HUGETLB_H
0003 #define _ASM_POWERPC_BOOK3S_64_HUGETLB_H
0004
0005 #include <asm/firmware.h>
0006
0007
0008
0009
0010
0011
0012 void radix__flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
0013 void radix__local_flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
0014
0015 extern void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma,
0016 unsigned long addr, pte_t *ptep,
0017 pte_t old_pte, pte_t pte);
0018
0019 static inline int hstate_get_psize(struct hstate *hstate)
0020 {
0021 unsigned long shift;
0022
0023 shift = huge_page_shift(hstate);
0024 if (shift == mmu_psize_defs[MMU_PAGE_2M].shift)
0025 return MMU_PAGE_2M;
0026 else if (shift == mmu_psize_defs[MMU_PAGE_1G].shift)
0027 return MMU_PAGE_1G;
0028 else if (shift == mmu_psize_defs[MMU_PAGE_16M].shift)
0029 return MMU_PAGE_16M;
0030 else if (shift == mmu_psize_defs[MMU_PAGE_16G].shift)
0031 return MMU_PAGE_16G;
0032 else {
0033 WARN(1, "Wrong huge page shift\n");
0034 return mmu_virtual_psize;
0035 }
0036 }
0037
0038 #define __HAVE_ARCH_GIGANTIC_PAGE_RUNTIME_SUPPORTED
0039 static inline bool gigantic_page_runtime_supported(void)
0040 {
0041
0042
0043
0044
0045
0046 if (firmware_has_feature(FW_FEATURE_LPAR) && !radix_enabled())
0047 return false;
0048
0049 return true;
0050 }
0051
0052
0053 #define HUGEPD_VAL_BITS (0x8000000000000000UL)
0054
0055 #define huge_ptep_modify_prot_start huge_ptep_modify_prot_start
0056 extern pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma,
0057 unsigned long addr, pte_t *ptep);
0058
0059 #define huge_ptep_modify_prot_commit huge_ptep_modify_prot_commit
0060 extern void huge_ptep_modify_prot_commit(struct vm_area_struct *vma,
0061 unsigned long addr, pte_t *ptep,
0062 pte_t old_pte, pte_t new_pte);
0063
0064
0065
0066
0067 static inline pte_t *hugepd_page(hugepd_t hpd)
0068 {
0069 BUG_ON(!hugepd_ok(hpd));
0070
0071
0072
0073 BUILD_BUG_ON((MMU_PAGE_COUNT - 1) > 0xf);
0074 return __va(hpd_val(hpd) & HUGEPD_ADDR_MASK);
0075 }
0076
0077 static inline unsigned int hugepd_mmu_psize(hugepd_t hpd)
0078 {
0079 return (hpd_val(hpd) & HUGEPD_SHIFT_MASK) >> 2;
0080 }
0081
0082 static inline unsigned int hugepd_shift(hugepd_t hpd)
0083 {
0084 return mmu_psize_to_shift(hugepd_mmu_psize(hpd));
0085 }
0086 static inline void flush_hugetlb_page(struct vm_area_struct *vma,
0087 unsigned long vmaddr)
0088 {
0089 if (radix_enabled())
0090 return radix__flush_hugetlb_page(vma, vmaddr);
0091 }
0092
0093 static inline pte_t *hugepte_offset(hugepd_t hpd, unsigned long addr,
0094 unsigned int pdshift)
0095 {
0096 unsigned long idx = (addr & ((1UL << pdshift) - 1)) >> hugepd_shift(hpd);
0097
0098 return hugepd_page(hpd) + idx;
0099 }
0100
0101 static inline void hugepd_populate(hugepd_t *hpdp, pte_t *new, unsigned int pshift)
0102 {
0103 *hpdp = __hugepd(__pa(new) | HUGEPD_VAL_BITS | (shift_to_mmu_psize(pshift) << 2));
0104 }
0105
0106 void flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
0107
0108 static inline int check_and_get_huge_psize(int shift)
0109 {
0110 int mmu_psize;
0111
0112 if (shift > SLICE_HIGH_SHIFT)
0113 return -EINVAL;
0114
0115 mmu_psize = shift_to_mmu_psize(shift);
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125 if (radix_enabled()) {
0126 if (mmu_psize != MMU_PAGE_2M && mmu_psize != MMU_PAGE_1G)
0127 return -EINVAL;
0128 } else {
0129 if (mmu_psize != MMU_PAGE_16M && mmu_psize != MMU_PAGE_16G)
0130 return -EINVAL;
0131 }
0132 return mmu_psize;
0133 }
0134
0135 #endif