csky: Fixup get wrong psr value from phyical reg
[ 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>
This commit is contained in:
parent
c848e00e3b
commit
57615a8561
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user