After the exception handling moved to generic code, and some changes in
following two commits:
56dd9470d7c8734f055da2a6bac553caf4a468eb
  context_tracking: Move exception handling to generic code
6c1e0256fad84a843d915414e4b5973b7443d48d
  context_tracking: Restore correct previous context state on exception exit

it is able for this patch to replace the implementation in arch code
with the generic code in above commits.

Signed-off-by: Li Zhong <zh...@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/context_tracking.h |   29 ---------------
 arch/powerpc/kernel/exceptions-64s.S        |    4 +--
 arch/powerpc/kernel/traps.c                 |   42 +++++++++++++---------
 arch/powerpc/mm/fault.c                     |    7 ++--
 arch/powerpc/mm/hash_utils_64.c             |   51 ++++++++++++++-------------
 5 files changed, 57 insertions(+), 76 deletions(-)

diff --git a/arch/powerpc/include/asm/context_tracking.h 
b/arch/powerpc/include/asm/context_tracking.h
index 4da287e..b6f5a33 100644
--- a/arch/powerpc/include/asm/context_tracking.h
+++ b/arch/powerpc/include/asm/context_tracking.h
@@ -1,39 +1,10 @@
 #ifndef _ASM_POWERPC_CONTEXT_TRACKING_H
 #define _ASM_POWERPC_CONTEXT_TRACKING_H
 
-#ifndef __ASSEMBLY__
-#include <linux/context_tracking.h>
-#include <asm/ptrace.h>
-
-/*
- * temporarily defined to avoid potential conflicts with the common
- * implementation, these will be removed by a later patch after the common
- * code enters powerpc tree
- */
-#define exception_enter __exception_enter
-#define exception_exit __exception_exit
-
-static inline void __exception_enter(struct pt_regs *regs)
-{
-       user_exit();
-}
-
-static inline void __exception_exit(struct pt_regs *regs)
-{
-#ifdef CONFIG_CONTEXT_TRACKING
-       if (user_mode(regs))
-               user_enter();
-#endif
-}
-
-#else /* __ASSEMBLY__ */
-
 #ifdef CONFIG_CONTEXT_TRACKING
 #define SCHEDULE_USER bl       .schedule_user
 #else
 #define SCHEDULE_USER bl       .schedule
 #endif
 
-#endif /* !__ASSEMBLY__ */
-
 #endif
diff --git a/arch/powerpc/kernel/exceptions-64s.S 
b/arch/powerpc/kernel/exceptions-64s.S
index 6d82f4f..a8a5361 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1368,17 +1368,15 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
        rlwimi  r4,r0,32-13,30,30       /* becomes _PAGE_USER access bit */
        ori     r4,r4,1                 /* add _PAGE_PRESENT */
        rlwimi  r4,r5,22+2,31-2,31-2    /* Set _PAGE_EXEC if trap is 0x400 */
-       addi    r6,r1,STACK_FRAME_OVERHEAD
 
        /*
         * r3 contains the faulting address
         * r4 contains the required access permissions
         * r5 contains the trap number
-        * r6 contains the address of pt_regs
         *
         * at return r3 = 0 for success, 1 for page fault, negative for error
         */
-       bl      .hash_page_ct           /* build HPTE if possible */
+       bl      .hash_page              /* build HPTE if possible */
        cmpdi   r3,0                    /* see if hash_page succeeded */
 
        /* Success */
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 6228b6b..1b46c2d9 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -35,6 +35,7 @@
 #include <linux/kdebug.h>
 #include <linux/debugfs.h>
 #include <linux/ratelimit.h>
+#include <linux/context_tracking.h>
 
 #include <asm/emulated_ops.h>
 #include <asm/pgtable.h>
@@ -60,7 +61,6 @@
 #include <asm/switch_to.h>
 #include <asm/tm.h>
 #include <asm/debug.h>
-#include <asm/context_tracking.h>
 
 #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
 int (*__debugger)(struct pt_regs *regs) __read_mostly;
@@ -669,8 +669,9 @@ int machine_check_generic(struct pt_regs *regs)
 void machine_check_exception(struct pt_regs *regs)
 {
        int recover = 0;
+       enum ctx_state prev_state;
 
-       exception_enter(regs);
+       prev_state = exception_enter();
 
        __get_cpu_var(irq_stat).mce_exceptions++;
 
@@ -712,7 +713,7 @@ void machine_check_exception(struct pt_regs *regs)
                panic("Unrecoverable Machine check");
 
 exit:
-       exception_exit(regs);
+       exception_exit(prev_state);
 }
 
 void SMIException(struct pt_regs *regs)
@@ -722,19 +723,21 @@ void SMIException(struct pt_regs *regs)
 
 void unknown_exception(struct pt_regs *regs)
 {
-       exception_enter(regs);
+       enum ctx_state prev_state;
+       prev_state = exception_enter();
 
        printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
               regs->nip, regs->msr, regs->trap);
 
        _exception(SIGTRAP, regs, 0, 0);
 
