diff options
Diffstat (limited to 'arch/sparc/mm/hugetlbpage.c')
-rw-r--r-- | arch/sparc/mm/hugetlbpage.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c index 4977800e9770..ba52e6466a82 100644 --- a/arch/sparc/mm/hugetlbpage.c +++ b/arch/sparc/mm/hugetlbpage.c | |||
@@ -176,17 +176,31 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, | |||
176 | pte_t *ptep, pte_t entry) | 176 | pte_t *ptep, pte_t entry) |
177 | { | 177 | { |
178 | int i; | 178 | int i; |
179 | pte_t orig[2]; | ||
180 | unsigned long nptes; | ||
179 | 181 | ||
180 | if (!pte_present(*ptep) && pte_present(entry)) | 182 | if (!pte_present(*ptep) && pte_present(entry)) |
181 | mm->context.huge_pte_count++; | 183 | mm->context.huge_pte_count++; |
182 | 184 | ||
183 | addr &= HPAGE_MASK; | 185 | addr &= HPAGE_MASK; |
184 | for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { | 186 | |
185 | set_pte_at(mm, addr, ptep, entry); | 187 | nptes = 1 << HUGETLB_PAGE_ORDER; |
188 | orig[0] = *ptep; | ||
189 | orig[1] = *(ptep + nptes / 2); | ||
190 | for (i = 0; i < nptes; i++) { | ||
191 | *ptep = entry; | ||
186 | ptep++; | 192 | ptep++; |
187 | addr += PAGE_SIZE; | 193 | addr += PAGE_SIZE; |
188 | pte_val(entry) += PAGE_SIZE; | 194 | pte_val(entry) += PAGE_SIZE; |
189 | } | 195 | } |
196 | |||
197 | /* Issue TLB flush at REAL_HPAGE_SIZE boundaries */ | ||
198 | addr -= REAL_HPAGE_SIZE; | ||
199 | ptep -= nptes / 2; | ||
200 | maybe_tlb_batch_add(mm, addr, ptep, orig[1], 0); | ||
201 | addr -= REAL_HPAGE_SIZE; | ||
202 | ptep -= nptes / 2; | ||
203 | maybe_tlb_batch_add(mm, addr, ptep, orig[0], 0); | ||
190 | } | 204 | } |
191 | 205 | ||
192 | pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | 206 | pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, |
@@ -194,19 +208,28 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | |||
194 | { | 208 | { |
195 | pte_t entry; | 209 | pte_t entry; |
196 | int i; | 210 | int i; |
211 | unsigned long nptes; | ||
197 | 212 | ||
198 | entry = *ptep; | 213 | entry = *ptep; |
199 | if (pte_present(entry)) | 214 | if (pte_present(entry)) |
200 | mm->context.huge_pte_count--; | 215 | mm->context.huge_pte_count--; |
201 | 216 | ||
202 | addr &= HPAGE_MASK; | 217 | addr &= HPAGE_MASK; |
203 | 218 | nptes = 1 << HUGETLB_PAGE_ORDER; | |
204 | for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { | 219 | for (i = 0; i < nptes; i++) { |
205 | pte_clear(mm, addr, ptep); | 220 | *ptep = __pte(0UL); |
206 | addr += PAGE_SIZE; | 221 | addr += PAGE_SIZE; |
207 | ptep++; | 222 | ptep++; |
208 | } | 223 | } |
209 | 224 | ||
225 | /* Issue TLB flush at REAL_HPAGE_SIZE boundaries */ | ||
226 | addr -= REAL_HPAGE_SIZE; | ||
227 | ptep -= nptes / 2; | ||
228 | maybe_tlb_batch_add(mm, addr, ptep, entry, 0); | ||
229 | addr -= REAL_HPAGE_SIZE; | ||
230 | ptep -= nptes / 2; | ||
231 | maybe_tlb_batch_add(mm, addr, ptep, entry, 0); | ||
232 | |||
210 | return entry; | 233 | return entry; |
211 | } | 234 | } |
212 | 235 | ||