~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/kernel/entry_32.S

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0-or-later */
  2 /*
  3  *  PowerPC version
  4  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  5  *  Rewritten by Cort Dougan (cort@fsmlabs.com) for PReP
  6  *    Copyright (C) 1996 Cort Dougan <cort@fsmlabs.com>
  7  *  Adapted for Power Macintosh by Paul Mackerras.
  8  *  Low-level exception handlers and MMU support
  9  *  rewritten by Paul Mackerras.
 10  *    Copyright (C) 1996 Paul Mackerras.
 11  *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
 12  *
 13  *  This file contains the system call entry code, context switch
 14  *  code, and exception/interrupt return code for PowerPC.
 15  */
 16 
 17 #include <linux/errno.h>
 18 #include <linux/err.h>
 19 #include <linux/sys.h>
 20 #include <linux/threads.h>
 21 #include <linux/linkage.h>
 22 
 23 #include <asm/reg.h>
 24 #include <asm/page.h>
 25 #include <asm/mmu.h>
 26 #include <asm/cputable.h>
 27 #include <asm/thread_info.h>
 28 #include <asm/ppc_asm.h>
 29 #include <asm/asm-offsets.h>
 30 #include <asm/unistd.h>
 31 #include <asm/ptrace.h>
 32 #include <asm/feature-fixups.h>
 33 #include <asm/barrier.h>
 34 #include <asm/kup.h>
 35 #include <asm/bug.h>
 36 #include <asm/interrupt.h>
 37 
 38 #include "head_32.h"
 39 
 40 /*
 41  * powerpc relies on return from interrupt/syscall being context synchronising
 42  * (which rfi is) to support ARCH_HAS_MEMBARRIER_SYNC_CORE without additional
 43  * synchronisation instructions.
 44  */
 45 
 46 /*
 47  * Align to 4k in order to ensure that all functions modyfing srr0/srr1
 48  * fit into one page in order to not encounter a TLB miss between the
 49  * modification of srr0/srr1 and the associated rfi.
 50  */
 51         .align  12
 52 
 53 #if defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_PPC_E500)
 54         .globl  prepare_transfer_to_handler
 55 prepare_transfer_to_handler:
 56         /* if from kernel, check interrupted DOZE/NAP mode */
 57         lwz     r12,TI_LOCAL_FLAGS(r2)
 58         mtcrf   0x01,r12
 59         bt-     31-TLF_NAPPING,4f
 60         bt-     31-TLF_SLEEPING,7f
 61         blr
 62 
 63 4:      rlwinm  r12,r12,0,~_TLF_NAPPING
 64         stw     r12,TI_LOCAL_FLAGS(r2)
 65         b       power_save_ppc32_restore
 66 
 67 7:      rlwinm  r12,r12,0,~_TLF_SLEEPING
 68         stw     r12,TI_LOCAL_FLAGS(r2)
 69         lwz     r9,_MSR(r11)            /* if sleeping, clear MSR.EE */
 70         rlwinm  r9,r9,0,~MSR_EE
 71         lwz     r12,_LINK(r11)          /* and return to address in LR */
 72         REST_GPR(2, r11)
 73         b       fast_exception_return
 74 _ASM_NOKPROBE_SYMBOL(prepare_transfer_to_handler)
 75 #endif /* CONFIG_PPC_BOOK3S_32 || CONFIG_PPC_E500 */
 76 
 77 #if defined(CONFIG_PPC_KUEP) && defined(CONFIG_PPC_BOOK3S_32)
 78 SYM_FUNC_START(__kuep_lock)
 79         lwz     r9, THREAD+THSR0(r2)
 80         update_user_segments_by_4 r9, r10, r11, r12
 81         blr
 82 SYM_FUNC_END(__kuep_lock)
 83 
 84 SYM_FUNC_START_LOCAL(__kuep_unlock)
 85         lwz     r9, THREAD+THSR0(r2)
 86         rlwinm  r9,r9,0,~SR_NX
 87         update_user_segments_by_4 r9, r10, r11, r12
 88         blr
 89 SYM_FUNC_END(__kuep_unlock)
 90 
 91 .macro  kuep_lock
 92         bl      __kuep_lock
 93 .endm
 94 .macro  kuep_unlock
 95         bl      __kuep_unlock
 96 .endm
 97 #else
 98 .macro  kuep_lock
 99 .endm