-       exception_exit(regs);
+       exception_exit(prev_state);
 }
 
 void instruction_breakpoint_exception(struct pt_regs *regs)
 {
-       exception_enter(regs);
+       enum ctx_state prev_state;
+       prev_state = exception_enter();
 
        if (notify_die(DIE_IABR_MATCH, "iabr_match", regs, 5,
                                        5, SIGTRAP) == NOTIFY_STOP)
@@ -744,7 +747,7 @@ void instruction_breakpoint_exception(struct pt_regs *regs)
        _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
 
 exit:
-       exception_exit(regs);
+       exception_exit(prev_state);
 }
 
 void RunModeException(struct pt_regs *regs)
@@ -754,7 +757,8 @@ void RunModeException(struct pt_regs *regs)
 
 void __kprobes single_step_exception(struct pt_regs *regs)
 {
-       exception_enter(regs);
+       enum ctx_state prev_state;
+       prev_state = exception_enter();
 
        clear_single_step(regs);
 
@@ -767,7 +771,7 @@ void __kprobes single_step_exception(struct pt_regs *regs)
        _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
 
 exit:
-       exception_exit(regs);
+       exception_exit(prev_state);
 }
 
 /*
@@ -1020,9 +1024,10 @@ int is_valid_bugaddr(unsigned long addr)
 void __kprobes program_check_exception(struct pt_regs *regs)
 {
        unsigned int reason = get_reason(regs);
+       enum ctx_state prev_state;
        extern int do_mathemu(struct pt_regs *regs);
 
-       exception_enter(regs);
+       prev_state = exception_enter();
 
        /* We can now get here via a FP Unavailable exception if the core
         * has no FPU, in that case the reason flags will be 0 */
@@ -1132,14 +1137,15 @@ void __kprobes program_check_exception(struct pt_regs 
*regs)
                _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
 
 exit:
-       exception_exit(regs);
+       exception_exit(prev_state);
 }
 
 void alignment_exception(struct pt_regs *regs)
 {
        int sig, code, fixed = 0;
+       enum ctx_state prev_state;
 
-       exception_enter(regs);
+       prev_state = exception_enter();
 
        /* We restore the interrupt state now */
        if (!arch_irq_disabled_regs(regs))
@@ -1169,7 +1175,7 @@ void alignment_exception(struct pt_regs *regs)
                bad_page_fault(regs, regs->dar, sig);
 
 exit:
-       exception_exit(regs);
+       exception_exit(prev_state);
 }
 
 void StackOverflow(struct pt_regs *regs)
