OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [powerpc/] [kernel/] [entry_32.S] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 *  PowerPC version
3
 *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
4
 *  Rewritten by Cort Dougan (cort@fsmlabs.com) for PReP
5
 *    Copyright (C) 1996 Cort Dougan 
6
 *  Adapted for Power Macintosh by Paul Mackerras.
7
 *  Low-level exception handlers and MMU support
8
 *  rewritten by Paul Mackerras.
9
 *    Copyright (C) 1996 Paul Mackerras.
10
 *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net).
11
 *
12
 *  This file contains the system call entry code, context switch
13
 *  code, and exception/interrupt return code for PowerPC.
14
 *
15
 *  This program is free software; you can redistribute it and/or
16
 *  modify it under the terms of the GNU General Public License
17
 *  as published by the Free Software Foundation; either version
18
 *  2 of the License, or (at your option) any later version.
19
 *
20
 */
21
 
22
#include 
23
#include 
24
#include 
25
#include 
26
#include 
27
#include 
28
#include 
29
#include 
30
#include 
31
#include 
32
#include 
33
 
34
#undef SHOW_SYSCALLS
35
#undef SHOW_SYSCALLS_TASK
36
 
37
/*
38
 * MSR_KERNEL is > 0x10000 on 4xx/Book-E since it include MSR_CE.
39
 */
40
#if MSR_KERNEL >= 0x10000
41
#define LOAD_MSR_KERNEL(r, x)   lis r,(x)@h; ori r,r,(x)@l
42
#else
43
#define LOAD_MSR_KERNEL(r, x)   li r,(x)
44
#endif
45
 
46
#ifdef CONFIG_BOOKE
47
#include "head_booke.h"
48
#define TRANSFER_TO_HANDLER_EXC_LEVEL(exc_level)        \
49
        mtspr   exc_level##_SPRG,r8;                    \
50
        BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);          \
51
        lwz     r0,GPR10-INT_FRAME_SIZE(r8);            \
52
        stw     r0,GPR10(r11);                          \
53
        lwz     r0,GPR11-INT_FRAME_SIZE(r8);            \
54
        stw     r0,GPR11(r11);                          \
55
        mfspr   r8,exc_level##_SPRG
56
 
57
        .globl  mcheck_transfer_to_handler
58
mcheck_transfer_to_handler:
59
        TRANSFER_TO_HANDLER_EXC_LEVEL(MCHECK)
60
        b       transfer_to_handler_full
61
 
62
        .globl  debug_transfer_to_handler
63
debug_transfer_to_handler:
64
        TRANSFER_TO_HANDLER_EXC_LEVEL(DEBUG)
65
        b       transfer_to_handler_full
66
 
67
        .globl  crit_transfer_to_handler
68
crit_transfer_to_handler:
69
        TRANSFER_TO_HANDLER_EXC_LEVEL(CRIT)
70
        /* fall through */
71
#endif
72
 
73
#ifdef CONFIG_40x
74
        .globl  crit_transfer_to_handler
75
crit_transfer_to_handler:
76
        lwz     r0,crit_r10@l(0)
77
        stw     r0,GPR10(r11)
78
        lwz     r0,crit_r11@l(0)
79
        stw     r0,GPR11(r11)
80
        /* fall through */
81
#endif
82
 
83
/*
84
 * This code finishes saving the registers to the exception frame
85
 * and jumps to the appropriate handler for the exception, turning
86
 * on address translation.
87
 * Note that we rely on the caller having set cr0.eq iff the exception
88
 * occurred in kernel mode (i.e. MSR:PR = 0).
89
 */
90
        .globl  transfer_to_handler_full
91
transfer_to_handler_full:
92
        SAVE_NVGPRS(r11)
93
        /* fall through */
94
 
95
        .globl  transfer_to_handler
96
transfer_to_handler:
97
        stw     r2,GPR2(r11)
98
        stw     r12,_NIP(r11)
99
        stw     r9,_MSR(r11)
100
        andi.   r2,r9,MSR_PR
101
        mfctr   r12
102
        mfspr   r2,SPRN_XER
103
        stw     r12,_CTR(r11)
104
        stw     r2,_XER(r11)
105
        mfspr   r12,SPRN_SPRG3
106
        addi    r2,r12,-THREAD
107
        tovirt(r2,r2)                   /* set r2 to current */
108
        beq     2f                      /* if from user, fix up THREAD.regs */
109
        addi    r11,r1,STACK_FRAME_OVERHEAD
110
        stw     r11,PT_REGS(r12)
111
#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
112
        /* Check to see if the dbcr0 register is set up to debug.  Use the
113
           single-step bit to do this. */
114
        lwz     r12,THREAD_DBCR0(r12)
115
        andis.  r12,r12,DBCR0_IC@h
116
        beq+    3f
117
        /* From user and task is ptraced - load up global dbcr0 */
118
        li      r12,-1                  /* clear all pending debug events */
119
        mtspr   SPRN_DBSR,r12
120
        lis     r11,global_dbcr0@ha
121
        tophys(r11,r11)
122
        addi    r11,r11,global_dbcr0@l
123
        lwz     r12,0(r11)
124
        mtspr   SPRN_DBCR0,r12
125
        lwz     r12,4(r11)
126
        addi    r12,r12,-1
127
        stw     r12,4(r11)
128
#endif
129
        b       3f
130
 
131
2:      /* if from kernel, check interrupted DOZE/NAP mode and
132
         * check for stack overflow
133
         */
