summaryrefslogtreecommitdiff
path: root/arch/arc/kernel
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2013-05-28 12:20:41 +0400
committerVineet Gupta <vgupta@synopsys.com>2013-06-22 17:53:25 +0400
commit359105bdb06f8421fd8e69ae47fd052e398b6778 (patch)
tree025dfe3a68cb9afa0a6e877ad264bbb8cf957783 /arch/arc/kernel
parentba3558c772ce1ac64d07f46b8c763349a0e51ba3 (diff)
downloadlinux-359105bdb06f8421fd8e69ae47fd052e398b6778.tar.xz
ARC: pt_regs update #4: r25 saved/restored unconditionally
(This is a VERY IMP change for low level interrupt/exception handling) ----------------------------------------------------------------------- WHAT ----------------------------------------------------------------------- * User 25 now saved in pt_regs->user_r25 (vs. tsk->thread_info.user_r25) * This allows Low level interrupt code to unconditionally save r25 (vs. the prev version which would only do it for U->K transition). Ofcourse for nested interrupts, only the pt_regs->user_r25 of bottom-most frame is useful. * simplifies the interrupt prologue/epilogue * Needed for ARCv2 ISA code and done here to keep design similar with ARCompact event handling ----------------------------------------------------------------------- WHY ------------------------------------------------------------------------- With CONFIG_ARC_CURR_IN_REG, r25 is used to cache "current" task pointer in kernel mode. So when entering kernel mode from User Mode - user r25 is specially safe-kept (it being a callee reg is NOT part of pt_regs which are saved by default on each interrupt/trap/exception) - r25 loaded with current task pointer. Further, if interrupt was taken in kernel mode, this is skipped since we know that r25 already has valid "current" pointer. With 2 level of interrupts in ARCompact ISA, detecting this is difficult but still possible, since we could be in kernel mode but r25 not already saved (in fact the stack itself might not have been switched). A. User mode B. L1 IRQ taken C. L2 IRQ taken (while on 1st line of L1 ISR) So in #C, although in kernel mode, r25 not saved (infact SP not switched at all) Given that ARcompact has manual stack switching, we could use a bit of trickey - The low level code would make sure that SP is only set to kernel mode value at the very end (after saving r25). So a non kernel mode SP, even if in kernel mode, meant r25 was NOT saved. The same paradigm won't work in ARCv2 ISA since SP is auto-switched so it's setting can't be delayed/constrained. Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc/kernel')
-rw-r--r--arch/arc/kernel/asm-offsets.c4
-rw-r--r--arch/arc/kernel/entry.S11
-rw-r--r--arch/arc/kernel/process.c1
3 files changed, 2 insertions, 14 deletions
diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c
index fdcd76532b70..75f05b83d77d 100644
--- a/arch/arc/kernel/asm-offsets.c
+++ b/arch/arc/kernel/asm-offsets.c
@@ -24,9 +24,6 @@ int main(void)
DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
DEFINE(THREAD_CALLEE_REG, offsetof(struct thread_struct, callee_reg));
-#ifdef CONFIG_ARC_CURR_IN_REG
- DEFINE(THREAD_USER_R25, offsetof(struct thread_struct, user_r25));
-#endif
DEFINE(THREAD_FAULT_ADDR,
offsetof(struct thread_struct, fault_address));
@@ -61,5 +58,6 @@ int main(void)
DEFINE(PT_r7, offsetof(struct pt_regs, r7));
DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs));
+ DEFINE(SZ_PT_REGS, sizeof(struct pt_regs));
return 0;
}
diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S
index 919e2f065d2f..fd5f9160bbd2 100644
--- a/arch/arc/kernel/entry.S
+++ b/arch/arc/kernel/entry.S
@@ -680,17 +680,6 @@ restore_regs :
; XXX can this be optimised out
IRQ_DISABLE_SAVE r9, r10 ;@r10 has prisitine (pre-disable) copy
-#ifdef CONFIG_ARC_CURR_IN_REG
- ; Restore User R25
- ; Earlier this used to be only for returning to user mode
- ; However with 2 levels of IRQ this can also happen even if
- ; in kernel mode
- ld r9, [sp, PT_sp]
- brhs r9, VMALLOC_START, 8f
- RESTORE_USER_R25
-8:
-#endif
-
; Restore REG File. In case multiple Events outstanding,
; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None
; Note that we use realtime STATUS32 (not pt_regs->status32) to
diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c
index c6e22e060578..a3cc6a577039 100644
--- a/arch/arc/kernel/process.c
+++ b/arch/arc/kernel/process.c
@@ -77,6 +77,7 @@ asmlinkage void ret_from_fork(void);
* | SP |
* | orig_r0 |
* | orig_r8 |
+ * | user_r25 |
* ------------------ <===== END of PAGE
*/
int copy_thread(unsigned long clone_flags,