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