Skip to content

Commit b060b7d

Browse files
committed
ARC: __switch_to: asm with dwarf ops (vs. inline asm)
__switch_to() is final step of context switch, swapping kernel modes stack (and callee regs) of outgoing task with next task. It is also the starting point of stack unwinging of a sleeping task and captures SP, FP, BLINK and the corresponding dwarf info. Back when dinosaurs still roamed around, ARC gas didn't support CFI pseudo ops and gcc was responsible for generating dwarf info. Thus it had to be written in "C" with inline asm to do the hand crafting of stack. The function prologue (and crucial saving of blink etc) was still gcc generated but not visible in code. Likewise dwarf info was missing. Now with modern tools, we can make things more obvious by writing the code in asm and adding approproate dwarf cfi pseudo ops. This is mostly non functional change, except for slight chnages to asm - ARCompact doesn't support MOV_S fp, sp, so we use MOV Signed-off-by: Vineet Gupta <[email protected]>
1 parent d1d1569 commit b060b7d

File tree

4 files changed

+61
-155
lines changed

4 files changed

+61
-155
lines changed

arch/arc/include/asm/dwarf.h

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,31 @@
1010

1111
#ifdef ARC_DW2_UNWIND_AS_CFI
1212

13-
#define CFI_STARTPROC .cfi_startproc
14-
#define CFI_ENDPROC .cfi_endproc
15-
#define CFI_DEF_CFA .cfi_def_cfa
16-
#define CFI_REGISTER .cfi_register
17-
#define CFI_REL_OFFSET .cfi_rel_offset
18-
#define CFI_UNDEFINED .cfi_undefined
13+
#define CFI_STARTPROC .cfi_startproc
14+
#define CFI_ENDPROC .cfi_endproc
15+
#define CFI_DEF_CFA .cfi_def_cfa
16+
#define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset
17+
#define CFI_DEF_CFA_REGISTER .cfi_def_cfa_register
18+
#define CFI_OFFSET .cfi_offset
19+
#define CFI_REL_OFFSET .cfi_rel_offset
20+
#define CFI_REGISTER .cfi_register
21+
#define CFI_RESTORE .cfi_restore
22+
#define CFI_UNDEFINED .cfi_undefined
1923

2024
#else
2125

2226
#define CFI_IGNORE #
2327

24-
#define CFI_STARTPROC CFI_IGNORE
25-
#define CFI_ENDPROC CFI_IGNORE
26-
#define CFI_DEF_CFA CFI_IGNORE
27-
#define CFI_REGISTER CFI_IGNORE
28-
#define CFI_REL_OFFSET CFI_IGNORE
29-
#define CFI_UNDEFINED CFI_IGNORE
28+
#define CFI_STARTPROC CFI_IGNORE
29+
#define CFI_ENDPROC CFI_IGNORE
30+
#define CFI_DEF_CFA CFI_IGNORE
31+
#define CFI_DEF_CFA_OFFSET CFI_IGNORE
32+
#define CFI_DEF_CFA_REGISTER CFI_IGNORE
33+
#define CFI_OFFSET CFI_IGNORE
34+
#define CFI_REL_OFFSET CFI_IGNORE
35+
#define CFI_REGISTER CFI_IGNORE
36+
#define CFI_RESTORE CFI_IGNORE
37+
#define CFI_UNDEFINED CFI_IGNORE
3038

3139
#endif /* !ARC_DW2_UNWIND_AS_CFI */
3240

arch/arc/kernel/Makefile

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
obj-y := head.o arcksyms.o setup.o irq.o reset.o ptrace.o process.o devtree.o
77
obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o
8+
obj-y += ctx_sw_asm.o
9+
810
obj-$(CONFIG_ISA_ARCOMPACT) += entry-compact.o intc-compact.o
911
obj-$(CONFIG_ISA_ARCV2) += entry-arcv2.o intc-arcv2.o
1012