100 .macro  kuep_unlock
101 .endm
102 #endif
103 
104         .globl  transfer_to_syscall
105 transfer_to_syscall:
106         stw     r3, ORIG_GPR3(r1)
107         stw     r11, GPR1(r1)
108         stw     r11, 0(r1)
109         mflr    r12
110         stw     r12, _LINK(r1)
111 #ifdef CONFIG_BOOKE
112         rlwinm  r9,r9,0,14,12           /* clear MSR_WE (necessary?) */
113 #endif
114         lis     r12,STACK_FRAME_REGS_MARKER@ha /* exception frame marker */
115         SAVE_GPR(2, r1)
116         addi    r12,r12,STACK_FRAME_REGS_MARKER@l
117         stw     r9,_MSR(r1)
118         li      r2, INTERRUPT_SYSCALL
119         stw     r12,STACK_INT_FRAME_MARKER(r1)
120         stw     r2,_TRAP(r1)
121         SAVE_GPR(0, r1)
122         SAVE_GPRS(3, 8, r1)
123         addi    r2,r10,-THREAD
124         SAVE_NVGPRS(r1)
125         kuep_lock
126 
127         /* Calling convention has r3 = regs, r4 = orig r0 */
128         addi    r3,r1,STACK_INT_FRAME_REGS
129         mr      r4,r0
130         bl      system_call_exception
131 
132 ret_from_syscall:
133         addi    r4,r1,STACK_INT_FRAME_REGS
134         li      r5,0
135         bl      syscall_exit_prepare
136 #ifdef CONFIG_PPC_47x
137         lis     r4,icache_44x_need_flush@ha
138         lwz     r5,icache_44x_need_flush@l(r4)
139         cmplwi  cr0,r5,0
140         bne-    .L44x_icache_flush
141 #endif /* CONFIG_PPC_47x */
142 .L44x_icache_flush_return:
143         kuep_unlock
144         lwz     r4,_LINK(r1)
145         lwz     r5,_CCR(r1)
146         mtlr    r4
147         lwz     r7,_NIP(r1)
148         lwz     r8,_MSR(r1)
149         cmpwi   r3,0
150         REST_GPR(3, r1)
151 syscall_exit_finish:
152         mtspr   SPRN_SRR0,r7
153         mtspr   SPRN_SRR1,r8
154 
155         bne     3f
156         mtcr    r5
157 
158 1:      REST_GPR(2, r1)
159         REST_GPR(1, r1)
160         rfi
161 
162 3:      mtcr    r5
163         lwz     r4,_CTR(r1)
164         lwz     r5,_XER(r1)
165         REST_NVGPRS(r1)
166         mtctr   r4
167         mtxer   r5
168         REST_GPR(0, r1)
169         REST_GPRS(3, 12, r1)
170         b       1b
171 
172 #ifdef CONFIG_44x
173 .L44x_icache_flush:
174         li      r7,0
175         iccci   r0,r0
176         stw     r7,icache_44x_need_flush@l(r4)
177         b       .L44x_icache_flush_return
178 #endif  /* CONFIG_44x */
179 
180         .globl  ret_from_fork
181 ret_from_fork:
182         REST_NVGPRS(r1)
183         bl      schedule_tail
184         li      r3,0    /* fork() return value */
185         b       ret_from_syscall
186 
187         .globl  ret_from_kernel_user_thread
188 ret_from_kernel_user_thread:
189         bl      schedule_tail
190         mtctr   r14
191         mr      r3,r15
192         PPC440EP_ERR42
193         bctrl
194         li      r3,0
195         b       ret_from_syscall
196 
197         .globl  start_kernel_thread
198 start_kernel_thread:
199         bl      schedule_tail
200         mtctr   r14
201         mr      r3,r15
202         PPC440EP_ERR42
203         bctrl
204         /*
205          * This must not return. We actually want to BUG here, not WARN,
206          * because BUG will exit the process which is what the kernel thread
207          * should have done, which may give some hope of continuing.
208          */
209 100:    trap
210         EMIT_BUG_ENTRY 100b,__FILE__,__LINE__,0
211 
212         .globl  fast_exception_return
213 fast_exception_return:
214 #ifndef CONFIG_BOOKE
215         andi.   r10,r9,MSR_RI           /* check for recoverable interrupt */
216         beq     3f                      /* if not, we've got problems */
217 #endif
218 
219 2:      lwz     r10,_CCR(r11)
220         REST_GPRS(1, 6, r11)
221         mtcr    r10
222         lwz     r10,_LINK(r11)
223         mtlr    r10
224         /* Clear the exception marker on the stack to avoid confusing stacktrace */
225         li      r10, 0
226         stw     r10, 8(r11)
227         REST_GPR(10, r11)
228 #if defined(CONFIG_PPC_8xx) && defined(CONFIG_PERF_EVENTS)
229         mtspr   SPRN_NRI, r0
230 #endif
231         mtspr   SPRN_SRR1,r9
232         mtspr   SPRN_SRR0,r12
233         REST_GPR(9, r11)
234         REST_GPR(12, r11)
235         REST_GPR(11, r11)
236         rfi
237 _ASM_NOKPROBE_SYMBOL(fast_exception_return)
238 
239 /* aargh, a nonrecoverable interrupt, panic */
240 /* aargh, we don't know which trap this is */
241 3:
242         li      r10,-1
243         stw     r10,_TRAP(r11)
244         prepare_transfer_to_handler
245         bl      unrecoverable_exception
246         trap    /* should not get here */
247 
248         .globl interrupt_return
249 interrupt_return:
250         lwz     r4,_MSR(r1)
251         addi    r3,r1,STACK_INT_FRAME_REGS
252         andi.   r0,r4,MSR_PR
253         beq     .Lkernel_interrupt_return
254         bl      interrupt_exit_user_prepare
255         cmpwi   r3,0
256         kuep_unlock
257         bne-    .Lrestore_nvgprs
258 
259 .Lfast_user_interrupt_return:
260         lwz     r11,_NIP(r1)
261         lwz     r12,_MSR(r1)
262         mtspr   SPRN_SRR0,r11
263         mtspr   SPRN_SRR1,r12
264 
265 BEGIN_FTR_SECTION
266         stwcx.  r0,0,r1         /* to clear the reservation */
267 FTR_SECTION_ELSE
268         lwarx   r0,0,r1
269 ALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
270 
271         lwz     r3,_CCR(r1)
272         lwz     r4,_LINK(r1)
273         lwz     r5,_CTR(r1)
274         lwz     r6,_XER(r1)
275         li      r0,0
276 
277         /*
278          * Leaving a stale exception marker on the stack can confuse
279          * the reliable stack unwinder later on. Clear it.
280          */
281         stw     r0,8(r1)
282         REST_GPRS(7, 12, r1)
283 
284         mtcr    r3
285         mtlr    r4
286         mtctr   r5
287         mtspr   SPRN_XER,r6
288 
289         REST_GPRS(2, 6, r1)
290         REST_GPR(0, r1)
291         REST_GPR(1, r1)
292         rfi
293 
294 .Lrestore_nvgprs:
295         REST_NVGPRS(r1)
296         b       .Lfast_user_interrupt_return
297 
298 .Lkernel_interrupt_return:
299         bl      interrupt_exit_kernel_prepare
300 
301 .Lfast_kernel_interrupt_return:
302         cmpwi   cr1,r3,0
303         lwz     r11,_NIP(r1)
304         lwz     r12,_MSR(r1)
305         mtspr   SPRN_SRR0,r11
306         mtspr   SPRN_SRR1,r12
307 
308 BEGIN_FTR_SECTION
309         stwcx.  r0,0,r1         /* to clear the reservation */
310 FTR_SECTION_ELSE
311         lwarx   r0,0,r1
312 ALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
313 
314         lwz     r3,_LINK(r1)
315         lwz     r4,_CTR(r1)
316         lwz     r5,_XER(r1)
317         lwz     r6,_CCR(r1)
318         li      r0,0
319 
320         REST_GPRS(7, 12, r1)
321 
322         mtlr    r3
323         mtctr   r4
324         mtspr   SPRN_XER,r5
325 
326         /*
327          * Leaving a stale exception marker on the stack can confuse
328          * the reliable stack unwinder later on. Clear it.
329          */
330         stw     r0,8(r1)
331 
332         REST_GPRS(2, 5, r1)
333 
334         bne-    cr1,1f /* emulate stack store */
335         mtcr    r6
336         REST_GPR(6, r1)
337         REST_GPR(0, r1)
338         REST_GPR(1, r1)
339         rfi
340 
341 1:      /*
342          * Emulate stack store with update. New r1 value was already calculated
343          * and updated in our interrupt regs by emulate_loadstore, but we can't
344          * store the previous value of r1 to the stack before re-loading our
345          * registers from it, otherwise they could be clobbered.  Use
346          * SPRG Scratch0 as temporary storage to hold the store
347          * data, as interrupts are disabled here so it won't be clobbered.
348          */
349         mtcr    r6
350 #ifdef CONFIG_BOOKE
351         mtspr   SPRN_SPRG_WSCRATCH0, r9
352 #else
353         mtspr   SPRN_SPRG_SCRATCH0, r9
354 #endif
355         addi    r9,r1,INT_FRAME_SIZE /* get original r1 */
356         REST_GPR(6, r1)
357         REST_GPR(0, r1)
358         REST_GPR(1, r1)
359         stw     r9,0(r1) /* perform store component of stwu */
360 #ifdef CONFIG_BOOKE
361         mfspr   r9, SPRN_SPRG_RSCRATCH0
362 #else
363         mfspr   r9, SPRN_SPRG_SCRATCH0
364 #endif
365         rfi
366 _ASM_NOKPROBE_SYMBOL(interrupt_return)
367 
368 #ifdef CONFIG_BOOKE
369 
370 /*
371  * Returning from a critical interrupt in user mode doesn't need
372  * to be any different from a normal exception.  For a critical
373  * interrupt in the kernel, we just return (without checking for
374  * preemption) since the interrupt may have happened at some crucial
375  * place (e.g. inside the TLB miss handler), and because we will be
376  * running with r1 pointing into critical_stack, not the current
377  * process's kernel stack (and therefore current_thread_info() will
378  * give the wrong answer).
379  * We have to restore various SPRs that may have been in use at the
380  * time of the critical interrupt.
381  *
382  */
383 
384 #define RET_FROM_EXC_LEVEL(exc_lvl_srr0, exc_lvl_srr1, exc_lvl_rfi)     \
385         REST_NVGPRS(r1);                                                \
386         lwz     r3,_MSR(r1);                                            \
387         andi.   r3,r3,MSR_PR;                                           \
388         bne     interrupt_return;                                       \
389         REST_GPR(0, r1);                                                \
390         REST_GPRS(2, 8, r1);                                            \
391         lwz     r10,_XER(r1);                                           \
392         lwz     r11,_CTR(r1);                                           \
393         mtspr   SPRN_XER,r10;                                           \
394         mtctr   r11;                                                    \
395         stwcx.  r0,0,r1;                /* to clear the reservation */  \
396         lwz     r11,_LINK(r1);                                          \
397         mtlr    r11;                                                    \
398         lwz     r10,_CCR(r1);                                           \
399         mtcrf   0xff,r10;                                               \
400         lwz     r9,_DEAR(r1);                                           \
401         lwz     r10,_ESR(r1);                                           \
402         mtspr   SPRN_DEAR,r9;                                           \
403         mtspr   SPRN_ESR,r10;                                           \
404         lwz     r11,_NIP(r1);                                           \
405         lwz     r12,_MSR(r1);                                           \
406         mtspr   exc_lvl_srr0,r11;                                       \
407         mtspr   exc_lvl_srr1,r12;                                       \
408         REST_GPRS(9, 12, r1);                                           \
409         REST_GPR(1, r1);                                                \
410         exc_lvl_rfi;                                                    \
411         b       .;              /* prevent prefetch past exc_lvl_rfi */
412 
413 #define RESTORE_xSRR(exc_lvl_srr0, exc_lvl_srr1)                        \
414         lwz     r9,_##exc_lvl_srr0(r1);                                 \
415         lwz     r10,_##exc_lvl_srr1(r1);                                \
416         mtspr   SPRN_##exc_lvl_srr0,r9;                                 \
417         mtspr   SPRN_##exc_lvl_srr1,r10;
418 
419 #if defined(CONFIG_PPC_E500)
420 #ifdef CONFIG_PHYS_64BIT
421 #define RESTORE_MAS7                                                    \
422         lwz     r11,MAS7(r1);                                           \
423         mtspr   SPRN_MAS7,r11;
424 #else
425 #define RESTORE_MAS7
426 #endif /* CONFIG_PHYS_64BIT */
427 #define RESTORE_MMU_REGS                                                \
428         lwz     r9,MAS0(r1);                                            \
429         lwz     r10,MAS1(r1);                                           \
430         lwz     r11,MAS2(r1);                                           \
431         mtspr   SPRN_MAS0,r9;                                           \
432         lwz     r9,MAS3(r1);                                            \
433         mtspr   SPRN_MAS1,r10;                                          \
434         lwz     r10,MAS6(r1);                                           \
435         mtspr   SPRN_MAS2,r11;                                          \
436         mtspr   SPRN_MAS3,r9;                                           \
437         mtspr   SPRN_MAS6,r10;                                          \
438         RESTORE_MAS7;
439 #elif defined(CONFIG_44x)
440 #define RESTORE_MMU_REGS                                                \
441         lwz     r9,MMUCR(r1);                                           \
442         mtspr   SPRN_MMUCR,r9;
443 #else
444 #define RESTORE_MMU_REGS
445 #endif
446 
447         .globl  ret_from_crit_exc
448 ret_from_crit_exc:
449         RESTORE_xSRR(SRR0,SRR1);
450         RESTORE_MMU_REGS;
451         RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, PPC_RFCI)
452 _ASM_NOKPROBE_SYMBOL(ret_from_crit_exc)
453 
454         .globl  ret_from_debug_exc
455 ret_from_debug_exc:
456         RESTORE_xSRR(SRR0,SRR1);
457         RESTORE_xSRR(CSRR0,CSRR1);
458         RESTORE_MMU_REGS;
459         RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, PPC_RFDI)
460 _ASM_NOKPROBE_SYMBOL(ret_from_debug_exc)
461 
462         .globl  ret_from_mcheck_exc
463 ret_from_mcheck_exc:
464         RESTORE_xSRR(SRR0,SRR1);
465         RESTORE_xSRR(CSRR0,CSRR1);
466         RESTORE_xSRR(DSRR0,DSRR1);
467         RESTORE_MMU_REGS;
468         RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, PPC_RFMCI)
469 _ASM_NOKPROBE_SYMBOL(ret_from_mcheck_exc)
470 #endif /* CONFIG_BOOKE */

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php