134
        lwz     r9,THREAD_INFO-THREAD(r12)
135
        cmplw   r1,r9                   /* if r1 <= current->thread_info */
136
        ble-    stack_ovf               /* then the kernel stack overflowed */
137
5:
138
#ifdef CONFIG_6xx
139
        tophys(r9,r9)                   /* check local flags */
140
        lwz     r12,TI_LOCAL_FLAGS(r9)
141
        mtcrf   0x01,r12
142
        bt-     31-TLF_NAPPING,4f
143
#endif /* CONFIG_6xx */
144
        .globl transfer_to_handler_cont
145
transfer_to_handler_cont:
146
3:
147
        mflr    r9
148
        lwz     r11,0(r9)               /* virtual address of handler */
149
        lwz     r9,4(r9)                /* where to go when done */
150
        mtspr   SPRN_SRR0,r11
151
        mtspr   SPRN_SRR1,r10
152
        mtlr    r9
153
        SYNC
154
        RFI                             /* jump to handler, enable MMU */
155
 
156
#ifdef CONFIG_6xx
157
4:      rlwinm  r12,r12,0,~_TLF_NAPPING
158
        stw     r12,TI_LOCAL_FLAGS(r9)
159
        b       power_save_6xx_restore
160
#endif
161
 
162
/*
163
 * On kernel stack overflow, load up an initial stack pointer
164
 * and call StackOverflow(regs), which should not return.
165
 */
166
stack_ovf:
167
        /* sometimes we use a statically-allocated stack, which is OK. */
168
        lis     r12,_end@h
169
        ori     r12,r12,_end@l
170
        cmplw   r1,r12
171
        ble     5b                      /* r1 <= &_end is OK */
172
        SAVE_NVGPRS(r11)
173
        addi    r3,r1,STACK_FRAME_OVERHEAD
174
        lis     r1,init_thread_union@ha
175
        addi    r1,r1,init_thread_union@l
176
        addi    r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
177
        lis     r9,StackOverflow@ha
178
        addi    r9,r9,StackOverflow@l
179
        LOAD_MSR_KERNEL(r10,MSR_KERNEL)
180
        FIX_SRR1(r10,r12)
181
        mtspr   SPRN_SRR0,r9
182
        mtspr   SPRN_SRR1,r10
183
        SYNC
184
        RFI
185
 
186
/*
187
 * Handle a system call.
188
 */
189
        .stabs  "arch/powerpc/kernel/",N_SO,0,0,0f
190
        .stabs  "entry_32.S",N_SO,0,0,0f
191
0:
192
 
193
_GLOBAL(DoSyscall)
194
        stw     r3,ORIG_GPR3(r1)
195
        li      r12,0
196
        stw     r12,RESULT(r1)
197
        lwz     r11,_CCR(r1)    /* Clear SO bit in CR */
198
        rlwinm  r11,r11,0,4,2
199
        stw     r11,_CCR(r1)
200
#ifdef SHOW_SYSCALLS
201
        bl      do_show_syscall
202
#endif /* SHOW_SYSCALLS */
203
        rlwinm  r10,r1,0,0,(31-THREAD_SHIFT)    /* current_thread_info() */
204
        lwz     r11,TI_FLAGS(r10)
205
        andi.   r11,r11,_TIF_SYSCALL_T_OR_A
206
        bne-    syscall_dotrace
207
syscall_dotrace_cont:
208
        cmplwi  0,r0,NR_syscalls
209
        lis     r10,sys_call_table@h
210
        ori     r10,r10,sys_call_table@l
211
        slwi    r0,r0,2
212
        bge-    66f
213
        lwzx    r10,r10,r0      /* Fetch system call handler [ptr] */
214
        mtlr    r10
215
        addi    r9,r1,STACK_FRAME_OVERHEAD
216
        PPC440EP_ERR42
217
        blrl                    /* Call handler */
218
        .globl  ret_from_syscall
219
ret_from_syscall:
220
#ifdef SHOW_SYSCALLS
221
        bl      do_show_syscall_exit
222
#endif
223
        mr      r6,r3
224
        rlwinm  r12,r1,0,0,(31-THREAD_SHIFT)    /* current_thread_info() */
225
        /* disable interrupts so current_thread_info()->flags can't change */
226
        LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
227
        SYNC
228
        MTMSRD(r10)
229
        lwz     r9,TI_FLAGS(r12)
230
        li      r8,-_LAST_ERRNO
231
        andi.   r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)
232
        bne-    syscall_exit_work
233
        cmplw   0,r3,r8
234
        blt+    syscall_exit_cont
235
        lwz     r11,_CCR(r1)                    /* Load CR */
236
        neg     r3,r3
237
        oris    r11,r11,0x1000  /* Set SO bit in CR */
238
        stw     r11,_CCR(r1)
239
syscall_exit_cont:
240
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
241
        /* If the process has its own DBCR0 value, load it up.  The single
242
           step bit tells us that dbcr0 should be loaded. */
243
        lwz     r0,THREAD+THREAD_DBCR0(r2)
244
        andis.  r10,r0,DBCR0_IC@h
245
        bnel-   load_dbcr0
246
#endif
247
#ifdef CONFIG_44x
248
        lis     r4,icache_44x_need_flush@ha
249
        lwz     r5,icache_44x_need_flush@l(r4)
250
        cmplwi  cr0,r5,0
251
        bne-    2f
