1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * IBM System z Huge TLB Page Support for Kernel.
4 *
5 * Copyright IBM Corp. 2008
6 * Author(s): Gerald Schaefer <[email protected]>
7 */
8
9 #ifndef _ASM_S390_HUGETLB_H
10 #define _ASM_S390_HUGETLB_H
11
12 #include <linux/pgtable.h>
13 #include <linux/swap.h>
14 #include <linux/swapops.h>
15 #include <asm/page.h>
16
17 #define hugepages_supported() (MACHINE_HAS_EDAT1)
18
19 #define __HAVE_ARCH_HUGE_SET_HUGE_PTE_AT
20 void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
21 pte_t *ptep, pte_t pte, unsigned long sz);
22 void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
23 pte_t *ptep, pte_t pte);
24
25 #define __HAVE_ARCH_HUGE_PTEP_GET
26 pte_t huge_ptep_get(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
27
28 pte_t __huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
29 pte_t *ptep);
30
31 #define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
huge_ptep_get_and_clear(struct mm_struct * mm,unsigned long addr,pte_t * ptep,unsigned long sz)32 static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
33 unsigned long addr, pte_t *ptep,
34 unsigned long sz)
35 {
36 return __huge_ptep_get_and_clear(mm, addr, ptep);
37 }
38
arch_clear_hugetlb_flags(struct folio * folio)39 static inline void arch_clear_hugetlb_flags(struct folio *folio)
40 {
41 clear_bit(PG_arch_1, &folio->flags);
42 }
43 #define arch_clear_hugetlb_flags arch_clear_hugetlb_flags
44
45 #define __HAVE_ARCH_HUGE_PTE_CLEAR
huge_pte_clear(struct mm_struct * mm,unsigned long addr,pte_t * ptep,unsigned long sz)46 static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
47 pte_t *ptep, unsigned long sz)
48 {
49 if ((pte_val(*ptep) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3)
50 set_pte(ptep, __pte(_REGION3_ENTRY_EMPTY));
51 else
52 set_pte(ptep, __pte(_SEGMENT_ENTRY_EMPTY));
53 }
54
55 #define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH
huge_ptep_clear_flush(struct vm_area_struct * vma,unsigned long address,pte_t * ptep)56 static inline pte_t huge_ptep_clear_flush(struct vm_area_struct *vma,
57 unsigned long address, pte_t *ptep)
58 {
59 return __huge_ptep_get_and_clear(vma->vm_mm, address, ptep);
60 }
61
62 #define __HAVE_ARCH_HUGE_PTEP_SET_ACCESS_FLAGS
huge_ptep_set_access_flags(struct vm_area_struct * vma,unsigned long addr,pte_t * ptep,pte_t pte,int dirty)63 static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
64 unsigned long addr, pte_t *ptep,
65 pte_t pte, int dirty)
66 {
67 int changed = !pte_same(huge_ptep_get(vma->vm_mm, addr, ptep), pte);
68
69 if (changed) {
70 __huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
71 __set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
72 }
73 return changed;
74 }
75
76 #define __HAVE_ARCH_HUGE_PTEP_SET_WRPROTECT
huge_ptep_set_wrprotect(struct mm_struct * mm,unsigned long addr,pte_t * ptep)77 static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
78 unsigned long addr, pte_t *ptep)
79 {
80 pte_t pte = __huge_ptep_get_and_clear(mm, addr, ptep);
81
82 __set_huge_pte_at(mm, addr, ptep, pte_wrprotect(pte));
83 }
84
85 #define __HAVE_ARCH_HUGE_PTE_MKUFFD_WP
huge_pte_mkuffd_wp(pte_t pte)86 static inline pte_t huge_pte_mkuffd_wp(pte_t pte)
87 {
88 return pte;
89 }
90
91 #define __HAVE_ARCH_HUGE_PTE_CLEAR_UFFD_WP
huge_pte_clear_uffd_wp(pte_t pte)92 static inline pte_t huge_pte_clear_uffd_wp(pte_t pte)
93 {
94 return pte;
95 }
96
97 #define __HAVE_ARCH_HUGE_PTE_UFFD_WP
huge_pte_uffd_wp(pte_t pte)98 static inline int huge_pte_uffd_wp(pte_t pte)
99 {
100 return 0;
101 }
102
103 #include <asm-generic/hugetlb.h>
104
105 #endif /* _ASM_S390_HUGETLB_H */
106