From 990129dbfaad967b04ba3677cf90dffd49d9b070 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 12 Jun 2013 10:05:13 +0530 Subject: [PATCH] ARC: Use real ECR for pt_regs->event vs. synthetic values pt_regs->event was set with artificial values to identify the low level system event (syscall trap / breakpoint trap / exceptions / interrupts) Now we save CPU ECR (Exception Cause Register) itself in there. Only for Interrupts, where ECR is not applicable, do we resort to synthetic non ECR values. The ptrace helpers now use the sub-fields of ECR to distinguish the events (e.g. vector 0x25 is trap, param 0 is syscall...) The following benefits will follow: (1) This centralizes the location of where ECR is saved and will allow the cleanup of task->thread.cause_code ECR placeholder which is set in non-uniform way. Then ARC VM code can safely rely on it being there for purpose of finer grained VM_EXEC dcache flush (based on exec fault: I-TLB Miss) (2) Further, ECR being passed around from low level handlers as arg can be eliminated. Signed-off-by: Vineet Gupta --- arch/arc/include/asm/arcregs.h | 4 ++++ arch/arc/include/asm/entry.h | 19 +++-------------- arch/arc/include/asm/ptrace.h | 38 ++++++++++++++++++++++------------ arch/arc/kernel/entry.S | 6 ++---- arch/arc/kernel/kgdb.c | 2 +- arch/arc/kernel/process.c | 2 +- arch/arc/kernel/troubleshoot.c | 12 +++++------ 7 files changed, 41 insertions(+), 42 deletions(-) diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index 122e9af46824..ff92c23bbaf9 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -60,6 +60,7 @@ #define ECR_V_ITLB_MISS 0x21 #define ECR_V_DTLB_MISS 0x22 #define ECR_V_PROTV 0x23 +#define ECR_V_TRAP 0x25 /* Protection Violation Exception Cause Code Values */ #define ECR_C_PROTV_INST_FETCH 0x00 @@ -77,6 +78,9 @@ #define ECR_C_BIT_DTLB_LD_MISS 8 #define ECR_C_BIT_DTLB_ST_MISS 9 +/* Dummy ECR values for Interrupts */ +#define event_IRQ1 0x00310000 +#define event_IRQ2 0x00320000 /* Auxiliary registers */ #define AUX_IDENTITY 4 diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h index 4a7e7ea0ed3d..af53bab2de84 100644 --- a/arch/arc/include/asm/entry.h +++ b/arch/arc/include/asm/entry.h @@ -391,9 +391,10 @@ * Note that syscalls are implemented via TRAP which is also a exception * from CPU's point of view *-------------------------------------------------------------*/ -.macro SAVE_ALL_EXCEPTION marker +.macro SAVE_ALL_SYS - st \marker, [sp, 8] /* event */ + lr r9, [ecr] + st r9, [sp, 8] /* event */ st r0, [sp, 4] /* orig_r0, needed only for sys calls */ /* Restore r9 used to code the early prologue */ @@ -411,20 +412,6 @@ PUSHAX erbta .endm -/*-------------------------------------------------------------- - * Save scratch regs for exceptions - *-------------------------------------------------------------*/ -.macro SAVE_ALL_SYS - SAVE_ALL_EXCEPTION event_EXCPN -.endm - -/*-------------------------------------------------------------- - * Save scratch regs for sys calls - *-------------------------------------------------------------*/ -.macro SAVE_ALL_TRAP - SAVE_ALL_EXCEPTION event_SCALL -.endm - /*-------------------------------------------------------------- * Restore all registers used by system call or Exceptions * SP should always be pointing to the next free stack element diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index e98b9c2c34e1..c9938e7a7dbd 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -44,8 +44,25 @@ struct pt_regs { long sp; /* user/kernel sp depending on where we came from */ long orig_r0; - /*to distinguish bet excp, syscall, irq */ - unsigned long event; + /* + * To distinguish bet excp, syscall, irq + * For traps and exceptions, Exception Cause Register. + * ECR: <00> + * Last word used by Linux for extra state mgmt (syscall-restart) + * For interrupts, use artificial ECR values to note current prio-level + */ + union { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned long state:8, ecr_vec:8, + ecr_cause:8, ecr_param:8; +#else + unsigned long ecr_param:8, ecr_cause:8, + ecr_vec:8, state:8; +#endif + }; + unsigned long event; + }; long user_r25; }; @@ -86,11 +103,13 @@ struct callee_regs { /* return 1 if PC in delay slot */ #define delay_mode(regs) ((regs->status32 & STATUS_DE_MASK) == STATUS_DE_MASK) -#define in_syscall(regs) (regs->event & event_SCALL) -#define in_brkpt_trap(regs) (regs->event & event_BRKPT) +#define in_syscall(regs) ((regs->ecr_vec == ECR_V_TRAP) && !regs->ecr_param) +#define in_brkpt_trap(regs) ((regs->ecr_vec == ECR_V_TRAP) && regs->ecr_param) -#define syscall_wont_restart(regs) (regs->event |= event_SCALL_RESTARTED) -#define syscall_restartable(regs) !(regs->event & event_SCALL_RESTARTED) +#define STATE_SCALL_RESTARTED 0x01 + +#define syscall_wont_restart(reg) (reg->state |= STATE_SCALL_RESTARTED) +#define syscall_restartable(reg) !(reg->state & STATE_SCALL_RESTARTED) #define current_pt_regs() \ ({ \ @@ -107,11 +126,4 @@ static inline long regs_return_value(struct pt_regs *regs) #endif /* !__ASSEMBLY__ */ -#define event_SCALL 0x0001 -#define event_SCALL_RESTARTED 0x0002 -#define event_BRKPT 0x0004 -#define event_EXCPN 0x0008 -#define event_IRQ1 0x0010 -#define event_IRQ2 0x0020 - #endif /* __ASM_PTRACE_H */ diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index 18321241f07b..89a955dab267 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -142,7 +142,7 @@ VECTOR reserved ; Reserved Exceptions .endr #include /* ARC_{EXTRY,EXIT} */ -#include /* SAVE_ALL_{INT1,INT2,TRAP...} */ +#include /* SAVE_ALL_{INT1,INT2,SYS...} */ #include #include #include @@ -495,8 +495,6 @@ tracesys_exit: trap_with_param: ; stop_pc info by gdb needs this info - st event_BRKPT, [sp, PT_event] - mov r0, r12 lr r1, [efa] mov r2, sp @@ -541,7 +539,7 @@ ARC_ENTRY EV_Trap lr r9, [erstatus] SWITCH_TO_KERNEL_STK - SAVE_ALL_TRAP + SAVE_ALL_SYS ;------- (4) What caused the Trap -------------- lr r12, [ecr] diff --git a/arch/arc/kernel/kgdb.c b/arch/arc/kernel/kgdb.c index 52bdc83c1495..84f1bb8208b4 100644 --- a/arch/arc/kernel/kgdb.c +++ b/arch/arc/kernel/kgdb.c @@ -181,7 +181,7 @@ void kgdb_trap(struct pt_regs *regs, int param) * with trap_s 4 (compiled) breakpoints, continuation needs to * start after the breakpoint. */ - if (param == 3) + if (regs->ecr_param == 3) instruction_pointer(regs) -= BREAK_INSTR_SIZE; kgdb_handle_exception(1, SIGTRAP, 0, regs); diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index 3e748f1b1f8a..07a3a968fe49 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -76,7 +76,7 @@ asmlinkage void ret_from_fork(void); * ------------------ * | SP | * | orig_r0 | - * | event | + * | event/ECR | * | user_r25 | * ------------------ <===== END of PAGE */ diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c index 31a5d8905e1a..977464126be9 100644 --- a/arch/arc/kernel/troubleshoot.c +++ b/arch/arc/kernel/troubleshoot.c @@ -117,17 +117,16 @@ static void show_faulting_vma(unsigned long address, char *buf) static void show_ecr_verbose(struct pt_regs *regs) { - unsigned int vec, cause_code, cause_reg; + unsigned int vec, cause_code; unsigned long address; - cause_reg = current->thread.cause_code; - pr_info("\n[ECR ]: 0x%08x => ", cause_reg); + pr_info("\n[ECR ]: 0x%08lx => ", regs->event); /* For Data fault, this is data address not instruction addr */ address = current->thread.fault_address; - vec = cause_reg >> 16; - cause_code = (cause_reg >> 8) & 0xFF; + vec = regs->ecr_vec; + cause_code = regs->ecr_cause; /* For DTLB Miss or ProtV, display the memory involved too */ if (vec == ECR_V_DTLB_MISS) { @@ -174,8 +173,7 @@ void show_regs(struct pt_regs *regs) print_task_path_n_nm(tsk, buf); show_regs_print_info(KERN_INFO); - if (current->thread.cause_code) - show_ecr_verbose(regs); + show_ecr_verbose(regs); pr_info("[EFA ]: 0x%08lx\n[BLINK ]: %pS\n[ERET ]: %pS\n", current->thread.fault_address, -- 2.39.5