252
1:
253
#endif /* CONFIG_44x */
254
BEGIN_FTR_SECTION
255
        lwarx   r7,0,r1
256
END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
257
        stwcx.  r0,0,r1                 /* to clear the reservation */
258
        lwz     r4,_LINK(r1)
259
        lwz     r5,_CCR(r1)
260
        mtlr    r4
261
        mtcr    r5
262
        lwz     r7,_NIP(r1)
263
        lwz     r8,_MSR(r1)
264
        FIX_SRR1(r8, r0)
265
        lwz     r2,GPR2(r1)
266
        lwz     r1,GPR1(r1)
267
        mtspr   SPRN_SRR0,r7
268
        mtspr   SPRN_SRR1,r8
269
        SYNC
270
        RFI
271
#ifdef CONFIG_44x
272
2:      li      r7,0
273
        iccci   r0,r0
274
        stw     r7,icache_44x_need_flush@l(r4)
275
        b       1b
276
#endif  /* CONFIG_44x */
277
 
278
66:     li      r3,-ENOSYS
279
        b       ret_from_syscall
280
 
281
        .globl  ret_from_fork
282
ret_from_fork:
283
        REST_NVGPRS(r1)
284
        bl      schedule_tail
285
        li      r3,0
286
        b       ret_from_syscall
287
 
288
/* Traced system call support */
289
syscall_dotrace:
290
        SAVE_NVGPRS(r1)
291
        li      r0,0xc00
292
        stw     r0,_TRAP(r1)
293
        addi    r3,r1,STACK_FRAME_OVERHEAD
294
        bl      do_syscall_trace_enter
295
        lwz     r0,GPR0(r1)     /* Restore original registers */
296
        lwz     r3,GPR3(r1)
297
        lwz     r4,GPR4(r1)
298
        lwz     r5,GPR5(r1)
299
        lwz     r6,GPR6(r1)
300
        lwz     r7,GPR7(r1)
301
        lwz     r8,GPR8(r1)
302
        REST_NVGPRS(r1)
303
        b       syscall_dotrace_cont
304
 
305
syscall_exit_work:
306
        andi.   r0,r9,_TIF_RESTOREALL
307
        beq+    0f
308
        REST_NVGPRS(r1)
309
        b       2f
310
0:      cmplw   0,r3,r8
311
        blt+    1f
312
        andi.   r0,r9,_TIF_NOERROR
313
        bne-    1f
314
        lwz     r11,_CCR(r1)                    /* Load CR */
315
        neg     r3,r3
316
        oris    r11,r11,0x1000  /* Set SO bit in CR */
317
        stw     r11,_CCR(r1)
318
 
319
1:      stw     r6,RESULT(r1)   /* Save result */
320
        stw     r3,GPR3(r1)     /* Update return value */
321
2:      andi.   r0,r9,(_TIF_PERSYSCALL_MASK)
322
        beq     4f
323
 
324
        /* Clear per-syscall TIF flags if any are set.  */
325
 
326
        li      r11,_TIF_PERSYSCALL_MASK
327
        addi    r12,r12,TI_FLAGS
328
3:      lwarx   r8,0,r12
329
        andc    r8,r8,r11
330
#ifdef CONFIG_IBM405_ERR77
331
        dcbt    0,r12
332
#endif
333
        stwcx.  r8,0,r12
334
        bne-    3b
335
        subi    r12,r12,TI_FLAGS
336
 
337
4:      /* Anything which requires enabling interrupts? */
338
        andi.   r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
339
        beq     ret_from_except
340
 
341
        /* Re-enable interrupts */
342
        ori     r10,r10,MSR_EE
343
        SYNC
344
        MTMSRD(r10)
345
 
346
        /* Save NVGPRS if they're not saved already */
347
        lwz     r4,_TRAP(r1)
348
        andi.   r4,r4,1
349
        beq     5f
350
        SAVE_NVGPRS(r1)
351
        li      r4,0xc00
352
        stw     r4,_TRAP(r1)
353
5:
354
        addi    r3,r1,STACK_FRAME_OVERHEAD
355
        bl      do_syscall_trace_leave
356
        b       ret_from_except_full
357
 
358
#ifdef SHOW_SYSCALLS
359
do_show_syscall:
360
#ifdef SHOW_SYSCALLS_TASK
361
        lis     r11,show_syscalls_task@ha
362
        lwz     r11,show_syscalls_task@l(r11)
363
        cmp     0,r2,r11
364
        bnelr
365
#endif
366
        stw     r31,GPR31(r1)
367
        mflr    r31
368
        lis     r3,7f@ha
369
        addi    r3,r3,7f@l
370
        lwz     r4,GPR0(r1)
371
        lwz     r5,GPR3(r1)
372
        lwz     r6,GPR4(r1)
373
        lwz     r7,GPR5(r1)
374
        lwz     r8,GPR6(r1)
375
        lwz     r9,GPR7(r1)
376
        bl      printk
377
        lis     r3,77f@ha
378
        addi    r3,r3,77f@l
379
        lwz     r4,GPR8(r1)
380
        mr      r5,r2
381
        bl      printk
382
        lwz     r0,GPR0(r1)
383
        lwz     r3,GPR3(r1)
384
        lwz     r4,GPR4(r1)
385
        lwz     r5,GPR5(r1)
386
        lwz     r6,GPR6(r1)
387
        lwz     r7,GPR7(r1)
388
        lwz     r8,GPR8(r1)
389
        mtlr    r31
390
        lwz     r31,GPR31(r1)
