Skip to content

Commit

Permalink
ARC: [Review] Preparing to fix incorrect syscall restarts due to signals
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Al Viro <[email protected]>
  • Loading branch information
vineetgarc committed Feb 15, 2013
1 parent c358103 commit 5c39c0a
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 19 deletions.
29 changes: 17 additions & 12 deletions arch/arc/include/asm/entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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
/*
* 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

/*--------------------------------------------------------------
Expand Down Expand Up @@ -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 */
Expand Down
24 changes: 20 additions & 4 deletions arch/arc/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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() \
({ \
Expand All @@ -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__
Expand Down
2 changes: 1 addition & 1 deletion arch/arc/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
4 changes: 2 additions & 2 deletions arch/arc/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down

0 comments on commit 5c39c0a

Please sign in to comment.