csky: Fixup get wrong psr value from phyical reg
authorGuo Ren <guoren@linux.alibaba.com>
Tue, 31 Mar 2020 15:45:52 +0000 (23:45 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 23 Apr 2020 08:36:38 +0000 (10:36 +0200)
[ Upstream commit 9c0e343d7654a329d1f9b53d253cbf7fb6eff85d ]

We should get psr value from regs->psr in stack, not directly get
it from phyiscal register then save the vector number in
tsk->trap_no.

Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/csky/include/asm/processor.h
arch/csky/kernel/traps.c
arch/csky/mm/fault.c

index 21e0bd5..c6bcd7f 100644 (file)
@@ -43,6 +43,7 @@ extern struct cpuinfo_csky cpu_data[];
 struct thread_struct {
        unsigned long  ksp;       /* kernel stack pointer */
        unsigned long  sr;        /* saved status register */
+       unsigned long  trap_no;   /* saved status register */
 
        /* FPU regs */
        struct user_fp __aligned(16) user_fp;
index b057480..63715cb 100644 (file)
@@ -115,8 +115,9 @@ asmlinkage void trap_c(struct pt_regs *regs)
        int sig;
        unsigned long vector;
        siginfo_t info;
+       struct task_struct *tsk = current;
 
-       vector = (mfcr("psr") >> 16) & 0xff;
+       vector = (regs->sr >> 16) & 0xff;
 
        switch (vector) {
        case VEC_ZERODIV:
@@ -129,6 +130,7 @@ asmlinkage void trap_c(struct pt_regs *regs)
                sig = SIGTRAP;
                break;
        case VEC_ILLEGAL:
+               tsk->thread.trap_no = vector;
                die_if_kernel("Kernel mode ILLEGAL", regs, vector);
 #ifndef CONFIG_CPU_NO_USER_BKPT
                if (*(uint16_t *)instruction_pointer(regs) != USR_BKPT)
@@ -146,16 +148,20 @@ asmlinkage void trap_c(struct pt_regs *regs)
                sig = SIGTRAP;
                break;
        case VEC_ACCESS:
+               tsk->thread.trap_no = vector;
                return buserr(regs);
 #ifdef CONFIG_CPU_NEED_SOFTALIGN
        case VEC_ALIGN:
+               tsk->thread.trap_no = vector;
                return csky_alignment(regs);
 #endif
 #ifdef CONFIG_CPU_HAS_FPU
        case VEC_FPE:
+               tsk->thread.trap_no = vector;
                die_if_kernel("Kernel mode FPE", regs, vector);
                return fpu_fpe(regs);
        case VEC_PRIV:
+               tsk->thread.trap_no = vector;
                die_if_kernel("Kernel mode PRIV", regs, vector);
                if (fpu_libc_helper(regs))
                        return;
@@ -164,5 +170,8 @@ asmlinkage void trap_c(struct pt_regs *regs)
                sig = SIGSEGV;
                break;
        }
+
+       tsk->thread.trap_no = vector;
+
        send_sig(sig, current, 0);
 }
index f76618b..562c7f7 100644 (file)
@@ -179,11 +179,14 @@ bad_area:
 bad_area_nosemaphore:
        /* User mode accesses just cause a SIGSEGV */
        if (user_mode(regs)) {
+               tsk->thread.trap_no = (regs->sr >> 16) & 0xff;
                force_sig_fault(SIGSEGV, si_code, (void __user *)address);
                return;
        }
 
 no_context:
+       tsk->thread.trap_no = (regs->sr >> 16) & 0xff;
+
        /* Are we prepared to handle this kernel fault? */
        if (fixup_exception(regs))
                return;
@@ -198,6 +201,8 @@ no_context:
        die_if_kernel("Oops", regs, write);
 
 out_of_memory:
+       tsk->thread.trap_no = (regs->sr >> 16) & 0xff;
+
        /*
         * We ran out of memory, call the OOM killer, and return the userspace
         * (which will retry the fault, or kill us if we got oom-killed).
@@ -206,6 +211,8 @@ out_of_memory:
        return;
 
 do_sigbus:
+       tsk->thread.trap_no = (regs->sr >> 16) & 0xff;
+
        up_read(&mm->mmap_sem);
 
        /* Kernel mode? Handle exceptions or die */