391
        blr
392
 
393
do_show_syscall_exit:
394
#ifdef SHOW_SYSCALLS_TASK
395
        lis     r11,show_syscalls_task@ha
396
        lwz     r11,show_syscalls_task@l(r11)
397
        cmp     0,r2,r11
398
        bnelr
399
#endif
400
        stw     r31,GPR31(r1)
401
        mflr    r31
402
        stw     r3,RESULT(r1)   /* Save result */
403
        mr      r4,r3
404
        lis     r3,79f@ha
405
        addi    r3,r3,79f@l
406
        bl      printk
407
        lwz     r3,RESULT(r1)
408
        mtlr    r31
409
        lwz     r31,GPR31(r1)
410
        blr
411
 
412
7:      .string "syscall %d(%x, %x, %x, %x, %x, "
413
77:     .string "%x), current=%p\n"
414
79:     .string " -> %x\n"
415
        .align  2,0
416
 
417
#ifdef SHOW_SYSCALLS_TASK
418
        .data
419
        .globl  show_syscalls_task
420
show_syscalls_task:
421
        .long   -1
422
        .text
423
#endif
424
#endif /* SHOW_SYSCALLS */
425
 
426
/*
427
 * The fork/clone functions need to copy the full register set into
428
 * the child process. Therefore we need to save all the nonvolatile
429
 * registers (r13 - r31) before calling the C code.
430
 */
431
        .globl  ppc_fork
432
ppc_fork:
433
        SAVE_NVGPRS(r1)
434
        lwz     r0,_TRAP(r1)
435
        rlwinm  r0,r0,0,0,30            /* clear LSB to indicate full */
436
        stw     r0,_TRAP(r1)            /* register set saved */
437
        b       sys_fork
438
 
439
        .globl  ppc_vfork
440
ppc_vfork:
441
        SAVE_NVGPRS(r1)
442
        lwz     r0,_TRAP(r1)
443
        rlwinm  r0,r0,0,0,30            /* clear LSB to indicate full */
444
        stw     r0,_TRAP(r1)            /* register set saved */
445
        b       sys_vfork
446
 
447
        .globl  ppc_clone
448
ppc_clone:
449
        SAVE_NVGPRS(r1)
450
        lwz     r0,_TRAP(r1)
451
        rlwinm  r0,r0,0,0,30            /* clear LSB to indicate full */
452
        stw     r0,_TRAP(r1)            /* register set saved */
453
        b       sys_clone
454
 
455
        .globl  ppc_swapcontext
456
ppc_swapcontext:
457
        SAVE_NVGPRS(r1)
458
        lwz     r0,_TRAP(r1)
459
        rlwinm  r0,r0,0,0,30            /* clear LSB to indicate full */
460
        stw     r0,_TRAP(r1)            /* register set saved */
461
        b       sys_swapcontext
462
 
463
/*
464
 * Top-level page fault handling.
465
 * This is in assembler because if do_page_fault tells us that
466
 * it is a bad kernel page fault, we want to save the non-volatile
467
 * registers before calling bad_page_fault.
468
 */
469
        .globl  handle_page_fault
470
handle_page_fault:
471
        stw     r4,_DAR(r1)
472
        addi    r3,r1,STACK_FRAME_OVERHEAD
473
        bl      do_page_fault
474
        cmpwi   r3,0
475
        beq+    ret_from_except
476
        SAVE_NVGPRS(r1)
477
        lwz     r0,_TRAP(r1)
478
        clrrwi  r0,r0,1
479
        stw     r0,_TRAP(r1)
480
        mr      r5,r3
481
        addi    r3,r1,STACK_FRAME_OVERHEAD
482
        lwz     r4,_DAR(r1)
483
        bl      bad_page_fault
484
        b       ret_from_except_full
485
 
486
/*
487
 * This routine switches between two different tasks.  The process
488
 * state of one is saved on its kernel stack.  Then the state
489
 * of the other is restored from its kernel stack.  The memory
490
 * management hardware is updated to the second process's state.
491
 * Finally, we can return to the second process.
492
 * On entry, r3 points to the THREAD for the current task, r4
493
 * points to the THREAD for the new task.
494
 *
495
 * This routine is always called with interrupts disabled.
496
 *
497
 * Note: there are two ways to get to the "going out" portion
498
 * of this code; either by coming in via the entry (_switch)
499
 * or via "fork" which must set up an environment equivalent
500
 * to the "_switch" path.  If you change this , you'll have to
501
 * change the fork code also.
502
 *
503
 * The code which creates the new task context is in 'copy_thread'
504
 * in arch/ppc/kernel/process.c
505
 */
506
_GLOBAL(_switch)
507
        stwu    r1,-INT_FRAME_SIZE(r1)
508
        mflr    r0
509
        stw     r0,INT_FRAME_SIZE+4(r1)
510
        /* r3-r12 are caller saved -- Cort */
511
        SAVE_NVGPRS(r1)
512
        stw     r0,_NIP(r1)     /* Return to switch caller */
513
        mfmsr   r11
514
        li      r0,MSR_FP       /* Disable floating-point */
515
#ifdef CONFIG_ALTIVEC
516
BEGIN_FTR_SECTION
517
        oris    r0,r0,MSR_VEC@h /* Disable altivec */
518
        mfspr   r12,SPRN_VRSAVE /* save vrsave register value */
519
        stw     r12,THREAD+THREAD_VRSAVE(r2)
