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: Vineet Gupta <vgupta@synopsys.com>
This commit is contained in:
Vineet Gupta 2013-06-12 15:13:40 +05:30
parent 502a0c775c
commit 38a9ff6d24
13 changed files with 59 additions and 78 deletions

View File

@ -18,9 +18,8 @@ struct task_struct;
void show_regs(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,
unsigned long address, unsigned long cause_reg);
void die(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);
#define BUG() do { \
dump_stack(); \

View File

@ -31,7 +31,7 @@ static inline void arch_kgdb_breakpoint(void)
__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 {
_R0 = 0,
@ -53,7 +53,7 @@ enum arc700_linux_regnums {
};
#else
#define kgdb_trap(regs, param)
#define kgdb_trap(regs)
#endif
#endif /* __ARC_KGDB_H__ */

View File

@ -50,11 +50,9 @@ struct kprobe_ctlblk {
int kprobe_fault_handler(struct pt_regs *regs, unsigned long cause);
void kretprobe_trampoline(void);
void trap_is_kprobe(unsigned long cause, unsigned long address,
struct pt_regs *regs);
void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
#else
static void trap_is_kprobe(unsigned long cause, unsigned long address,
struct pt_regs *regs)
static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
{
}
#endif

View File

@ -29,7 +29,6 @@ struct thread_struct {
unsigned long ksp; /* kernel mode stack pointer */
unsigned long callee_reg; /* pointer to callee regs */
unsigned long fault_address; /* dbls as brkpt holder as well */
unsigned long cause_code; /* Exception Cause Code (ECR) */
#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
struct arc_fpu fpu;
#endif

View File

@ -16,11 +16,11 @@
#ifdef CONFIG_ARC_MISALIGN_ACCESS
int misaligned_fixup(unsigned long address, struct pt_regs *regs,
unsigned long cause, struct callee_regs *cregs);
struct callee_regs *cregs);
#else
static inline int
misaligned_fixup(unsigned long address, struct pt_regs *regs,
unsigned long cause, struct callee_regs *cregs)
struct callee_regs *cregs)
{
return 0;
}

View File

@ -274,10 +274,8 @@ ARC_ENTRY instr_service
SWITCH_TO_KERNEL_STK
SAVE_ALL_SYS
lr r0, [ecr]
lr r1, [efa]
mov r2, sp
lr r0, [efa]
mov r1, sp
FAKE_RET_FROM_EXCPN r9
@ -298,9 +296,8 @@ ARC_ENTRY mem_service
SWITCH_TO_KERNEL_STK
SAVE_ALL_SYS
lr r0, [ecr]
lr r1, [efa]
mov r2, sp
lr r0, [efa]
mov r1, sp
bl do_memory_error
b ret_from_exception
ARC_EXIT mem_service
@ -317,11 +314,11 @@ ARC_ENTRY EV_MachineCheck
SWITCH_TO_KERNEL_STK
SAVE_ALL_SYS
lr r0, [ecr]
lr r1, [efa]
mov r2, sp
lr r2, [ecr]
lr r0, [efa]
mov r1, sp
lsr r3, r0, 8
lsr r3, r2, 8
bmsk r3, r3, 7
brne r3, ECR_C_MCHK_DUP_TLB, 1f
@ -384,12 +381,12 @@ ARC_ENTRY EV_TLBProtV
;========== (6b) Non aligned access ============
4:
mov r0, r2 ; cause code
mov r2, sp ; pt_regs
mov r0, r1
mov r1, sp ; pt_regs
#ifdef CONFIG_ARC_MISALIGN_ACCESS
SAVE_CALLEE_SAVED_USER
mov r3, sp ; callee_regs
mov r2, sp ; callee_regs
bl do_misaligned_access
@ -416,9 +413,8 @@ ARC_ENTRY EV_PrivilegeV
SWITCH_TO_KERNEL_STK
SAVE_ALL_SYS
lr r0, [ecr]
lr r1, [efa]
mov r2, sp
lr r0, [efa]
mov r1, sp
FAKE_RET_FROM_EXCPN r9
@ -437,9 +433,8 @@ ARC_ENTRY EV_Extension
SWITCH_TO_KERNEL_STK
SAVE_ALL_SYS
lr r0, [ecr]
lr r1, [efa]
mov r2, sp
lr r0, [efa]
mov r1, sp
bl do_extension_fault
b ret_from_exception
ARC_EXIT EV_Extension
@ -495,9 +490,8 @@ tracesys_exit:
trap_with_param:
; stop_pc info by gdb needs this info
mov r0, r12
lr r1, [efa]
mov r2, sp
lr r0, [efa]
mov r1, sp
; Now that we have read EFA, its safe to do "fake" rtie
; and get out of CPU exception mode

View File

@ -169,7 +169,7 @@ int kgdb_arch_init(void)
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
* instructions, while trap_s 4 is used for compiled breakpoints.

View File

@ -517,8 +517,7 @@ int __kprobes arch_trampoline_kprobe(struct kprobe *p)
return 0;
}
void trap_is_kprobe(unsigned long cause, unsigned long address,
struct pt_regs *regs)
void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
{
notify_die(DIE_TRAP, "kprobe_trap", regs, address, cause, SIGTRAP);
notify_die(DIE_TRAP, "kprobe_trap", regs, address, 0, SIGTRAP);
}

View File

