mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 08:14:15 +08:00
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:
parent
502a0c775c
commit
38a9ff6d24
@ -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(); \
|
||||
|
@ -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__ */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user