520
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
521
#endif /* CONFIG_ALTIVEC */
522
#ifdef CONFIG_SPE
523
BEGIN_FTR_SECTION
524
        oris    r0,r0,MSR_SPE@h  /* Disable SPE */
525
        mfspr   r12,SPRN_SPEFSCR /* save spefscr register value */
526
        stw     r12,THREAD+THREAD_SPEFSCR(r2)
527
END_FTR_SECTION_IFSET(CPU_FTR_SPE)
528
#endif /* CONFIG_SPE */
529
        and.    r0,r0,r11       /* FP or altivec or SPE enabled? */
530
        beq+    1f
531
        andc    r11,r11,r0
532
        MTMSRD(r11)
533
        isync
534
1:      stw     r11,_MSR(r1)
535
        mfcr    r10
536
        stw     r10,_CCR(r1)
537
        stw     r1,KSP(r3)      /* Set old stack pointer */
538
 
539
#ifdef CONFIG_SMP
540
        /* We need a sync somewhere here to make sure that if the
541
         * previous task gets rescheduled on another CPU, it sees all
542
         * stores it has performed on this one.
543
         */
544
        sync
545
#endif /* CONFIG_SMP */
546
 
547
        tophys(r0,r4)
548
        CLR_TOP32(r0)
549
        mtspr   SPRN_SPRG3,r0   /* Update current THREAD phys addr */
550
        lwz     r1,KSP(r4)      /* Load new stack pointer */
551
 
552
        /* save the old current 'last' for return value */
553
        mr      r3,r2
554
        addi    r2,r4,-THREAD   /* Update current */
555
 
556
#ifdef CONFIG_ALTIVEC
557
BEGIN_FTR_SECTION
558
        lwz     r0,THREAD+THREAD_VRSAVE(r2)
559
        mtspr   SPRN_VRSAVE,r0          /* if G4, restore VRSAVE reg */
560
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
561
#endif /* CONFIG_ALTIVEC */
562
#ifdef CONFIG_SPE
563
BEGIN_FTR_SECTION
564
        lwz     r0,THREAD+THREAD_SPEFSCR(r2)
565
        mtspr   SPRN_SPEFSCR,r0         /* restore SPEFSCR reg */
566
END_FTR_SECTION_IFSET(CPU_FTR_SPE)
567
#endif /* CONFIG_SPE */
568
 
569
        lwz     r0,_CCR(r1)
570
        mtcrf   0xFF,r0
571
        /* r3-r12 are destroyed -- Cort */
572
        REST_NVGPRS(r1)
573
 
574
        lwz     r4,_NIP(r1)     /* Return to _switch caller in new task */
575
        mtlr    r4
576
        addi    r1,r1,INT_FRAME_SIZE
577
        blr
578
 
579
        .globl  fast_exception_return
580
fast_exception_return:
581
#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
582
        andi.   r10,r9,MSR_RI           /* check for recoverable interrupt */
583
        beq     1f                      /* if not, we've got problems */
584
#endif
585
 
586
2:      REST_4GPRS(3, r11)
587
        lwz     r10,_CCR(r11)
588
        REST_GPR(1, r11)
589
        mtcr    r10
590
        lwz     r10,_LINK(r11)
591
        mtlr    r10
592
        REST_GPR(10, r11)
593
        mtspr   SPRN_SRR1,r9
594
        mtspr   SPRN_SRR0,r12
595
        REST_GPR(9, r11)
596
        REST_GPR(12, r11)
597
        lwz     r11,GPR11(r11)
598
        SYNC
599
        RFI
600
 
601
#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
602
/* check if the exception happened in a restartable section */
603
1:      lis     r3,exc_exit_restart_end@ha
604
        addi    r3,r3,exc_exit_restart_end@l
605
        cmplw   r12,r3
606
        bge     3f
607
        lis     r4,exc_exit_restart@ha
608
        addi    r4,r4,exc_exit_restart@l
609
        cmplw   r12,r4
610
        blt     3f
611
        lis     r3,fee_restarts@ha
612
        tophys(r3,r3)
613
        lwz     r5,fee_restarts@l(r3)
614
        addi    r5,r5,1
615
        stw     r5,fee_restarts@l(r3)
616
        mr      r12,r4          /* restart at exc_exit_restart */
617
        b       2b
618
 
619
        .section .bss
620
        .align  2
621
fee_restarts:
622
        .space  4
623
        .previous
624
 
625
/* aargh, a nonrecoverable interrupt, panic */
626
/* aargh, we don't know which trap this is */
627
/* but the 601 doesn't implement the RI bit, so assume it's OK */
628
3:
629
BEGIN_FTR_SECTION
630
        b       2b
631
END_FTR_SECTION_IFSET(CPU_FTR_601)
632
        li      r10,-1
633
        stw     r10,_TRAP(r11)
634
        addi    r3,r1,STACK_FRAME_OVERHEAD
635
        lis     r10,MSR_KERNEL@h
636
        ori     r10,r10,MSR_KERNEL@l
637
        bl      transfer_to_handler_full
638
        .long   nonrecoverable_exception
639
        .long   ret_from_except
640
#endif
641
 
642
        .globl  ret_from_except_full
643
ret_from_except_full:
644
        REST_NVGPRS(r1)
645
        /* fall through */
646
 
647
        .globl  ret_from_except
648
ret_from_except:
649
        /* Hard-disable interrupts so that current_thread_info()->flags
650
         * can't change between when we test it and when we return
651
         * from the interrupt. */
