diff options
author | Ingo Molnar <mingo@elte.hu> | 2010-08-02 08:29:56 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-08-02 08:31:54 +0200 |
commit | 3772b734720e1a3f2dc1d95cfdfaa5332f4ccf01 (patch) | |
tree | a1a8cc85948c086aa12a1d8014151a7ca7c04ea8 /arch/powerpc/mm/hugetlbpage-hash64.c | |
parent | 9fc3af467d0749989518a23f7289a6f44e5cb214 (diff) | |
parent | 9fe6206f400646a2322096b56c59891d530e8d51 (diff) | |
download | kernel_samsung_crespo-3772b734720e1a3f2dc1d95cfdfaa5332f4ccf01.zip kernel_samsung_crespo-3772b734720e1a3f2dc1d95cfdfaa5332f4ccf01.tar.gz kernel_samsung_crespo-3772b734720e1a3f2dc1d95cfdfaa5332f4ccf01.tar.bz2 |
Merge commit 'v2.6.35' into perf/core
Conflicts:
tools/perf/Makefile
tools/perf/util/hist.c
Merge reason: Resolve the conflicts and update to latest upstream.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/powerpc/mm/hugetlbpage-hash64.c')
-rw-r--r-- | arch/powerpc/mm/hugetlbpage-hash64.c | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/arch/powerpc/mm/hugetlbpage-hash64.c b/arch/powerpc/mm/hugetlbpage-hash64.c index 1995398..cc5c273 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, 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)); @@ -121,8 +121,16 @@ repeat: } } - if (unlikely(slot == -2)) - panic("hash_huge_page: pte_insert failed\n"); + /* + * Hypervisor failure. Restore old pte and return -1 + * similar to __hash_page_* + */ + if (unlikely(slot == -2)) { + *ptep = __pte(old_pte); + hash_failure_debug(ea, access, vsid, trap, ssize, + mmu_psize, old_pte); + return -1; + } new_pte |= (slot << 12) & (_PAGE_F_SECOND | _PAGE_F_GIX); } @@ -131,9 +139,5 @@ repeat: * No need to use ldarx/stdcx here */ *ptep = __pte(new_pte & ~_PAGE_BUSY); - - err = 0; - - out: - return err; + return 0; } |