]> Pileus Git - ~andy/linux/commitdiff
ARC: pt_regs update #5: Use real ECR for pt_regs->event vs. synth values
authorVineet Gupta <vgupta@synopsys.com>
Tue, 11 Jun 2013 13:26:54 +0000 (18:56 +0530)
committerVineet Gupta <vgupta@synopsys.com>
Wed, 26 Jun 2013 08:34:48 +0000 (14:04 +0530)
pt_regs->event was set with artificial values to identify the low level
system event (syscall trap / breakpoint trap / exceptions / interrupts)

With r8 saving out of the way, the full word can be used to save real
ECR (Exception Cause Register) which helps idenify the event naturally,
including additional info such as cause code, param.
Only for Interrupts, where ECR is not applicable, do we resort to
synthetic non ECR values.

SAVE_ALL_TRAP/EXCEPTIONS can now be merged as they both use ECR with
different runtime 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 as it is part of standard reg-file in pt_regs

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/asm-offsets.c
arch/arc/kernel/entry.S
arch/arc/kernel/kgdb.c
arch/arc/kernel/process.c
arch/arc/kernel/troubleshoot.c

index 122e9af468245111d3a2f84683455de816f097a4..355cb470c2a4770f7ba9d06a93dd8aa162789680 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             0x0031abcd
+#define event_IRQ2             0x0032abcd
 
 /* Auxiliary registers */
 #define AUX_IDENTITY           4
index de01bc842a9acb9e7578ffa33e76e0fb5e8ae440..8943c028d4bbe3ae2aea2875aae5c2d7e3dd2bda 100644 (file)
 #endif
 
        /* Save Pre Intr/Exception User SP on kernel stack */
-       st.a    sp, [r9, -16]   ; Make room for orig_r0, orig_r8, user_r25
+       st.a    sp, [r9, -16]   ; Make room for orig_r0, ECR, user_r25
 
        /* CAUTION:
         * SP should be set at the very end when we are done with everything
  * 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]        /* orig_r8 */
+       lr      r9, [ecr]
+       st      r9, [sp, 8]    /* ECR */
        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  orig_r8_IS_EXCPN
-.endm
-
-/*--------------------------------------------------------------
- * Save scratch regs for sys calls
- *-------------------------------------------------------------*/
-.macro SAVE_ALL_TRAP
-       SAVE_ALL_EXCEPTION  orig_r8_IS_SCALL
-.endm
-
 /*--------------------------------------------------------------
  * Restore all registers used by system call or Exceptions
  * SP should always be pointing to the next free stack element
        RESTORE_R12_TO_R0
 
        ld  sp, [sp] /* restore original sp */
-       /* orig_r0, orig_r8, user_r25 skipped automatically */
+       /* orig_r0, ECR, user_r25 skipped automatically */
 .endm
 
 
 #endif
 
        /* now we are ready to save the remaining context :) */
-       st      orig_r8_IS_IRQ1, [sp, 8]    /* Event Type */
+       st      event_IRQ1, [sp, 8]    /* Dummy ECR */
        st      0, [sp, 4]    /* orig_r0 , N/A for IRQ */
 
        SAVE_R0_TO_R12
        ld  r9, [@int2_saved_reg]
 
        /* now we are ready to save the remaining context :) */
-       st      orig_r8_IS_IRQ2, [sp, 8]    /* Event Type */
+       st      event_IRQ2, [sp, 8]    /* Dummy ECR */
        st      0, [sp, 4]    /* orig_r0 , N/A for IRQ */
 
        SAVE_R0_TO_R12
        RESTORE_R12_TO_R0
 
        ld  sp, [sp] /* restore original sp */
-       /* orig_r0, orig_r8, user_r25 skipped automatically */
+       /* orig_r0, ECR, user_r25 skipped automatically */
 .endm
 
 .macro RESTORE_ALL_INT2
        RESTORE_R12_TO_R0
 
        ld  sp, [sp] /* restore original sp */
-       /* orig_r0, orig_r8, user_r25 skipped automatically */
+       /* orig_r0, ECR, user_r25 skipped automatically */
 .endm
 
 
index 7b2de6f7025a22c4e58ebe70832cc25d1f715aca..c9938e7a7dbd3b596fc3c0021d8ff57548719402 100644 (file)
@@ -44,15 +44,24 @@ struct pt_regs {
        long sp;        /* user/kernel sp depending on where we came from  */
        long orig_r0;
 
-       /*to distinguish bet excp, syscall, irq */
+       /*
+        * 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
-               /* so that assembly code is same for LE/BE */
-               unsigned long orig_r8:16, event:16;
+                       unsigned long state:8, ecr_vec:8,
+                                     ecr_cause:8, ecr_param:8;
 #else
-               unsigned long event:16, orig_r8:16;
+                       unsigned long ecr_param:8, ecr_cause:8,
+                                     ecr_vec:8, state:8;
 #endif
-               long orig_r8_word;
+               };
+               unsigned long event;
        };
 
        long user_r25;