652
        LOAD_MSR_KERNEL(r10,MSR_KERNEL)
653
        SYNC                    /* Some chip revs have problems here... */
654
        MTMSRD(r10)             /* disable interrupts */
655
 
656
        lwz     r3,_MSR(r1)     /* Returning to user mode? */
657
        andi.   r0,r3,MSR_PR
658
        beq     resume_kernel
659
 
660
user_exc_return:                /* r10 contains MSR_KERNEL here */
661
        /* Check current_thread_info()->flags */
662
        rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
663
        lwz     r9,TI_FLAGS(r9)
664
        andi.   r0,r9,(_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NEED_RESCHED)
665
        bne     do_work
666
 
667
restore_user:
668
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
669
        /* Check whether this process has its own DBCR0 value.  The single
670
           step bit tells us that dbcr0 should be loaded. */
671
        lwz     r0,THREAD+THREAD_DBCR0(r2)
672
        andis.  r10,r0,DBCR0_IC@h
673
        bnel-   load_dbcr0
674
#endif
675
 
676
#ifdef CONFIG_PREEMPT
677
        b       restore
678
 
679
/* N.B. the only way to get here is from the beq following ret_from_except. */
680
resume_kernel:
681
        /* check current_thread_info->preempt_count */
682
        rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
683
        lwz     r0,TI_PREEMPT(r9)
684
        cmpwi   0,r0,0          /* if non-zero, just restore regs and return */
685
        bne     restore
686
        lwz     r0,TI_FLAGS(r9)
687
        andi.   r0,r0,_TIF_NEED_RESCHED
688
        beq+    restore
689
        andi.   r0,r3,MSR_EE    /* interrupts off? */
690
        beq     restore         /* don't schedule if so */
691
1:      bl      preempt_schedule_irq
692
        rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
693
        lwz     r3,TI_FLAGS(r9)
694
        andi.   r0,r3,_TIF_NEED_RESCHED
695
        bne-    1b
696
#else
697
resume_kernel:
698
#endif /* CONFIG_PREEMPT */
699
 
700
        /* interrupts are hard-disabled at this point */
701
restore:
702
#ifdef CONFIG_44x
703
        lis     r4,icache_44x_need_flush@ha
704
        lwz     r5,icache_44x_need_flush@l(r4)
705
        cmplwi  cr0,r5,0
706
        beq+    1f
707
        li      r6,0
708
        iccci   r0,r0
709
        stw     r6,icache_44x_need_flush@l(r4)
710
1:
711
#endif  /* CONFIG_44x */
712
        lwz     r0,GPR0(r1)
713
        lwz     r2,GPR2(r1)
714
        REST_4GPRS(3, r1)
715
        REST_2GPRS(7, r1)
716
 
717
        lwz     r10,_XER(r1)
718
        lwz     r11,_CTR(r1)
719
        mtspr   SPRN_XER,r10
720
        mtctr   r11
721
 
722
        PPC405_ERR77(0,r1)
723
BEGIN_FTR_SECTION
724
        lwarx   r11,0,r1
725
END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
726
        stwcx.  r0,0,r1                 /* to clear the reservation */
727
 
728
#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
729
        lwz     r9,_MSR(r1)
730
        andi.   r10,r9,MSR_RI           /* check if this exception occurred */
731
        beql    nonrecoverable          /* at a bad place (MSR:RI = 0) */
732
 
733
        lwz     r10,_CCR(r1)
734
        lwz     r11,_LINK(r1)
735
        mtcrf   0xFF,r10
736
        mtlr    r11
737
 
738
        /*
739
         * Once we put values in SRR0 and SRR1, we are in a state
740
         * where exceptions are not recoverable, since taking an
741
         * exception will trash SRR0 and SRR1.  Therefore we clear the
742
         * MSR:RI bit to indicate this.  If we do take an exception,
743
         * we can't return to the point of the exception but we
744
         * can restart the exception exit path at the label
745
         * exc_exit_restart below.  -- paulus
746
         */
747
        LOAD_MSR_KERNEL(r10,MSR_KERNEL & ~MSR_RI)
748
        SYNC
749
        MTMSRD(r10)             /* clear the RI bit */
750
        .globl exc_exit_restart
751
exc_exit_restart:
752
        lwz     r9,_MSR(r1)
753
        lwz     r12,_NIP(r1)
754
        FIX_SRR1(r9,r10)
755
        mtspr   SPRN_SRR0,r12
756
        mtspr   SPRN_SRR1,r9
757
        REST_4GPRS(9, r1)
758
        lwz     r1,GPR1(r1)
759
        .globl exc_exit_restart_end
760
exc_exit_restart_end:
761
        SYNC
762
        RFI
763
 
764
#else /* !(CONFIG_4xx || CONFIG_BOOKE) */
765
        /*
766
         * This is a bit different on 4xx/Book-E because it doesn't have
767
         * the RI bit in the MSR.
768
         * The TLB miss handler checks if we have interrupted
769
         * the exception exit path and restarts it if so
770
         * (well maybe one day it will... :).
771
         */
772
        lwz     r11,_LINK(r1)
773
        mtlr    r11
774
        lwz     r10,_CCR(r1)
775
        mtcrf   0xff,r10
776
        REST_2GPRS(9, r1)
777
        .globl exc_exit_restart
778
exc_exit_restart:
779
        lwz     r11,_NIP(r1)
780
        lwz     r12,_MSR(r1)
