]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ARC: Use real ECR for pt_regs->event vs. synthetic values
authorVineet Gupta <vgupta@synopsys.com>
Wed, 12 Jun 2013 04:35:13 +0000 (10:05 +0530)
committerVineet Gupta <vgupta@synopsys.com>
Mon, 17 Jun 2013 13:02:23 +0000 (18:32 +0530)
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 <vgupta@synopsys.com>
arch/arc/include/asm/arcregs.h
arch/arc/include/asm/entry.h
arch/arc/include/asm/ptrace.h
arch/arc/kernel/entry.S
arch/arc/kernel/kgdb.c
arch/arc/kernel/process.c
arch/arc/kernel/troubleshoot.c

index 122e9af468245111d3a2f84683455de816f097a4..ff92c23bbaf9e6752ed38c7fc40cb1fc11cef6c4 100644 (file)
@@ -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
index 4a7e7ea0ed3dd13cde26a7b7ed149d90f2c01111..af53bab2de84da528cbf83e382721ae5de0308e4 100644 (file)
  * 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 */
        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
index e98b9c2c34e170d55fb33d26d0b06b4071de6623..c9938e7a7dbd3b596fc3c0021d8ff57548719402 100644 (file)
@@ -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> <VV> <CC> <PP>
+        *      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 */
index 18321241f07b2b9fd41bbf50a15670498261db01..89a955dab267e071a230a85738485dc960c31575 100644 (file)
@@ -142,7 +142,7 @@ VECTOR   reserved                ; Reserved Exceptions
 .endr
 
 #include <linux/linkage.h>   /* ARC_{EXTRY,EXIT} */
-#include <asm/entry.h>       /* SAVE_ALL_{INT1,INT2,TRAP...} */
+#include <asm/entry.h>       /* SAVE_ALL_{INT1,INT2,SYS...} */
 #include <asm/errno.h>
 #include <asm/arcregs.h>
 #include <asm/irqflags.h>
@@ -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]
index 52bdc83c1495b5bf31a685998f7a5d7b9a1bd15e..84f1bb8208b444466e12acc82dd2925af3717374 100644 (file)
@@ -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);
index 3e748f1b1f8a478ee568eab84d4f80c7fa0cdeb1..07a3a968fe49a113e94c2a894895db09362108ac 100644 (file)
@@ -76,7 +76,7 @@ asmlinkage void ret_from_fork(void);
  * ------------------
  * |      SP        |
  * |    orig_r0     |
- * |    event       |
+ * |    event/ECR   |
  * |    user_r25    |
  * ------------------  <===== END of PAGE
  */
index 31a5d8905e1aecc76b0b3ce54521651800a4d147..977464126be949ac0ab241db52809441e635264e 100644 (file)
@@ -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,