To avoid multiple syscall restarts (multiple signals) or no restart at
all (sigreturn), we need just an extra bit of state "literally 1 bit" in
struct pt_regs. orig_r8 is the best place to do this, however given the
way it is encoded currently, we can't add anything simplistically.

Current orig_r8:
* syscalls   -> 1 to NR_SYSCALLS
* Exceptions -> NR_SYSCALLS + 1
* Break-point-> NR_SYSCALLS + 2

In new scheme it is a bit-field
* lower short word contains the  exact event type (and a new bit to represent
   restart semantics : if syscall was already / can't be restarted)
* upper short word optionally containing the syscall num - needed by
  likes of tracehooks etc

This patch only changes how orig_r8 is organised and nothing should
change behaviourily.

Signed-off-by: Vineet Gupta <vgu...@synopsys.com>
Cc: Al Viro <v...@zeniv.linux.org.uk>
---
 arch/arc/include/asm/entry.h  |   29 +++++++++++++++++------------
 arch/arc/include/asm/ptrace.h |   15 +++++++++++----
 arch/arc/kernel/entry.S       |    4 ++--
 3 files changed, 30 insertions(+), 18 deletions(-)

diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h
index 6b42bf5..d72995b 100644
--- a/arch/arc/include/asm/entry.h
+++ b/arch/arc/include/asm/entry.h
@@ -343,18 +343,12 @@
  *-------------------------------------------------------------*/
 .macro SAVE_ALL_EXCEPTION   marker
 
+       st      \marker, [sp, 8]
+       st      r0, [sp, 4]    /* orig_r0, needed only for sys calls */
+
        /* Restore r9 used to code the early prologue */
        EXCPN_PROLOG_RESTORE_REG  r9
 
-       /* Save the complete regfile now */
-
-       /* orig_r8 marker:
-        * syscalls   -> 1 to NR_SYSCALLS
-        * Exceptions -> NR_SYSCALLS + 1
-        * Break-point-> NR_SYSCALLS + 2
-        */
-       st      \marker, [sp, 8]
-       st      r0, [sp, 4]    /* orig_r0, needed only for sys calls */
        SAVE_CALLER_SAVED
        st.a    r26, [sp, -4]   /* gp */
        st.a    fp, [sp, -4]
@@ -384,14 +378,25 @@
  * Save scratch regs for exceptions
  *-------------------------------------------------------------*/
 .macro SAVE_ALL_SYS
-       SAVE_ALL_EXCEPTION  (NR_syscalls + 1)
+       SAVE_ALL_EXCEPTION  orig_r8_IS_EXCPN
 .endm
 
 /*--------------------------------------------------------------
  * Save scratch regs for sys calls
  *-------------------------------------------------------------*/
 .macro SAVE_ALL_TRAP
-       SAVE_ALL_EXCEPTION  r8
+       /*
+        * Encode syscall number (r8) in upper short word of event type (r9)
+        * (r9 is already clobbered when we land here)
+        */
+#ifndef CONFIG_CPU_BIG_ENDIAN
+       lsl  r9, r8, 16
+       or   r9, r9, orig_r8_IS_SCALL
+#else
+       lsl  r9, orig_r8_IS_SCALL, 16
+       or   r9, r9, r8
+#endif
+       SAVE_ALL_EXCEPTION  r9
 .endm
 
 /*--------------------------------------------------------------
@@ -442,7 +447,7 @@
        ld  r9, [@int1_saved_reg]
 
        /* now we are ready to save the remaining context :) */
-       st     -1, [sp, 8]    /* orig_r8, -1 for interuppt level one */
+       st      orig_r8_IS_IRQ1, [sp, 8]    /* Event Type */
        st      0, [sp, 4]    /* orig_r0 , N/A for IRQ */
        SAVE_CALLER_SAVED
        st.a    r26, [sp, -4]   /* gp */
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 9abbb7c..ddb9ce7 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -81,7 +81,8 @@ struct pt_regs {
        long r0;
        long sp;        /* user/kernel sp depending on where we came from  */
        long orig_r0;
-       long orig_r8;   /*to distinguish bet excp, sys call, int1 or int2 */
+       /*to distinguish bet excp, syscall, irq */
+       unsigned long event_type:16, orig_r8:16;
 };
 
 /* Callee saved registers - need to be saved only when you are scheduled out */
@@ -126,12 +127,18 @@ struct user_regs_struct {
        sp;                     \
 })
 
-/* return 1 if in syscall, 0 if Intr or Exception */
-#define in_syscall(regs) (((regs->orig_r8) >= 0 && \
-                          (regs->orig_r8 <= NR_syscalls)) ? 1 : 0)
+#define in_syscall(regs) (regs->orig_r8 & orig_r8_IS_SCALL)
+#define in_brkpt_trap(regs) (regs->orig_r8 & orig_r8_IS_BRKPT)
 
 #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               0x0004
+#define orig_r8_IS_IRQ1                        0x0010
+#define orig_r8_IS_IRQ2                        0x0020
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASM_PTRACE_H */
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index efaf3de..0324ad1 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -354,8 +354,8 @@ ARC_EXIT EV_Extension
 
 trap_with_param:
 
-       ;make sure orig_r8 is a positive value
-       st  NR_syscalls + 2, [sp, PT_orig_r8]
+       ; stop_pc info by gdb needs this info
+       st  orig_r8_IS_BRKPT, [sp, PT_orig_r8]
 
        mov r0, r12
        lr  r1, [efa]
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to