781
exc_exit_start:
782
        mtspr   SPRN_SRR0,r11
783
        mtspr   SPRN_SRR1,r12
784
        REST_2GPRS(11, r1)
785
        lwz     r1,GPR1(r1)
786
        .globl exc_exit_restart_end
787
exc_exit_restart_end:
788
        PPC405_ERR77_SYNC
789
        rfi
790
        b       .                       /* prevent prefetch past rfi */
791
 
792
/*
793
 * Returning from a critical interrupt in user mode doesn't need
794
 * to be any different from a normal exception.  For a critical
795
 * interrupt in the kernel, we just return (without checking for
796
 * preemption) since the interrupt may have happened at some crucial
797
 * place (e.g. inside the TLB miss handler), and because we will be
798
 * running with r1 pointing into critical_stack, not the current
799
 * process's kernel stack (and therefore current_thread_info() will
800
 * give the wrong answer).
801
 * We have to restore various SPRs that may have been in use at the
802
 * time of the critical interrupt.
803
 *
804
 */
805
#ifdef CONFIG_40x
806
#define PPC_40x_TURN_OFF_MSR_DR                                             \
807
        /* avoid any possible TLB misses here by turning off MSR.DR, we     \
808
         * assume the instructions here are mapped by a pinned TLB entry */ \
809
        li      r10,MSR_IR;                                                 \
810
        mtmsr   r10;                                                        \
811
        isync;                                                              \
812
        tophys(r1, r1);
813
#else
814
#define PPC_40x_TURN_OFF_MSR_DR
815
#endif
816
 
817
#define RET_FROM_EXC_LEVEL(exc_lvl_srr0, exc_lvl_srr1, exc_lvl_rfi)     \
818
        REST_NVGPRS(r1);                                                \
819
        lwz     r3,_MSR(r1);                                            \
820
        andi.   r3,r3,MSR_PR;                                           \
821
        LOAD_MSR_KERNEL(r10,MSR_KERNEL);                                \
822
        bne     user_exc_return;                                        \
823
        lwz     r0,GPR0(r1);                                            \
824
        lwz     r2,GPR2(r1);                                            \
825
        REST_4GPRS(3, r1);                                              \
826
        REST_2GPRS(7, r1);                                              \
827
        lwz     r10,_XER(r1);                                           \
828
        lwz     r11,_CTR(r1);                                           \
829
        mtspr   SPRN_XER,r10;                                           \
830
        mtctr   r11;                                                    \
831
        PPC405_ERR77(0,r1);                                             \
832
        stwcx.  r0,0,r1;                /* to clear the reservation */  \
833
        lwz     r11,_LINK(r1);                                          \
834
        mtlr    r11;                                                    \
835
        lwz     r10,_CCR(r1);                                           \
836
        mtcrf   0xff,r10;                                               \
837
        PPC_40x_TURN_OFF_MSR_DR;                                        \
838
        lwz     r9,_DEAR(r1);                                           \
839
        lwz     r10,_ESR(r1);                                           \
840
        mtspr   SPRN_DEAR,r9;                                           \
841
        mtspr   SPRN_ESR,r10;                                           \
842
        lwz     r11,_NIP(r1);                                           \
843
        lwz     r12,_MSR(r1);                                           \
844
        mtspr   exc_lvl_srr0,r11;                                       \
845
        mtspr   exc_lvl_srr1,r12;                                       \
846
        lwz     r9,GPR9(r1);                                            \
847
        lwz     r12,GPR12(r1);                                          \
848
        lwz     r10,GPR10(r1);                                          \
849
        lwz     r11,GPR11(r1);                                          \
850
        lwz     r1,GPR1(r1);                                            \
851
        PPC405_ERR77_SYNC;                                              \
852
        exc_lvl_rfi;                                                    \
853
        b       .;              /* prevent prefetch past exc_lvl_rfi */
854
 
855
        .globl  ret_from_crit_exc
856
ret_from_crit_exc:
857
        RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
858
 
859
#ifdef CONFIG_BOOKE
860
        .globl  ret_from_debug_exc
861
ret_from_debug_exc:
862
        RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, RFDI)
863
 
864
        .globl  ret_from_mcheck_exc
865
ret_from_mcheck_exc:
866
        RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI)
867
#endif /* CONFIG_BOOKE */
868
 
869
/*
870
 * Load the DBCR0 value for a task that is being ptraced,
871
 * having first saved away the global DBCR0.  Note that r0
872
 * has the dbcr0 value to set upon entry to this.
873
 */
874
load_dbcr0:
875
        mfmsr   r10             /* first disable debug exceptions */
876
        rlwinm  r10,r10,0,~MSR_DE
877
        mtmsr   r10
878
        isync
879
        mfspr   r10,SPRN_DBCR0
880
        lis     r11,global_dbcr0@ha
881
        addi    r11,r11,global_dbcr0@l
882
        stw     r10,0(r11)
883
        mtspr   SPRN_DBCR0,r0
884
        lwz     r10,4(r11)
885
        addi    r10,r10,1
886
        stw     r10,4(r11)
887
        li      r11,-1
888
        mtspr   SPRN_DBSR,r11   /* clear all pending debug events */
889
        blr
890
 
891
        .section .bss
892
        .align  4
893
global_dbcr0:
894
        .space  8
895
        .previous
896
#endif /* !(CONFIG_4xx || CONFIG_BOOKE) */
897
 
898
do_work:                        /* r10 contains MSR_KERNEL here */
899
        andi.   r0,r9,_TIF_NEED_RESCHED
