diff options
-rw-r--r-- | arch/powerpc/include/asm/book3s/64/hugetlb.h | 12 | ||||
-rw-r--r-- | arch/powerpc/mm/hugetlbpage-hash64.c | 25 | ||||
-rw-r--r-- | arch/powerpc/mm/hugetlbpage-radix.c | 17 |
3 files changed, 54 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/book3s/64/hugetlb.h b/arch/powerpc/include/asm/book3s/64/hugetlb.h index 5b0177733994..66c1e4f88d65 100644 --- a/arch/powerpc/include/asm/book3s/64/hugetlb.h +++ b/arch/powerpc/include/asm/book3s/64/hugetlb.h | |||
@@ -13,6 +13,10 @@ radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | |||
13 | unsigned long len, unsigned long pgoff, | 13 | unsigned long len, unsigned long pgoff, |
14 | unsigned long flags); | 14 | unsigned long flags); |
15 | 15 | ||
16 | extern void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma, | ||
17 | unsigned long addr, pte_t *ptep, | ||
18 | pte_t old_pte, pte_t pte); | ||
19 | |||
16 | static inline int hstate_get_psize(struct hstate *hstate) | 20 | static inline int hstate_get_psize(struct hstate *hstate) |
17 | { | 21 | { |
18 | unsigned long shift; | 22 | unsigned long shift; |
@@ -42,4 +46,12 @@ static inline bool gigantic_page_supported(void) | |||
42 | /* hugepd entry valid bit */ | 46 | /* hugepd entry valid bit */ |
43 | #define HUGEPD_VAL_BITS (0x8000000000000000UL) | 47 | #define HUGEPD_VAL_BITS (0x8000000000000000UL) |
44 | 48 | ||
49 | #define huge_ptep_modify_prot_start huge_ptep_modify_prot_start | ||
50 | extern pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma, | ||
51 | unsigned long addr, pte_t *ptep); | ||
52 | |||
53 | #define huge_ptep_modify_prot_commit huge_ptep_modify_prot_commit | ||
54 | extern void huge_ptep_modify_prot_commit(struct vm_area_struct *vma, | ||
55 | unsigned long addr, pte_t *ptep, | ||
56 | pte_t old_pte, pte_t new_pte); | ||
45 | #endif | 57 | #endif |
diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c index 2e6a8f9345d3..367ce3a4a503 100644 --- a/arch/powerpc/mm/hugetlbpage-hash64.c +++ b/arch/powerpc/mm/hugetlbpage-hash64.c | |||
@@ -121,3 +121,28 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid, | |||
121 | *ptep = __pte(new_pte & ~H_PAGE_BUSY); | 121 | *ptep = __pte(new_pte & ~H_PAGE_BUSY); |
122 | return 0; | 122 | return 0; |
123 | } | 123 | } |
124 | |||
125 | pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma, | ||
126 | unsigned long addr, pte_t *ptep) | ||
127 | { | ||
128 | unsigned long pte_val; | ||
129 | /* | ||
130 | * Clear the _PAGE_PRESENT so that no hardware parallel update is | ||
131 | * possible. Also keep the pte_present true so that we don't take | ||
132 | * wrong fault. | ||
133 | */ | ||
134 | pte_val = pte_update(vma->vm_mm, addr, ptep, | ||
135 | _PAGE_PRESENT, _PAGE_INVALID, 1); | ||
136 | |||
137 | return __pte(pte_val); | ||
138 | } | ||
139 | |||
140 | void huge_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, | ||
141 | pte_t *ptep, pte_t old_pte, pte_t pte) | ||
142 | { | ||
143 | |||
144 | if (radix_enabled()) | ||
145 | return radix__huge_ptep_modify_prot_commit(vma, addr, ptep, | ||
146 | old_pte, pte); | ||
147 | set_huge_pte_at(vma->vm_mm, addr, ptep, pte); | ||
148 | } | ||
diff --git a/arch/powerpc/mm/hugetlbpage-radix.c b/arch/powerpc/mm/hugetlbpage-radix.c index 2486bee0f93e..11d9ea28a816 100644 --- a/arch/powerpc/mm/hugetlbpage-radix.c +++ b/arch/powerpc/mm/hugetlbpage-radix.c | |||
@@ -90,3 +90,20 @@ radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | |||
90 | 90 | ||
91 | return vm_unmapped_area(&info); | 91 | return vm_unmapped_area(&info); |
92 | } | 92 | } |
93 | |||
94 | void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma, | ||
95 | unsigned long addr, pte_t *ptep, | ||
96 | pte_t old_pte, pte_t pte) | ||
97 | { | ||
98 | struct mm_struct *mm = vma->vm_mm; | ||
99 | |||
100 | /* | ||
101 | * To avoid NMMU hang while relaxing access we need to flush the tlb before | ||
102 | * we set the new value. | ||
103 | */ | ||
104 | if (is_pte_rw_upgrade(pte_val(old_pte), pte_val(pte)) && | ||
105 | (atomic_read(&mm->context.copros) > 0)) | ||
106 | radix__flush_hugetlb_page(vma, addr); | ||
107 | |||
108 | set_huge_pte_at(vma->vm_mm, addr, ptep, pte); | ||
109 | } | ||