Commit 38a9ff6d authored by Vineet Gupta's avatar Vineet Gupta

ARC: Remove explicit passing around of ECR

With ECR now part of pt_regs

* No need to propagate from lowest asm handlers as arg
* No need to save it in tsk->thread.cause_code
* Avoid bit chopping to access the bit-fields

More code consolidation, cleanup
Signed-off-by: default avatarVineet Gupta <vgupta@synopsys.com>
parent 502a0c77
...@@ -18,9 +18,8 @@ struct task_struct; ...@@ -18,9 +18,8 @@ struct task_struct;
void show_regs(struct pt_regs *regs); void show_regs(struct pt_regs *regs);
void show_stacktrace(struct task_struct *tsk, struct pt_regs *regs); void show_stacktrace(struct task_struct *tsk, struct pt_regs *regs);
void show_kernel_fault_diag(const char *str, struct pt_regs *regs, void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
unsigned long address, unsigned long cause_reg); unsigned long address);
void die(const char *str, struct pt_regs *regs, unsigned long address, void die(const char *str, struct pt_regs *regs, unsigned long address);
unsigned long cause_reg);
#define BUG() do { \ #define BUG() do { \
dump_stack(); \ dump_stack(); \
......
...@@ -31,7 +31,7 @@ static inline void arch_kgdb_breakpoint(void) ...@@ -31,7 +31,7 @@ static inline void arch_kgdb_breakpoint(void)
__asm__ __volatile__ ("trap_s 0x4\n"); __asm__ __volatile__ ("trap_s 0x4\n");
} }
extern void kgdb_trap(struct pt_regs *regs, int param); extern void kgdb_trap(struct pt_regs *regs);
enum arc700_linux_regnums { enum arc700_linux_regnums {
_R0 = 0, _R0 = 0,
...@@ -53,7 +53,7 @@ enum arc700_linux_regnums { ...@@ -53,7 +53,7 @@ enum arc700_linux_regnums {
}; };
#else #else
#define kgdb_trap(regs, param) #define kgdb_trap(regs)
#endif #endif
#endif /* __ARC_KGDB_H__ */ #endif /* __ARC_KGDB_H__ */
...@@ -50,11 +50,9 @@ struct kprobe_ctlblk { ...@@ -50,11 +50,9 @@ struct kprobe_ctlblk {
int kprobe_fault_handler(struct pt_regs *regs, unsigned long cause); int kprobe_fault_handler(struct pt_regs *regs, unsigned long cause);
void kretprobe_trampoline(void); void kretprobe_trampoline(void);
void trap_is_kprobe(unsigned long cause, unsigned long address, void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
struct pt_regs *regs);
#else #else
static void trap_is_kprobe(unsigned long cause, unsigned long address, static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
struct pt_regs *regs)
{ {
} }
#endif #endif
......
...@@ -29,7 +29,6 @@ struct thread_struct { ...@@ -29,7 +29,6 @@ struct thread_struct {
unsigned long ksp; /* kernel mode stack pointer */ unsigned long ksp; /* kernel mode stack pointer */
unsigned long callee_reg; /* pointer to callee regs */ unsigned long callee_reg; /* pointer to callee regs */
unsigned long fault_address; /* dbls as brkpt holder as well */ unsigned long fault_address; /* dbls as brkpt holder as well */
unsigned long cause_code; /* Exception Cause Code (ECR) */
#ifdef CONFIG_ARC_FPU_SAVE_RESTORE #ifdef CONFIG_ARC_FPU_SAVE_RESTORE
struct arc_fpu fpu; struct arc_fpu fpu;
#endif #endif
......
...@@ -16,11 +16,11 @@ ...@@ -16,11 +16,11 @@
#ifdef CONFIG_ARC_MISALIGN_ACCESS #ifdef CONFIG_ARC_MISALIGN_ACCESS
int misaligned_fixup(unsigned long address, struct pt_regs *regs, int misaligned_fixup(unsigned long address, struct pt_regs *regs,
unsigned long cause, struct callee_regs *cregs); struct callee_regs *cregs);
#else #else
static inline int static inline int
misaligned_fixup(unsigned long address, struct pt_regs *regs, misaligned_fixup(unsigned long address, struct pt_regs *regs,
unsigned long cause, struct callee_regs *cregs) struct callee_regs *cregs)
{ {
return 0; return 0;
} }
......
...@@ -274,10 +274,8 @@ ARC_ENTRY instr_service ...@@ -274,10 +274,8 @@ ARC_ENTRY instr_service
SWITCH_TO_KERNEL_STK SWITCH_TO_KERNEL_STK
SAVE_ALL_SYS SAVE_ALL_SYS
lr r0, [ecr] lr r0, [efa]
lr r1, [efa] mov r1, sp
mov r2, sp
FAKE_RET_FROM_EXCPN r9 FAKE_RET_FROM_EXCPN r9
...@@ -298,9 +296,8 @@ ARC_ENTRY mem_service ...@@ -298,9 +296,8 @@ ARC_ENTRY mem_service
SWITCH_TO_KERNEL_STK SWITCH_TO_KERNEL_STK
SAVE_ALL_SYS SAVE_ALL_SYS
lr r0, [ecr] lr r0, [efa]
lr r1, [efa] mov r1, sp
mov r2, sp
bl do_memory_error bl do_memory_error
b ret_from_exception b ret_from_exception
ARC_EXIT mem_service ARC_EXIT mem_service
...@@ -317,11 +314,11 @@ ARC_ENTRY EV_MachineCheck ...@@ -317,11 +314,11 @@ ARC_ENTRY EV_MachineCheck
SWITCH_TO_KERNEL_STK SWITCH_TO_KERNEL_STK
SAVE_ALL_SYS SAVE_ALL_SYS
lr r0, [ecr] lr r2, [ecr]
lr r1, [efa] lr r0, [efa]
mov r2, sp mov r1, sp
lsr r3, r0, 8 lsr r3, r2, 8
bmsk r3, r3, 7 bmsk r3, r3, 7
brne r3, ECR_C_MCHK_DUP_TLB, 1f brne r3, ECR_C_MCHK_DUP_TLB, 1f
...@@ -384,12 +381,12 @@ ARC_ENTRY EV_TLBProtV ...@@ -384,12 +381,12 @@ ARC_ENTRY EV_TLBProtV
;========== (6b) Non aligned access ============ ;========== (6b) Non aligned access ============
4: 4:
mov r0, r2 ; cause code mov r0, r1
mov r2, sp ; pt_regs mov r1, sp ; pt_regs
#ifdef CONFIG_ARC_MISALIGN_ACCESS #ifdef CONFIG_ARC_MISALIGN_ACCESS
SAVE_CALLEE_SAVED_USER SAVE_CALLEE_SAVED_USER
mov r3, sp ; callee_regs mov r2, sp ; callee_regs
bl do_misaligned_access bl do_misaligned_access
...@@ -416,9 +413,8 @@ ARC_ENTRY EV_PrivilegeV ...@@ -416,9 +413,8 @@ ARC_ENTRY EV_PrivilegeV
SWITCH_TO_KERNEL_STK SWITCH_TO_KERNEL_STK
SAVE_ALL_SYS SAVE_ALL_SYS
lr r0, [ecr] lr r0, [efa]
lr r1, [efa] mov r1, sp
mov r2, sp
FAKE_RET_FROM_EXCPN r9 FAKE_RET_FROM_EXCPN r9
...@@ -437,9 +433,8 @@ ARC_ENTRY EV_Extension ...@@ -437,9 +433,8 @@ ARC_ENTRY EV_Extension
SWITCH_TO_KERNEL_STK SWITCH_TO_KERNEL_STK
SAVE_ALL_SYS SAVE_ALL_SYS
lr r0, [ecr] lr r0, [efa]
lr r1, [efa] mov r1, sp
mov r2, sp
bl do_extension_fault bl do_extension_fault
b ret_from_exception b ret_from_exception
ARC_EXIT EV_Extension ARC_EXIT EV_Extension
...@@ -495,9 +490,8 @@ tracesys_exit: ...@@ -495,9 +490,8 @@ tracesys_exit:
trap_with_param: trap_with_param:
; stop_pc info by gdb needs this info ; stop_pc info by gdb needs this info
mov r0, r12 lr r0, [efa]
lr r1, [efa] mov r1, sp
mov r2, sp
; Now that we have read EFA, its safe to do "fake" rtie ; Now that we have read EFA, its safe to do "fake" rtie
; and get out of CPU exception mode ; and get out of CPU exception mode
......
...@@ -169,7 +169,7 @@ int kgdb_arch_init(void) ...@@ -169,7 +169,7 @@ int kgdb_arch_init(void)
return 0; return 0;
} }
void kgdb_trap(struct pt_regs *regs, int param) void kgdb_trap(struct pt_regs *regs)
{ {
/* trap_s 3 is used for breakpoints that overwrite existing /* trap_s 3 is used for breakpoints that overwrite existing
* instructions, while trap_s 4 is used for compiled breakpoints. * instructions, while trap_s 4 is used for compiled breakpoints.
......
...@@ -517,8 +517,7 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p) ...@@ -517,8 +517,7 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p)
return 0; return 0;
} }
void trap_is_kprobe(unsigned long cause, unsigned long address, void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
struct pt_regs *regs)
{ {
notify_die(DIE_TRAP, "kprobe_trap", regs, address, cause, SIGTRAP); notify_die(DIE_TRAP, "kprobe_trap", regs, address, 0, SIGTRAP);
} }
...@@ -28,10 +28,9 @@ void __init trap_init(void) ...@@ -28,10 +28,9 @@ void __init trap_init(void)
return; return;
} }
void die(const char *str, struct pt_regs *regs, unsigned long address, void die(const char *str, struct pt_regs *regs, unsigned long address)
unsigned long cause_reg)
{ {
show_kernel_fault_diag(str, regs, address, cause_reg); show_kernel_fault_diag(str, regs, address);
/* DEAD END */ /* DEAD END */
__asm__("flag 1"); __asm__("flag 1");
...@@ -42,14 +41,13 @@ void die(const char *str, struct pt_regs *regs, unsigned long address, ...@@ -42,14 +41,13 @@ void die(const char *str, struct pt_regs *regs, unsigned long address,
* -for user faults enqueues requested signal * -for user faults enqueues requested signal
* -for kernel, chk if due to copy_(to|from)_user, otherwise die() * -for kernel, chk if due to copy_(to|from)_user, otherwise die()
*/ */
static noinline int handle_exception(unsigned long cause, char *str, static noinline int
struct pt_regs *regs, siginfo_t *info) handle_exception(const char *str, struct pt_regs *regs, siginfo_t *info)
{ {
if (user_mode(regs)) { if (user_mode(regs)) {
struct task_struct *tsk = current; struct task_struct *tsk = current;
tsk->thread.fault_address = (__force unsigned int)info->si_addr; tsk->thread.fault_address = (__force unsigned int)info->si_addr;
tsk->thread.cause_code = cause;
force_sig_info(info->si_signo, info, tsk); force_sig_info(info->si_signo, info, tsk);
...@@ -58,14 +56,14 @@ static noinline int handle_exception(unsigned long cause, char *str, ...@@ -58,14 +56,14 @@ static noinline int handle_exception(unsigned long cause, char *str,
if (fixup_exception(regs)) if (fixup_exception(regs))
return 0; return 0;
die(str, regs, (unsigned long)info->si_addr, cause); die(str, regs, (unsigned long)info->si_addr);
} }
return 1; return 1;
} }
#define DO_ERROR_INFO(signr, str, name, sicode) \ #define DO_ERROR_INFO(signr, str, name, sicode) \
int name(unsigned long cause, unsigned long address, struct pt_regs *regs) \ int name(unsigned long address, struct pt_regs *regs) \
{ \ { \
siginfo_t info = { \ siginfo_t info = { \
.si_signo = signr, \ .si_signo = signr, \
...@@ -73,7 +71,7 @@ int name(unsigned long cause, unsigned long address, struct pt_regs *regs) \ ...@@ -73,7 +71,7 @@ int name(unsigned long cause, unsigned long address, struct pt_regs *regs) \
.si_code = sicode, \ .si_code = sicode, \
.si_addr = (void __user *)address, \ .si_addr = (void __user *)address, \
}; \ }; \
return handle_exception(cause, str, regs, &info);\ return handle_exception(str, regs, &info);\
} }
/* /*
...@@ -90,11 +88,11 @@ DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN) ...@@ -90,11 +88,11 @@ DO_ERROR_INFO(SIGBUS, "Misaligned Access", do_misaligned_error, BUS_ADRALN)
/* /*
* Entry Point for Misaligned Data access Exception, for emulating in software * Entry Point for Misaligned Data access Exception, for emulating in software
*/ */
int do_misaligned_access(unsigned long cause, unsigned long address, int do_misaligned_access(unsigned long address, struct pt_regs *regs,
struct pt_regs *regs, struct callee_regs *cregs) struct callee_regs *cregs)
{ {
if (misaligned_fixup(address, regs, cause, cregs) != 0) if (misaligned_fixup(address, regs, cregs) != 0)
return do_misaligned_error(cause, address, regs); return do_misaligned_error(address, regs);
return 0; return 0;
} }
...@@ -104,10 +102,9 @@ int do_misaligned_access(unsigned long cause, unsigned long address, ...@@ -104,10 +102,9 @@ int do_misaligned_access(unsigned long cause, unsigned long address,
* Entry point for miscll errors such as Nested Exceptions * Entry point for miscll errors such as Nested Exceptions
* -Duplicate TLB entry is handled seperately though * -Duplicate TLB entry is handled seperately though
*/ */
void do_machine_check_fault(unsigned long cause, unsigned long address, void do_machine_check_fault(unsigned long address, struct pt_regs *regs)
struct pt_regs *regs)
{ {
die("Machine Check Exception", regs, address, cause); die("Machine Check Exception", regs, address);
} }
...@@ -120,23 +117,22 @@ void do_machine_check_fault(unsigned long cause, unsigned long address, ...@@ -120,23 +117,22 @@ void do_machine_check_fault(unsigned long cause, unsigned long address,
* -1 used for software breakpointing (gdb) * -1 used for software breakpointing (gdb)
* -2 used by kprobes * -2 used by kprobes
*/ */
void do_non_swi_trap(unsigned long cause, unsigned long address, void do_non_swi_trap(unsigned long address, struct pt_regs *regs)
struct pt_regs *regs)
{ {
unsigned int param = cause & 0xff; unsigned int param = regs->ecr_param;
switch (param) { switch (param) {
case 1: case 1:
trap_is_brkpt(cause, address, regs); trap_is_brkpt(address, regs);
break; break;
case 2: case 2:
trap_is_kprobe(param, address, regs); trap_is_kprobe(address, regs);
break; break;
case 3: case 3:
case 4: case 4:
kgdb_trap(regs, param); kgdb_trap(regs);
break; break;
default: default:
...@@ -149,14 +145,14 @@ void do_non_swi_trap(unsigned long cause, unsigned long address, ...@@ -149,14 +145,14 @@ void do_non_swi_trap(unsigned long cause, unsigned long address,
* -For a corner case, ARC kprobes implementation resorts to using * -For a corner case, ARC kprobes implementation resorts to using
* this exception, hence the check * this exception, hence the check
*/ */
void do_insterror_or_kprobe(unsigned long cause, void do_insterror_or_kprobe(unsigned long address, struct pt_regs *regs)
unsigned long address,
struct pt_regs *regs)
{ {
int rc;
/* Check if this exception is caused by kprobes */ /* Check if this exception is caused by kprobes */
if (notify_die(DIE_IERR, "kprobe_ierr", regs, address, rc = notify_die(DIE_IERR, "kprobe_ierr", regs, address, 0, SIGILL);
cause, SIGILL) == NOTIFY_STOP) if (rc == NOTIFY_STOP)
return; return;
insterror_is_error(cause, address, regs); insterror_is_error(address, regs);
} }
...@@ -209,10 +209,9 @@ void show_regs(struct pt_regs *regs) ...@@ -209,10 +209,9 @@ void show_regs(struct pt_regs *regs)
} }
void show_kernel_fault_diag(const char *str, struct pt_regs *regs, void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
unsigned long address, unsigned long cause_reg) unsigned long address)
{ {
current->thread.fault_address = address; current->thread.fault_address = address;
current->thread.cause_code = cause_reg;
/* Caller and Callee regs */ /* Caller and Callee regs */
show_regs(regs); show_regs(regs);
......
...@@ -187,7 +187,7 @@ fault: state->fault = 1; ...@@ -187,7 +187,7 @@ fault: state->fault = 1;
* Returns 0 if successfully handled, 1 if some error happened * Returns 0 if successfully handled, 1 if some error happened
*/ */
int misaligned_fixup(unsigned long address, struct pt_regs *regs, int misaligned_fixup(unsigned long address, struct pt_regs *regs,
unsigned long cause, struct callee_regs *cregs) struct callee_regs *cregs)
{ {
struct disasm_state state; struct disasm_state state;
char buf[TASK_COMM_LEN]; char buf[TASK_COMM_LEN];
......
...@@ -52,15 +52,14 @@ static int handle_vmalloc_fault(struct mm_struct *mm, unsigned long address) ...@@ -52,15 +52,14 @@ static int handle_vmalloc_fault(struct mm_struct *mm, unsigned long address)
return 1; return 1;
} }
void do_page_fault(struct pt_regs *regs, unsigned long address, void do_page_fault(struct pt_regs *regs, unsigned long address)
unsigned long cause_code)
{ {
struct vm_area_struct *vma = NULL; struct vm_area_struct *vma = NULL;
struct task_struct *tsk = current; struct task_struct *tsk = current;
struct mm_struct *mm = tsk->mm; struct mm_struct *mm = tsk->mm;
siginfo_t info; siginfo_t info;
int fault, ret; int fault, ret;
int write = cause_code & (1 << ECR_C_BIT_DTLB_ST_MISS); /* ST/EX */ int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
(write ? FAULT_FLAG_WRITE : 0); (write ? FAULT_FLAG_WRITE : 0);
...@@ -111,7 +110,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -111,7 +110,8 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
/* Handle protection violation, execute on heap or stack */ /* Handle protection violation, execute on heap or stack */
if (cause_code == ((ECR_V_PROTV << 16) | ECR_C_PROTV_INST_FETCH)) if ((regs->ecr_vec == ECR_V_PROTV) &&
(regs->ecr_cause == ECR_C_PROTV_INST_FETCH))
goto bad_area; goto bad_area;
if (write) { if (write) {
...@@ -178,7 +178,6 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -178,7 +178,6 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
/* User mode accesses just cause a SIGSEGV */ /* User mode accesses just cause a SIGSEGV */
if (user_mode(regs)) { if (user_mode(regs)) {
tsk->thread.fault_address = address; tsk->thread.fault_address = address;
tsk->thread.cause_code = cause_code;
info.si_signo = SIGSEGV; info.si_signo = SIGSEGV;
info.si_errno = 0; info.si_errno = 0;
/* info.si_code has been set above */ /* info.si_code has been set above */
...@@ -199,7 +198,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -199,7 +198,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
if (fixup_exception(regs)) if (fixup_exception(regs))
return; return;
die("Oops", regs, address, cause_code); die("Oops", regs, address);
out_of_memory: out_of_memory:
if (is_global_init(tsk)) { if (is_global_init(tsk)) {
...@@ -220,7 +219,6 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, ...@@ -220,7 +219,6 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
goto no_context; goto no_context;
tsk->thread.fault_address = address; tsk->thread.fault_address = address;
tsk->thread.cause_code = cause_code;
info.si_signo = SIGBUS; info.si_signo = SIGBUS;
info.si_errno = 0; info.si_errno = 0;
info.si_code = BUS_ADRERR; info.si_code = BUS_ADRERR;
......
...@@ -382,7 +382,6 @@ do_slow_path_pf: ...@@ -382,7 +382,6 @@ do_slow_path_pf:
; ------- setup args for Linux Page fault Hanlder --------- ; ------- setup args for Linux Page fault Hanlder ---------
mov_s r0, sp mov_s r0, sp
lr r1, [efa] lr r1, [efa]
lr r2, [ecr]
; We don't want exceptions to be disabled while the fault is handled. ; We don't want exceptions to be disabled while the fault is handled.
; Now that we have saved the context we return from exception hence ; Now that we have saved the context we return from exception hence
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment