Blame view

kernel/linux-rt-4.4.41/arch/arc/include/asm/entry-arcv2.h 4 KB
5113f6f70   김현기   kernel add
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
  
  #ifndef __ASM_ARC_ENTRY_ARCV2_H
  #define __ASM_ARC_ENTRY_ARCV2_H
  
  #include <asm/asm-offsets.h>
  #include <asm/irqflags-arcv2.h>
  #include <asm/thread_info.h>	/* For THREAD_SIZE */
  
  /*------------------------------------------------------------------------*/
  .macro INTERRUPT_PROLOGUE	called_from
  
  	; Before jumping to Interrupt Vector, hardware micro-ops did following:
  	;   1. SP auto-switched to kernel mode stack
  	;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1, K:0)
  	;   3. Auto saved: r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI, PC, STAT32
  	;
  	; Now manually save: r12, sp, fp, gp, r25
  
  	PUSH	r12
  
  	; Saving pt_regs->sp correctly requires some extra work due to the way
  	; Auto stack switch works
  	;  - U mode: retrieve it from AUX_USER_SP
  	;  - K mode: add the offset from current SP where H/w starts auto push
  	;
  	; Utilize the fact that Z bit is set if Intr taken in U mode
  	mov.nz	r9, sp
  	add.nz	r9, r9, SZ_PT_REGS - PT_sp - 4
  	bnz	1f
  
  	lr	r9, [AUX_USER_SP]
  1:
  	PUSH	r9	; SP
  
  	PUSH	fp
  	PUSH	gp
  
  #ifdef CONFIG_ARC_CURR_IN_REG
  	PUSH	r25			; user_r25
  	GET_CURR_TASK_ON_CPU	r25
  #else
  	sub	sp, sp, 4
  #endif
  
  .ifnc \called_from, exception
  	sub	sp, sp, 12	; BTA/ECR/orig_r0 placeholder per pt_regs
  .endif
  
  .endm
  
  /*------------------------------------------------------------------------*/
  .macro INTERRUPT_EPILOGUE	called_from
  
  .ifnc \called_from, exception
  	add	sp, sp, 12	; skip BTA/ECR/orig_r0 placeholderss
  .endif
  
  #ifdef CONFIG_ARC_CURR_IN_REG
  	POP	r25
  #else
  	add	sp, sp, 4
  #endif
  
  	POP	gp
  	POP	fp
  
  	; Don't touch AUX_USER_SP if returning to K mode (Z bit set)
  	; (Z bit set on K mode is inverse of INTERRUPT_PROLOGUE)
  	add.z	sp, sp, 4
  	bz	1f
  
  	POPAX	AUX_USER_SP
  1:
  	POP	r12
  
  .endm
  
  /*------------------------------------------------------------------------*/
  .macro EXCEPTION_PROLOGUE
  
  	; Before jumping to Exception Vector, hardware micro-ops did following:
  	;   1. SP auto-switched to kernel mode stack
  	;   2. STATUS32.Z flag set to U mode at time of interrupt (U:1,K:0)
  	;
  	; Now manually save the complete reg file
  
  	PUSH	r9		; freeup a register: slot of erstatus
  
  	PUSHAX	eret
  	sub	sp, sp, 12	; skip JLI, LDI, EI
  	PUSH	lp_count
  	PUSHAX	lp_start
  	PUSHAX	lp_end
  	PUSH	blink
  
  	PUSH	r11
  	PUSH	r10
  
  	ld.as	r9,  [sp, 10]	; load stashed r9 (status32 stack slot)
  	lr	r10, [erstatus]
  	st.as	r10, [sp, 10]	; save status32 at it's right stack slot
  
  	PUSH	r9
  	PUSH	r8
  	PUSH	r7
  	PUSH	r6
  	PUSH	r5
  	PUSH	r4
  	PUSH	r3
  	PUSH	r2
  	PUSH	r1
  	PUSH	r0
  
  	; -- for interrupts, regs above are auto-saved by h/w in that order --
  	; Now do what ISR prologue does (manually save r12, sp, fp, gp, r25)
  	;
  	; Set Z flag if this was from U mode (expected by INTERRUPT_PROLOGUE)
  	; Although H/w exception micro-ops do set Z flag for U mode (just like
  	; for interrupts), it could get clobbered in case we soft land here from
  	; a TLB Miss exception handler (tlbex.S)
  
  	and	r10, r10, STATUS_U_MASK
  	xor.f	0, r10, STATUS_U_MASK
  
  	INTERRUPT_PROLOGUE  exception
  
  	PUSHAX	erbta
  	PUSHAX	ecr		; r9 contains ECR, expected by EV_Trap
  
  	PUSH	r0		; orig_r0
  .endm
  
  /*------------------------------------------------------------------------*/
  .macro EXCEPTION_EPILOGUE
  
  	; Assumes r0 has PT_status32
  	btst   r0, STATUS_U_BIT	; Z flag set if K, used in INTERRUPT_EPILOGUE
  
  	add	sp, sp, 8	; orig_r0/ECR don't need restoring
  	POPAX	erbta
  
  	INTERRUPT_EPILOGUE  exception
  
  	POP	r0
  	POP	r1
  	POP	r2
  	POP	r3
  	POP	r4
  	POP	r5
  	POP	r6
  	POP	r7
  	POP	r8
  	POP	r9
  	POP	r10
  	POP	r11
  
  	POP	blink
  	POPAX	lp_end
  	POPAX	lp_start
  
  	POP	r9
  	mov	lp_count, r9
  
  	add	sp, sp, 12	; skip JLI, LDI, EI
  	POPAX	eret
  	POPAX	erstatus
  
  	ld.as	r9, [sp, -12]	; reload r9 which got clobbered
  .endm
  
  .macro FAKE_RET_FROM_EXCPN
  	lr      r9, [status32]
  	bic     r9, r9, (STATUS_U_MASK|STATUS_DE_MASK|STATUS_AE_MASK)
  	or      r9, r9, (STATUS_L_MASK|STATUS_IE_MASK)
  	kflag   r9
  .endm
  
  /* Get thread_info of "current" tsk */
  .macro GET_CURR_THR_INFO_FROM_SP  reg
  	bmskn \reg, sp, THREAD_SHIFT - 1
  .endm
  
  /* Get CPU-ID of this core */
  .macro  GET_CPU_ID  reg
  	lr  \reg, [identity]
  	xbfu \reg, \reg, 0xE8	/* 00111    01000 */
  				/* M = 8-1  N = 8 */
  .endm
  
  #endif