@@ -24,11 +26,4 @@ ifdef CONFIG_ISA_ARCOMPACT
2426
CFLAGS_fpu.o += -mdpfp
2527
endif
2628

27-
ifdef CONFIG_ARC_DW2_UNWIND
28-
CFLAGS_ctx_sw.o += -fno-omit-frame-pointer
29-
obj-y += ctx_sw.o
30-
else
31-
obj-y += ctx_sw_asm.o
32-
endif
33-
3429
extra-y := vmlinux.lds

arch/arc/kernel/ctx_sw.c

Lines changed: 0 additions & 103 deletions
This file was deleted.

arch/arc/kernel/ctx_sw_asm.S

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -13,48 +13,54 @@
1313

1414
#define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4)
1515

16-
;################### Low Level Context Switch ##########################
16+
; IN
17+
; - r0: prev task (also current)
18+
; - r1: next task
19+
; OUT
20+
; - r0: prev task (so r0 not touched)
1721

1822
.section .sched.text,"ax",@progbits
19-
.align 4
20-
.global __switch_to
21-
.type __switch_to, @function
22-
__switch_to:
23-
CFI_STARTPROC
24-
25-
/* Save regs on kernel mode stack of task */
26-
st.a blink, [sp, -4]
27-
st.a fp, [sp, -4]
23+
ENTRY_CFI(__switch_to)
24+
25+
/* save kernel stack frame regs of @prev task */
26+
push blink
27+
CFI_DEF_CFA_OFFSET 4
28+
CFI_OFFSET r31, -4
29+
30+
push fp
31+
CFI_DEF_CFA_OFFSET 8
32+
CFI_OFFSET r27, -8
33+
34+
mov fp, sp
35+
CFI_DEF_CFA_REGISTER r27
36+
37+
/* kernel mode callee regs of @prev */
2838
SAVE_CALLEE_SAVED_KERNEL
2939

30-
/* Save the now KSP in task->thread.ksp */
40+
/* save final SP to @prev->thread.ksp */
3141
#if KSP_WORD_OFF <= 255
3242
st.as sp, [r0, KSP_WORD_OFF]
3343
#else
3444
/* Workaround for NR_CPUS=4k as ST.as can only take s9 offset */
35-
add2 r24, r0, KSP_WORD_OFF
36-
st sp, [r24]
45+
add2 r10, r0, KSP_WORD_OFF
46+
st sp, [r10]
3747
#endif
38-
/*
39-
* Return last task in r0 (return reg)
40-
* On ARC, Return reg = First Arg reg = r0.
41-
* Since we already have last task in r0,
42-
* don't need to do anything special to return it
43-
*/
44-
45-
/*
46-
* switch to new task, contained in r1
47-
* Temp reg r3 is required to get the ptr to store val
48-
*/
49-
SET_CURR_TASK_ON_CPU r1, r3
50-
51-
/* reload SP with kernel mode stack pointer in task->thread.ksp */
52-
ld.as sp, [r1, KSP_WORD_OFF]
53-
54-
/* restore the registers */
48+
/* update @next in _current_task[] and GP register caching it */
49+
SET_CURR_TASK_ON_CPU r1, r10
50+
51+
/* load SP from @next->thread.ksp */
52+
ld.as sp, [r1, KSP_WORD_OFF]
53+
54+
/* restore callee regs, stack frame regs of @next */
5555
RESTORE_CALLEE_SAVED_KERNEL
56-
ld.ab fp, [sp, 4]
57-
ld.ab blink, [sp, 4]
58-
j [blink]
5956

57+
pop fp
58+
CFI_RESTORE r27
59+
CFI_DEF_CFA r28, 4
60+
61+
pop blink
62+
CFI_RESTORE r31
63+
CFI_DEF_CFA_OFFSET 0
64+
65+
j [blink]
6066
END_CFI(__switch_to)

0 commit comments

Comments
 (0)