@@ -94,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 & orig_r8_IS_SCALL)
-#define in_brkpt_trap(regs) (regs->event & orig_r8_IS_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 |= orig_r8_IS_SCALL_RESTARTED)
-#define syscall_restartable(regs) !(regs->event &  orig_r8_IS_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()                                      \
 ({                                                             \
@@ -115,11 +126,4 @@ static inline long regs_return_value(struct pt_regs *regs)
 
 #endif /* !__ASSEMBLY__ */
 
-#define orig_r8_IS_SCALL               0x0001
-#define orig_r8_IS_SCALL_RESTARTED     0x0002
-#define orig_r8_IS_BRKPT               0x0004
-#define orig_r8_IS_EXCPN               0x0008
-#define orig_r8_IS_IRQ1                        0x0010
-#define orig_r8_IS_IRQ2                        0x0020
-
 #endif /* __ASM_PTRACE_H */
index 75f05b83d77d309322122c7d4c2b05b0f5f64f6a..6c3aa0edb9b5bc1914d006b2a22b766f71adba9c 100644 (file)
@@ -46,7 +46,7 @@ int main(void)
        BLANK();
 
        DEFINE(PT_status32, offsetof(struct pt_regs, status32));
-       DEFINE(PT_orig_r8, offsetof(struct pt_regs, orig_r8_word));
+       DEFINE(PT_event, offsetof(struct pt_regs, event));
        DEFINE(PT_sp, offsetof(struct pt_regs, sp));
        DEFINE(PT_r0, offsetof(struct pt_regs, r0));
        DEFINE(PT_r1, offsetof(struct pt_regs, r1));
index fd5f9160bbd215845f773454dba2e52cdb3d242e..fb0fe3265637a11d44675ea5a3b79df9941ee3e2 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
-       stw orig_r8_IS_BRKPT, [sp, PT_orig_r8]
-
        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]
@@ -696,8 +694,17 @@ not_exception:
 
 #ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS
 
+       ; Level 2 interrupt return Path - from hardware standpoint
        bbit0  r10, STATUS_A2_BIT, not_level2_interrupt
 
+       ;------------------------------------------------------------------
+       ; However the context returning might not have taken L2 intr itself
+       ; e.g. Task'A' user-code -> L2 intr -> schedule -> 'B' user-code ret
+       ; Special considerations needed for the context which took L2 intr
+
+       ld   r9, [sp, PT_event]        ; Ensure this is L2 intr context
+       brne r9, event_IRQ2, 149f
+
        ;------------------------------------------------------------------
        ; if L2 IRQ interrupted a L1 ISR,  we'd disbaled preemption earlier
        ; so that sched doesnt move to new task, causing L1 to be delayed
@@ -705,19 +712,15 @@ not_exception:
        ; things to what they were, before returning from L2 context
        ;----------------------------------------------------------------
 
-       ldw  r9, [sp, PT_orig_r8]      ; get orig_r8 to make sure it is
-       brne r9, orig_r8_IS_IRQ2, 149f ; infact a L2 ISR ret path
-
        ld r9, [sp, PT_status32]       ; get statu32_l2 (saved in pt_regs)
        bbit0 r9, STATUS_A1_BIT, 149f  ; L1 not active when L2 IRQ, so normal
 
-       ; A1 is set in status32_l2
        ; decrement thread_info->preempt_count (re-enable preemption)
        GET_CURR_THR_INFO_FROM_SP   r10
        ld      r9, [r10, THREAD_INFO_PREEMPT_COUNT]
 
        ; paranoid check, given A1 was active when A2 happened, preempt count
-       ; must not be 0 beccause we would have incremented it.
+       ; must not be 0 because we would have incremented it.
        ; If this does happen we simply HALT as it means a BUG !!!
        cmp     r9, 0
        bnz     2f
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 a3cc6a57703924f29b0349b7cec8fea0c632c8ec..07a3a968fe49a113e94c2a894895db09362108ac 100644 (file)
@@ -76,7 +76,7 @@ asmlinkage void ret_from_fork(void);
  * ------------------
  * |      SP        |
  * |    orig_r0     |
- * |    orig_r8     |
+ * |    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,