@ -28,10 +28,9 @@ void __init trap_init(void)
return;
}
void die(const char *str, struct pt_regs *regs, unsigned long address,
unsigned long cause_reg)
void die(const char *str, struct pt_regs *regs, unsigned long address)
{
show_kernel_fault_diag(str, regs, address, cause_reg);
show_kernel_fault_diag(str, regs, address);
/* DEAD END */
__asm__("flag 1");
@ -42,14 +41,13 @@ void die(const char *str, struct pt_regs *regs, unsigned long address,
* -for user faults enqueues requested signal
* -for kernel, chk if due to copy_(to|from)_user, otherwise die()
*/
static noinline int handle_exception(unsigned long cause, char *str,
struct pt_regs *regs, siginfo_t *info)
static noinline int
handle_exception(const char *str, struct pt_regs *regs, siginfo_t *info)
{
if (user_mode(regs)) {
struct task_struct *tsk = current;
tsk->thread.fault_address = (__force unsigned int)info->si_addr;
tsk->thread.cause_code = cause;
force_sig_info(info->si_signo, info, tsk);
@ -58,14 +56,14 @@ static noinline int handle_exception(unsigned long cause, char *str,
if (fixup_exception(regs))
return 0;
die(str, regs, (unsigned long)info->si_addr, cause);
die(str, regs, (unsigned long)info->si_addr);
}
return 1;
}
#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 = { \
.si_signo = signr, \
@ -73,7 +71,7 @@ int name(unsigned long cause, unsigned long address, struct pt_regs *regs) \
.si_code = sicode, \
.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)
/*
* Entry Point for Misaligned Data access Exception, for emulating in software
*/
int do_misaligned_access(unsigned long cause, unsigned long address,
struct pt_regs *regs, struct callee_regs *cregs)
int do_misaligned_access(unsigned long address, struct pt_regs *regs,
struct callee_regs *cregs)
{
if (misaligned_fixup(address, regs, cause, cregs) != 0)
return do_misaligned_error(cause, address, regs);
if (misaligned_fixup(address, regs, cregs) != 0)
return do_misaligned_error(address, regs);
return 0;
}
@ -104,10 +102,9 @@ int do_misaligned_access(unsigned long cause, unsigned long address,
* Entry point for miscll errors such as Nested Exceptions
* -Duplicate TLB entry is handled seperately though
*/
void do_machine_check_fault(unsigned long cause, unsigned long address,
struct pt_regs *regs)
void do_machine_check_fault(unsigned long address, 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,
* -1 used for software breakpointing (gdb)
* -2 used by kprobes
*/
void do_non_swi_trap(unsigned long cause, unsigned long address,
struct pt_regs *regs)
void do_non_swi_trap(unsigned long address, struct pt_regs *regs)
{
unsigned int param = cause & 0xff;
unsigned int param = regs->ecr_param;
switch (param) {
case 1:
trap_is_brkpt(cause, address, regs);
trap_is_brkpt(address, regs);
break;
case 2:
trap_is_kprobe(param, address, regs);
trap_is_kprobe(address, regs);
break;
case 3:
case 4:
kgdb_trap(regs, param);
kgdb_trap(regs);
break;
default:
@ -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
* this exception, hence the check
*/
void do_insterror_or_kprobe(unsigned long cause,
unsigned long address,
struct pt_regs *regs)
void do_insterror_or_kprobe(unsigned long address, struct pt_regs *regs)
{
int rc;
/* Check if this exception is caused by kprobes */
if (notify_die(DIE_IERR, "kprobe_ierr", regs, address,
cause, SIGILL) == NOTIFY_STOP)
rc = notify_die(DIE_IERR, "kprobe_ierr", regs, address, 0, SIGILL);
if (rc == NOTIFY_STOP)
return;
insterror_is_error(cause, address, regs);
insterror_is_error(address, regs);
}

View File

@ -209,10 +209,9 @@ void show_regs(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.cause_code = cause_reg;
/* Caller and Callee regs */
show_regs(regs);

View File

@ -187,7 +187,7 @@ fault: state->fault = 1;
* Returns 0 if successfully handled, 1 if some error happened
*/
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;
char buf[TASK_COMM_LEN];

View File

@ -52,15 +52,14 @@ bad_area:
return 1;
}
void do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long cause_code)
void do_page_fault(struct pt_regs *regs, unsigned long address)
{
struct vm_area_struct *vma = NULL;
struct task_struct *tsk = current;
struct mm_struct *mm = tsk->mm;
siginfo_t info;
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 |
(write ? FAULT_FLAG_WRITE : 0);
@ -111,7 +110,8 @@ good_area:
/* 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;
if (write) {
@ -178,7 +178,6 @@ bad_area_nosemaphore:
/* User mode accesses just cause a SIGSEGV */
if (user_mode(regs)) {
tsk->thread.fault_address = address;
tsk->thread.cause_code = cause_code;
info.si_signo = SIGSEGV;
info.si_errno = 0;
/* info.si_code has been set above */
@ -199,7 +198,7 @@ no_context:
if (fixup_exception(regs))
return;
die("Oops", regs, address, cause_code);
die("Oops", regs, address);
out_of_memory:
if (is_global_init(tsk)) {
@ -220,7 +219,6 @@ do_sigbus:
goto no_context;
tsk->thread.fault_address = address;
tsk->thread.cause_code = cause_code;
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_ADRERR;

View File

@ -382,7 +382,6 @@ do_slow_path_pf:
; ------- setup args for Linux Page fault Hanlder ---------
mov_s r0, sp
lr r1, [efa]
lr r2, [ecr]
; 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