Skip to content

Commit 359105b

Browse files
committed
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 <[email protected]>
1 parent ba3558c commit 359105b

File tree

6 files changed

+24
-40
lines changed

6 files changed

+24
-40
lines changed

arch/arc/include/asm/entry.h

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@
102102
POP r2
103103
POP r1
104104
POP r0
105+
106+
#ifdef CONFIG_ARC_CURR_IN_REG
107+
ld r25, [sp, 12]
108+
#endif
105109
.endm
106110

107111
/*--------------------------------------------------------------
@@ -138,6 +142,7 @@
138142
POP r13
139143
.endm
140144

145+
#define OFF_USER_R25_FROM_R24 (SZ_CALLEE_REGS + SZ_PT_REGS - 8)/4
141146

142147
/*--------------------------------------------------------------
143148
* Collect User Mode callee regs as struct callee_regs - needed by
@@ -155,7 +160,7 @@
155160

156161
#ifdef CONFIG_ARC_CURR_IN_REG
157162
; Retrieve orig r25 and save it on stack
158-
ld r12, [r25, TASK_THREAD + THREAD_USER_R25]
163+
ld.as r12, [sp, OFF_USER_R25_FROM_R24]
159164
st.a r12, [sp, -4]
160165
#else
161166
PUSH r25
@@ -204,7 +209,7 @@
204209

205210
#ifdef CONFIG_ARC_CURR_IN_REG
206211
ld.ab r12, [sp, 4]
207-
st r12, [r25, TASK_THREAD + THREAD_USER_R25]
212+
st.as r12, [sp, OFF_USER_R25_FROM_R24]
208213
#else
209214
POP r25
210215
#endif
@@ -218,13 +223,6 @@
218223
add sp, sp, SZ_CALLEE_REGS
219224
.endm
220225

221-
/*--------------------------------------------------------------
222-
* Restore User mode r25 saved in task_struct->thread.user_r25
223-
*-------------------------------------------------------------*/
224-
.macro RESTORE_USER_R25
225-
ld r25, [r25, TASK_THREAD + THREAD_USER_R25]
226-
.endm
227-
228226
/*-------------------------------------------------------------
229227
* given a tsk struct, get to the base of it's kernel mode stack
230228
* tsk->thread_info is really a PAGE, whose bottom hoists stack
@@ -297,22 +295,21 @@
297295

298296
GET_CURR_TASK_ON_CPU r9
299297

300-
#ifdef CONFIG_ARC_CURR_IN_REG
301-
302-
/* If current task pointer cached in r25, time to
303-
* -safekeep USER r25 in task->thread_struct->user_r25
304-
* -load r25 with current task ptr
305-
*/
306-
st.as r25, [r9, (TASK_THREAD + THREAD_USER_R25)/4]
307-
mov r25, r9
308-
#endif
309-
310298
/* With current tsk in r9, get it's kernel mode stack base */
311299
GET_TSK_STACK_BASE r9, r9
312300

313301
66:
302+
#ifdef CONFIG_ARC_CURR_IN_REG
303+
/*
304+
* Treat r25 as scratch reg, save it on stack first
305+
* Load it with current task pointer
306+
*/
307+
st r25, [r9, -4]
308+
GET_CURR_TASK_ON_CPU r25
309+
#endif
310+
314311
/* Save Pre Intr/Exception User SP on kernel stack */
315-
st.a sp, [r9, -12] ; Make room for orig_r0 and orig_r8
312+
st.a sp, [r9, -16] ; Make room for orig_r0, orig_r8, user_r25
316313

317314
/* CAUTION:
318315
* SP should be set at the very end when we are done with everything
@@ -466,7 +463,7 @@
466463
RESTORE_R12_TO_R0
467464

468465
ld sp, [sp] /* restore original sp */
469-
/* orig_r0 and orig_r8 skipped automatically */
466+
/* orig_r0, orig_r8, user_r25 skipped automatically */
470467
.endm
471468

472469

@@ -549,7 +546,7 @@
549546
RESTORE_R12_TO_R0
550547

551548
ld sp, [sp] /* restore original sp */
552-
/* orig_r0 and orig_r8 skipped automatically */
549+
/* orig_r0, orig_r8, user_r25 skipped automatically */
553550
.endm
554551

555552
.macro RESTORE_ALL_INT2
@@ -568,7 +565,7 @@
568565
RESTORE_R12_TO_R0
569566

570567
ld sp, [sp] /* restore original sp */
571-
/* orig_r0 and orig_r8 skipped automatically */
568+
/* orig_r0, orig_r8, user_r25 skipped automatically */
572569
.endm
573570

574571

arch/arc/include/asm/processor.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ struct thread_struct {
3030
unsigned long callee_reg; /* pointer to callee regs */
3131
unsigned long fault_address; /* dbls as brkpt holder as well */
3232
unsigned long cause_code; /* Exception Cause Code (ECR) */
33-
#ifdef CONFIG_ARC_CURR_IN_REG
34-
unsigned long user_r25;
35-
#endif
3633
#ifdef CONFIG_ARC_FPU_SAVE_RESTORE
3734
struct arc_fpu fpu;
3835
#endif

arch/arc/include/asm/ptrace.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ struct pt_regs {
5454
#endif
5555
long orig_r8_word;
5656
};
57+
58+
long user_r25;
5759
};
5860

5961
/* Callee saved registers - need to be saved only when you are scheduled out */

arch/arc/kernel/asm-offsets.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ int main(void)
2424

2525
DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
2626
DEFINE(THREAD_CALLEE_REG, offsetof(struct thread_struct, callee_reg));
27-
#ifdef CONFIG_ARC_CURR_IN_REG
28-
DEFINE(THREAD_USER_R25, offsetof(struct thread_struct, user_r25));
29-
#endif
3027
DEFINE(THREAD_FAULT_ADDR,
3128
offsetof(struct thread_struct, fault_address));
3229

@@ -61,5 +58,6 @@ int main(void)
6158
DEFINE(PT_r7, offsetof(struct pt_regs, r7));
6259

6360
DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs));
61+
DEFINE(SZ_PT_REGS, sizeof(struct pt_regs));
6462
return 0;
6563
}

arch/arc/kernel/entry.S

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -680,17 +680,6 @@ restore_regs :
680680
; XXX can this be optimised out
681681
IRQ_DISABLE_SAVE r9, r10 ;@r10 has prisitine (pre-disable) copy
682682

683-
#ifdef CONFIG_ARC_CURR_IN_REG
684-
; Restore User R25
685-
; Earlier this used to be only for returning to user mode
686-
; However with 2 levels of IRQ this can also happen even if
687-
; in kernel mode
688-
ld r9, [sp, PT_sp]
689-
brhs r9, VMALLOC_START, 8f
690-
RESTORE_USER_R25
691-
8:
692-
#endif
693-
694683
; Restore REG File. In case multiple Events outstanding,
695684
; use the same priorty as rtie: EXCPN, L2 IRQ, L1 IRQ, None
696685
; Note that we use realtime STATUS32 (not pt_regs->status32) to

arch/arc/kernel/process.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ asmlinkage void ret_from_fork(void);
7777
* | SP |
7878
* | orig_r0 |
7979
* | orig_r8 |
80+
* | user_r25 |
8081
* ------------------ <===== END of PAGE
8182
*/
8283
int copy_thread(unsigned long clone_flags,

0 commit comments

Comments
 (0)