@@ -1198,18 +1204,20 @@ void trace_syscall(struct pt_regs *regs)
 
 void kernel_fp_unavailable_exception(struct pt_regs *regs)
 {
-       exception_enter(regs);
+       enum ctx_state prev_state;
+       prev_state = exception_enter();
 
        printk(KERN_EMERG "Unrecoverable FP Unavailable Exception "
                          "%lx at %lx\n", regs->trap, regs->nip);
        die("Unrecoverable FP Unavailable Exception", regs, SIGABRT);
 
-       exception_exit(regs);
+       exception_exit(prev_state);
 }
 
 void altivec_unavailable_exception(struct pt_regs *regs)
 {
-       exception_enter(regs);
+       enum ctx_state prev_state;
+       prev_state = exception_enter();
 
        if (user_mode(regs)) {
                /* A user program has executed an altivec instruction,
@@ -1223,7 +1231,7 @@ void altivec_unavailable_exception(struct pt_regs *regs)
        die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
 
 exit:
-       exception_exit(regs);
+       exception_exit(prev_state);
 }
 
 void vsx_unavailable_exception(struct pt_regs *regs)
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 108ab17..141835b 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -32,6 +32,7 @@
 #include <linux/perf_event.h>
 #include <linux/magic.h>
 #include <linux/ratelimit.h>
+#include <linux/context_tracking.h>
 
 #include <asm/firmware.h>
 #include <asm/page.h>
@@ -42,7 +43,6 @@
 #include <asm/tlbflush.h>
 #include <asm/siginfo.h>
 #include <asm/debug.h>
-#include <asm/context_tracking.h>
 #include <mm/mmu_decl.h>
 
 #include "icswx.h"
@@ -480,9 +480,10 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned 
long address,
                            unsigned long error_code)
 {
        int ret;
-       exception_enter(regs);
+       enum ctx_state prev_state;
+       prev_state = exception_enter();
        ret = __do_page_fault(regs, address, error_code);
-       exception_exit(regs);
+       exception_exit(prev_state);
        return ret;
 }
 
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 360fba8..eeab30f 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -33,6 +33,7 @@
 #include <linux/init.h>
 #include <linux/signal.h>
 #include <linux/memblock.h>
+#include <linux/context_tracking.h>
 
 #include <asm/processor.h>
 #include <asm/pgtable.h>
@@ -56,7 +57,6 @@
 #include <asm/fadump.h>
 #include <asm/firmware.h>
 #include <asm/tm.h>
-#include <asm/context_tracking.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -919,13 +919,17 @@ int hash_page(unsigned long ea, unsigned long access, 
unsigned long trap)
        const struct cpumask *tmp;
        int rc, user_region = 0, local = 0;
        int psize, ssize;
+       enum ctx_state prev_state;
+
+       prev_state = exception_enter();
 
        DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n",
                ea, access, trap);
 
        if ((ea & ~REGION_MASK) >= PGTABLE_RANGE) {
                DBG_LOW(" out of pgtable range !\n");
-               return 1;
+               rc = 1;
+               goto exit;
        }
 
        /* Get region & vsid */
@@ -935,7 +939,8 @@ int hash_page(unsigned long ea, unsigned long access, 
unsigned long trap)
                mm = current->mm;
                if (! mm) {
                        DBG_LOW(" user region with no mm !\n");
-                       return 1;
+                       rc = 1;
+                       goto exit;
                }
                psize = get_slice_psize(mm, ea);
                ssize = user_segment_size(ea);
@@ -954,14 +959,17 @@ int hash_page(unsigned long ea, unsigned long access, 
unsigned long trap)
                /* Not a valid range
                 * Send the problem up to do_page_fault 
                 */
-               return 1;
+               rc = 1;
+               goto exit;
        }
        DBG_LOW(" mm=%p, mm->pgdir=%p, vsid=%016lx\n", mm, mm->pgd, vsid);
 
        /* Get pgdir */
        pgdir = mm->pgd;
-       if (pgdir == NULL)
-               return 1;
+       if (pgdir == NULL) {
+               rc = 1;
+               goto exit;
+       }
 
        /* Check CPU locality */
        tmp = cpumask_of(smp_processor_id());
@@ -984,7 +992,8 @@ int hash_page(unsigned long ea, unsigned long access, 
unsigned long trap)
        ptep = find_linux_pte_or_hugepte(pgdir, ea, &hugeshift);
        if (ptep == NULL || !pte_present(*ptep)) {
                DBG_LOW(" no PTE !\n");
-               return 1;
+               rc = 1;
+               goto exit;
        }
 
        /* Add _PAGE_PRESENT to the required access perm */
@@ -995,13 +1004,16 @@ int hash_page(unsigned long ea, unsigned long access, 
unsigned long trap)
         */
        if (access & ~pte_val(*ptep)) {
                DBG_LOW(" no access !\n");
-               return 1;
+               rc = 1;
+               goto exit;
        }
 
 #ifdef CONFIG_HUGETLB_PAGE
-       if (hugeshift)
-               return __hash_page_huge(ea, access, vsid, ptep, trap, local,
+       if (hugeshift) {
+               rc = __hash_page_huge(ea, access, vsid, ptep, trap, local,
                                        ssize, hugeshift, psize);
+               goto exit;
+       }
 #endif /* CONFIG_HUGETLB_PAGE */
 
 #ifndef CONFIG_PPC_64K_PAGES
@@ -1081,22 +1093,12 @@ int hash_page(unsigned long ea, unsigned long access, 
unsigned long trap)
                pte_val(*(ptep + PTRS_PER_PTE)));
 #endif
        DBG_LOW(" -> rc=%d\n", rc);
+exit:
+       exception_exit(prev_state);
        return rc;
 }
 EXPORT_SYMBOL_GPL(hash_page);
 
-int hash_page_ct(unsigned long ea, unsigned long access,
-                unsigned long trap, struct pt_regs *regs)
-{
-       int ret;
-
-       exception_enter(regs);
-       ret = hash_page(ea, access, trap);
-       exception_exit(regs);
-
-       return ret;
-}
-
 void hash_preload(struct mm_struct *mm, unsigned long ea,
                  unsigned long access, unsigned long trap)
 {
@@ -1223,7 +1225,8 @@ void flush_hash_range(unsigned long number, int local)
  */
 void low_hash_fault(struct pt_regs *regs, unsigned long address, int rc)
 {
-       exception_enter(regs);
+       enum ctx_state prev_state;
+       prev_state = exception_enter();
 
        if (user_mode(regs)) {
 #ifdef CONFIG_PPC_SUBPAGE_PROT
@@ -1235,7 +1238,7 @@ void low_hash_fault(struct pt_regs *regs, unsigned long 
address, int rc)
        } else
                bad_page_fault(regs, address, SIGBUS);
 
-       exception_exit(regs);
+       exception_exit(prev_state);
 }
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to