900
        beq     do_user_signal
901
 
902
do_resched:                     /* r10 contains MSR_KERNEL here */
903
        ori     r10,r10,MSR_EE
904
        SYNC
905
        MTMSRD(r10)             /* hard-enable interrupts */
906
        bl      schedule
907
recheck:
908
        LOAD_MSR_KERNEL(r10,MSR_KERNEL)
909
        SYNC
910
        MTMSRD(r10)             /* disable interrupts */
911
        rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
912
        lwz     r9,TI_FLAGS(r9)
913
        andi.   r0,r9,_TIF_NEED_RESCHED
914
        bne-    do_resched
915
        andi.   r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
916
        beq     restore_user
917
do_user_signal:                 /* r10 contains MSR_KERNEL here */
918
        ori     r10,r10,MSR_EE
919
        SYNC
920
        MTMSRD(r10)             /* hard-enable interrupts */
921
        /* save r13-r31 in the exception frame, if not already done */
922
        lwz     r3,_TRAP(r1)
923
        andi.   r0,r3,1
924
        beq     2f
925
        SAVE_NVGPRS(r1)
926
        rlwinm  r3,r3,0,0,30
927
        stw     r3,_TRAP(r1)
928
2:      li      r3,0
929
        addi    r4,r1,STACK_FRAME_OVERHEAD
930
        bl      do_signal
931
        REST_NVGPRS(r1)
932
        b       recheck
933
 
934
/*
935
 * We come here when we are at the end of handling an exception
936
 * that occurred at a place where taking an exception will lose
937
 * state information, such as the contents of SRR0 and SRR1.
938
 */
939
nonrecoverable:
940
        lis     r10,exc_exit_restart_end@ha
941
        addi    r10,r10,exc_exit_restart_end@l
942
        cmplw   r12,r10
943
        bge     3f
944
        lis     r11,exc_exit_restart@ha
945
        addi    r11,r11,exc_exit_restart@l
946
        cmplw   r12,r11
947
        blt     3f
948
        lis     r10,ee_restarts@ha
949
        lwz     r12,ee_restarts@l(r10)
950
        addi    r12,r12,1
951
        stw     r12,ee_restarts@l(r10)
952
        mr      r12,r11         /* restart at exc_exit_restart */
953
        blr
954
3:      /* OK, we can't recover, kill this process */
955
        /* but the 601 doesn't implement the RI bit, so assume it's OK */
956
BEGIN_FTR_SECTION
957
        blr
958
END_FTR_SECTION_IFSET(CPU_FTR_601)
959
        lwz     r3,_TRAP(r1)
960
        andi.   r0,r3,1
961
        beq     4f
962
        SAVE_NVGPRS(r1)
963
        rlwinm  r3,r3,0,0,30
964
        stw     r3,_TRAP(r1)
965
4:      addi    r3,r1,STACK_FRAME_OVERHEAD
966
        bl      nonrecoverable_exception
967
        /* shouldn't return */
968
        b       4b
969
 
970
        .section .bss
971
        .align  2
972
ee_restarts:
973
        .space  4
974
        .previous
975
 
976
/*
977
 * PROM code for specific machines follows.  Put it
978
 * here so it's easy to add arch-specific sections later.
979
 * -- Cort
980
 */
981
#ifdef CONFIG_PPC_RTAS
982
/*
983
 * On CHRP, the Run-Time Abstraction Services (RTAS) have to be
984
 * called with the MMU off.
985
 */
986
_GLOBAL(enter_rtas)
987
        stwu    r1,-INT_FRAME_SIZE(r1)
988
        mflr    r0
989
        stw     r0,INT_FRAME_SIZE+4(r1)
990
        LOAD_REG_ADDR(r4, rtas)
991
        lis     r6,1f@ha        /* physical return address for rtas */
992
        addi    r6,r6,1f@l
993
        tophys(r6,r6)
994
        tophys(r7,r1)
995
        lwz     r8,RTASENTRY(r4)
996
        lwz     r4,RTASBASE(r4)
997
        mfmsr   r9
998
        stw     r9,8(r1)
999
        LOAD_MSR_KERNEL(r0,MSR_KERNEL)
1000
        SYNC                    /* disable interrupts so SRR0/1 */
1001
        MTMSRD(r0)              /* don't get trashed */
1002
        li      r9,MSR_KERNEL & ~(MSR_IR|MSR_DR)
1003
        mtlr    r6
1004
        mtspr   SPRN_SPRG2,r7
1005
        mtspr   SPRN_SRR0,r8
1006
        mtspr   SPRN_SRR1,r9
1007
        RFI
1008
1:      tophys(r9,r1)
1009
        lwz     r8,INT_FRAME_SIZE+4(r9) /* get return address */
1010
        lwz     r9,8(r9)        /* original msr value */
1011
        FIX_SRR1(r9,r0)
1012
        addi    r1,r1,INT_FRAME_SIZE
1013
        li      r0,0
1014
        mtspr   SPRN_SPRG2,r0
1015
        mtspr   SPRN_SRR0,r8
1016
        mtspr   SPRN_SRR1,r9
1017
        RFI                     /* return to caller */
1018
 
1019
        .globl  machine_check_in_rtas
1020
machine_check_in_rtas:
1021
        twi     31,0,0
1022
        /* XXX load up BATs and panic */
1023
 
1024
#endif /* CONFIG_PPC_RTAS */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.