aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r--arch/powerpc/mm/hugetlbpage-hash64.c31
1 files changed, 13 insertions, 18 deletions
diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c
index c9acd7910eea..faae9ec4cb04 100644
--- a/arch/powerpc/mm/hugetlbpage-hash64.c
+++ b/arch/powerpc/mm/hugetlbpage-hash64.c
@@ -21,21 +21,13 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
21 unsigned long old_pte, new_pte; 21 unsigned long old_pte, new_pte;
22 unsigned long va, rflags, pa, sz; 22 unsigned long va, rflags, pa, sz;
23 long slot; 23 long slot;
24 int err = 1;
25 24
26 BUG_ON(shift != mmu_psize_defs[mmu_psize].shift); 25 BUG_ON(shift != mmu_psize_defs[mmu_psize].shift);
27 26
28 /* Search the Linux page table for a match with va */ 27 /* Search the Linux page table for a match with va */
29 va = hpt_va(ea, vsid, ssize); 28 va = hpt_va(ea, vsid, ssize);
30 29
31 /* 30 /* At this point, we have a pte (old_pte) which can be used to build
32 * Check the user's access rights to the page. If access should be
33 * prevented then send the problem up to do_page_fault.
34 */
35 if (unlikely(access & ~pte_val(*ptep)))
36 goto out;
37 /*
38 * At this point, we have a pte (old_pte) which can be used to build
39 * or update an HPTE. There are 2 cases: 31 * or update an HPTE. There are 2 cases:
40 * 32 *
41 * 1. There is a valid (present) pte with no associated HPTE (this is 33 * 1. There is a valid (present) pte with no associated HPTE (this is
@@ -49,9 +41,17 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
49 41
50 do { 42 do {
51 old_pte = pte_val(*ptep); 43 old_pte = pte_val(*ptep);
52 if (old_pte & _PAGE_BUSY) 44 /* If PTE busy, retry the access */
53 goto out; 45 if (unlikely(old_pte & _PAGE_BUSY))
46 return 0;
47 /* If PTE permissions don't match, take page fault */
48 if (unlikely(access & ~old_pte))
49 return 1;
50 /* Try to lock the PTE, add ACCESSED and DIRTY if it was
51 * a write access */
54 new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED; 52 new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED;
53 if (access & _PAGE_RW)
54 new_pte |= _PAGE_DIRTY;
55 } while(old_pte != __cmpxchg_u64((unsigned long *)ptep, 55 } while(old_pte != __cmpxchg_u64((unsigned long *)ptep,
56 old_pte, new_pte)); 56 old_pte, new_pte));
57 57
@@ -127,8 +127,7 @@ repeat:
127 */ 127 */
128 if (unlikely(slot == -2)) { 128 if (unlikely(slot == -2)) {
129 *ptep = __pte(old_pte); 129 *ptep = __pte(old_pte);
130 err = -1; 130 return -1;
131 goto out;
132 } 131 }
133 132
134 new_pte |= (slot << 12) & (_PAGE_F_SECOND | _PAGE_F_GIX); 133 new_pte |= (slot << 12) & (_PAGE_F_SECOND | _PAGE_F_GIX);
@@ -138,9 +137,5 @@ repeat:
138 * No need to use ldarx/stdcx here 137 * No need to use ldarx/stdcx here
139 */ 138 */
140 *ptep = __pte(new_pte & ~_PAGE_BUSY); 139 *ptep = __pte(new_pte & ~_PAGE_BUSY);
141 140 return 0;
142 err = 0;
143
144 out:
145 return err;
146} 141}