ARC: [Review] Preparing to fix incorrect syscall restarts due to signals
authorVineet Gupta <vgupta@synopsys.com>
Mon, 11 Feb 2013 14:31:24 +0000 (20:01 +0530)
committerVineet Gupta <vgupta@synopsys.com>
Fri, 15 Feb 2013 17:45:49 +0000 (23:15 +0530)
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 <vgupta@synopsys.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>
arch/arc/include/asm/entry.h
arch/arc/include/asm/ptrace.h
arch/arc/kernel/asm-offsets.c
arch/arc/kernel/entry.S

index 6b42bf5c45ece02854a22d76ef9d321f02c11129..9eada5b28be6cc1ab221311e0349a095ff5b436f 100644 (file)
  *-------------------------------------------------------------*/
 .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]
  * 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
+       /*
+        * Setup pt_regs->orig_r8.
+        * Encode syscall number (r8) in upper short word of event type (r9)
+        * N.B. #1: This is already endian safe (see ptrace.h)
+        *      #2: Only r9 can be used as scratch as it is already clobbered
+        *          and it's contents are no longer needed by the latter part
+        *          of exception prologue
+        */
+       lsl  r9, r8, 16
+       or   r9, r9, orig_r8_IS_SCALL
+
+       SAVE_ALL_EXCEPTION  r9
 .endm
 
 /*--------------------------------------------------------------
        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 */
index 3afadefe335f0078fbc64bcae95a4ec982eaffbc..3ec89f467ac3f4713909bbdcd0501086624d767f 100644 (file)
@@ -50,7 +50,17 @@ 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 */
+       union {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+               /* so that assembly code is same for LE/BE */
+               unsigned long orig_r8:16, event:16;
+#else
+               unsigned long event:16, orig_r8:16;
+#endif
+               long orig_r8_word;
+       };
 };
 
 /* Callee saved registers - need to be saved only when you are scheduled out */
@@ -87,9 +97,8 @@ struct callee_regs {
        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->event & orig_r8_IS_SCALL)
+#define in_brkpt_trap(regs) (regs->event & orig_r8_IS_BRKPT)
 
 #define current_pt_regs()                                      \
 ({                                                             \
@@ -101,6 +110,13 @@ struct callee_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               0x0004
+#define orig_r8_IS_IRQ1                        0x0010
+#define orig_r8_IS_IRQ2                        0x0020
+
 #endif /* __KERNEL__ */
 
 #ifndef __ASSEMBLY__
index 64b2c2fa7b54a6acea0639d9b6dc1f65beecefa6..d7770cc9aee31777670fa900a7b710fd25f15d41 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));
+       DEFINE(PT_orig_r8, offsetof(struct pt_regs, orig_r8_word));
        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 d625b77c14bd548bc5eb393a2193761f80efb83c..ce8670da83064f27ebcb44b07a972821bcc089ae 100644 (file)
@@ -350,8 +350,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]