|
@@ -21,21 +21,13 @@ int __hash_page_huge(unsigned long ea, unsigned long access, unsigned long vsid,
|
|
|
unsigned long old_pte, new_pte;
|
|
|
unsigned long va, rflags, pa, sz;
|
|
|
long slot;
|
|
|
- int err = 1;
|
|
|
|
|
|
BUG_ON(shift != mmu_psize_defs[mmu_psize].shift);
|
|
|
|
|
|
/* Search the Linux page table for a match with va */
|
|
|
va = hpt_va(ea, vsid, ssize);
|
|
|
|
|
|
- /*
|
|
|
- * Check the user's access rights to the page. If access should be
|
|
|
- * prevented then send the problem up to do_page_fault.
|
|
|
- */
|
|
|
- if (unlikely(access & ~pte_val(*ptep)))
|
|
|
- goto out;
|
|
|
- /*
|
|
|
- * At this point, we have a pte (old_pte) which can be used to build
|
|
|
+ /* At this point, we have a pte (old_pte) which can be used to build
|
|
|
* or update an HPTE. There are 2 cases:
|
|
|
*
|
|
|
* 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,
|
|
|
|
|
|
do {
|
|
|
old_pte = pte_val(*ptep);
|
|
|
- if (old_pte & _PAGE_BUSY)
|
|
|
- goto out;
|
|
|
+ /* If PTE busy, retry the access */
|
|
|
+ if (unlikely(old_pte & _PAGE_BUSY))
|
|
|
+ return 0;
|
|
|
+ /* If PTE permissions don't match, take page fault */
|
|
|
+ if (unlikely(access & ~old_pte))
|
|
|
+ return 1;
|
|
|
+ /* Try to lock the PTE, add ACCESSED and DIRTY if it was
|
|
|
+ * a write access */
|
|
|
new_pte = old_pte | _PAGE_BUSY | _PAGE_ACCESSED;
|
|
|
+ if (access & _PAGE_RW)
|
|
|
+ new_pte |= _PAGE_DIRTY;
|
|
|
} while(old_pte != __cmpxchg_u64((unsigned long *)ptep,
|
|
|
old_pte, new_pte));
|
|
|
|
|
@@ -127,8 +127,7 @@ repeat:
|
|
|
*/
|
|
|
if (unlikely(slot == -2)) {
|
|
|
*ptep = __pte(old_pte);
|
|
|
- err = -1;
|
|
|
- goto out;
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
new_pte |= (slot << 12) & (_PAGE_F_SECOND | _PAGE_F_GIX);
|
|
@@ -138,9 +137,5 @@ repeat:
|
|
|
* No need to use ldarx/stdcx here
|
|
|
*/
|
|
|
*ptep = __pte(new_pte & ~_PAGE_BUSY);
|
|
|
-
|
|
|
- err = 0;
|
|
|
-
|
|
|
- out:
|
|
|
- return err;
|
|
|
+ return 0;
|
|
|
}
|