sparc32: remove sun4c traps
[linux-2.6.git] / arch / sparc / kernel / entry.S
blob8abe65d3f729d86623c1763bd8fb857e5ba252af
1 /* arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
2  *
3  * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
4  * Copyright (C) 1996 Eddie C. Dost   (ecd@skynet.be)
5  * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
6  * Copyright (C) 1996-1999 Jakub Jelinek   (jj@sunsite.mff.cuni.cz)
7  * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au)
8  */
10 #include <linux/errno.h>
12 #include <asm/head.h>
13 #include <asm/asi.h>
14 #include <asm/smp.h>
15 #include <asm/contregs.h>
16 #include <asm/ptrace.h>
17 #include <asm/asm-offsets.h>
18 #include <asm/psr.h>
19 #include <asm/vaddrs.h>
20 #include <asm/page.h>
21 #include <asm/pgtable.h>
22 #include <asm/pgtsun4c.h>
23 #include <asm/winmacro.h>
24 #include <asm/signal.h>
25 #include <asm/obio.h>
26 #include <asm/mxcc.h>
27 #include <asm/thread_info.h>
28 #include <asm/param.h>
29 #include <asm/unistd.h>
31 #include <asm/asmmacro.h>
33 #define curptr      g6
35 /* These are just handy. */
36 #define _SV     save    %sp, -STACKFRAME_SZ, %sp
37 #define _RS     restore 
39 #define FLUSH_ALL_KERNEL_WINDOWS \
40         _SV; _SV; _SV; _SV; _SV; _SV; _SV; \
41         _RS; _RS; _RS; _RS; _RS; _RS; _RS;
43         .text
45 #ifdef CONFIG_KGDB
46         .align  4
47         .globl          arch_kgdb_breakpoint
48         .type           arch_kgdb_breakpoint,#function
49 arch_kgdb_breakpoint:
50         ta              0x7d
51         retl
52          nop
53         .size           arch_kgdb_breakpoint,.-arch_kgdb_breakpoint
54 #endif
56 #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
57         .align  4
58         .globl  floppy_hardint
59 floppy_hardint:
60         /*
61          * This code cannot touch registers %l0 %l1 and %l2
62          * because SAVE_ALL depends on their values. It depends
63          * on %l3 also, but we regenerate it before a call.
64          * Other registers are:
65          * %l3 -- base address of fdc registers
66          * %l4 -- pdma_vaddr
67          * %l5 -- scratch for ld/st address
68          * %l6 -- pdma_size
69          * %l7 -- scratch [floppy byte, ld/st address, aux. data]
70          */
72         /* Do we have work to do? */
73         sethi   %hi(doing_pdma), %l7
74         ld      [%l7 + %lo(doing_pdma)], %l7
75         cmp     %l7, 0
76         be      floppy_dosoftint
77          nop
79         /* Load fdc register base */
80         sethi   %hi(fdc_status), %l3
81         ld      [%l3 + %lo(fdc_status)], %l3
83         /* Setup register addresses */
84         sethi   %hi(pdma_vaddr), %l5    ! transfer buffer
85         ld      [%l5 + %lo(pdma_vaddr)], %l4
86         sethi   %hi(pdma_size), %l5     ! bytes to go
87         ld      [%l5 + %lo(pdma_size)], %l6
88 next_byte:
89         ldub    [%l3], %l7
91         andcc   %l7, 0x80, %g0          ! Does fifo still have data
92         bz      floppy_fifo_emptied     ! fifo has been emptied...
93          andcc  %l7, 0x20, %g0          ! in non-dma mode still?
94         bz      floppy_overrun          ! nope, overrun
95          andcc  %l7, 0x40, %g0          ! 0=write 1=read
96         bz      floppy_write
97          sub    %l6, 0x1, %l6
99         /* Ok, actually read this byte */
100         ldub    [%l3 + 1], %l7
101         orcc    %g0, %l6, %g0
102         stb     %l7, [%l4]
103         bne     next_byte
104          add    %l4, 0x1, %l4
106         b       floppy_tdone
107          nop
109 floppy_write:
110         /* Ok, actually write this byte */
111         ldub    [%l4], %l7
112         orcc    %g0, %l6, %g0
113         stb     %l7, [%l3 + 1]
114         bne     next_byte
115          add    %l4, 0x1, %l4
117         /* fall through... */
118 floppy_tdone:
119         sethi   %hi(pdma_vaddr), %l5
120         st      %l4, [%l5 + %lo(pdma_vaddr)]
121         sethi   %hi(pdma_size), %l5
122         st      %l6, [%l5 + %lo(pdma_size)]
123         /* Flip terminal count pin */
124         set     auxio_register, %l7
125         ld      [%l7], %l7
127         set     sparc_cpu_model, %l5
128         ld      [%l5], %l5
129         subcc   %l5, 1, %g0             /* enum { sun4c = 1 }; */
130         be      1f
131          ldub   [%l7], %l5
133         or      %l5, 0xc2, %l5
134         stb     %l5, [%l7]
135         andn    %l5, 0x02, %l5
136         b       2f
137          nop
140         or      %l5, 0xf4, %l5
141         stb     %l5, [%l7]
142         andn    %l5, 0x04, %l5
145         /* Kill some time so the bits set */
146         WRITE_PAUSE
147         WRITE_PAUSE
149         stb     %l5, [%l7]
151         /* Prevent recursion */
152         sethi   %hi(doing_pdma), %l7
153         b       floppy_dosoftint
154          st     %g0, [%l7 + %lo(doing_pdma)]
156         /* We emptied the FIFO, but we haven't read everything
157          * as of yet.  Store the current transfer address and
158          * bytes left to read so we can continue when the next
159          * fast IRQ comes in.
160          */
161 floppy_fifo_emptied:
162         sethi   %hi(pdma_vaddr), %l5
163         st      %l4, [%l5 + %lo(pdma_vaddr)]
164         sethi   %hi(pdma_size), %l7
165         st      %l6, [%l7 + %lo(pdma_size)]
167         /* Restore condition codes */
168         wr      %l0, 0x0, %psr
169         WRITE_PAUSE
171         jmp     %l1
172         rett    %l2
174 floppy_overrun:
175         sethi   %hi(pdma_vaddr), %l5
176         st      %l4, [%l5 + %lo(pdma_vaddr)]
177         sethi   %hi(pdma_size), %l5
178         st      %l6, [%l5 + %lo(pdma_size)]
179         /* Prevent recursion */
180         sethi   %hi(doing_pdma), %l7
181         st      %g0, [%l7 + %lo(doing_pdma)]
183         /* fall through... */
184 floppy_dosoftint:
185         rd      %wim, %l3
186         SAVE_ALL
188         /* Set all IRQs off. */
189         or      %l0, PSR_PIL, %l4
190         wr      %l4, 0x0, %psr
191         WRITE_PAUSE
192         wr      %l4, PSR_ET, %psr
193         WRITE_PAUSE
195         mov     11, %o0                 ! floppy irq level (unused anyway)
196         mov     %g0, %o1                ! devid is not used in fast interrupts
197         call    sparc_floppy_irq
198          add    %sp, STACKFRAME_SZ, %o2 ! struct pt_regs *regs
200         RESTORE_ALL
201         
202 #endif /* (CONFIG_BLK_DEV_FD) */
204         /* Bad trap handler */
205         .globl  bad_trap_handler
206 bad_trap_handler:
207         SAVE_ALL
209         wr      %l0, PSR_ET, %psr
210         WRITE_PAUSE
212         add     %sp, STACKFRAME_SZ, %o0 ! pt_regs
213         call    do_hw_interrupt
214          mov    %l7, %o1                ! trap number
216         RESTORE_ALL
217         
218 /* For now all IRQ's not registered get sent here. handler_irq() will
219  * see if a routine is registered to handle this interrupt and if not
220  * it will say so on the console.
221  */
223         .align  4
224         .globl  real_irq_entry, patch_handler_irq
225 real_irq_entry:
226         SAVE_ALL
228 #ifdef CONFIG_SMP
229         .globl  patchme_maybe_smp_msg
231         cmp     %l7, 11
232 patchme_maybe_smp_msg:
233         bgu     maybe_smp4m_msg
234          nop
235 #endif
237 real_irq_continue:
238         or      %l0, PSR_PIL, %g2
239         wr      %g2, 0x0, %psr
240         WRITE_PAUSE
241         wr      %g2, PSR_ET, %psr
242         WRITE_PAUSE
243         mov     %l7, %o0                ! irq level
244 patch_handler_irq:
245         call    handler_irq
246          add    %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr
247         or      %l0, PSR_PIL, %g2       ! restore PIL after handler_irq
248         wr      %g2, PSR_ET, %psr       ! keep ET up
249         WRITE_PAUSE
251         RESTORE_ALL
253 #ifdef CONFIG_SMP
254         /* SMP per-cpu ticker interrupts are handled specially. */
255 smp4m_ticker:
256         bne     real_irq_continue+4
257          or     %l0, PSR_PIL, %g2
258         wr      %g2, 0x0, %psr
259         WRITE_PAUSE
260         wr      %g2, PSR_ET, %psr
261         WRITE_PAUSE
262         call    smp4m_percpu_timer_interrupt
263          add    %sp, STACKFRAME_SZ, %o0
264         wr      %l0, PSR_ET, %psr
265         WRITE_PAUSE
266         RESTORE_ALL
268         /* Here is where we check for possible SMP IPI passed to us
269          * on some level other than 15 which is the NMI and only used
270          * for cross calls.  That has a separate entry point below.
271          *
272          * IPIs are sent on Level 12, 13 and 14. See IRQ_IPI_*.
273          */
274 maybe_smp4m_msg:
275         GET_PROCESSOR4M_ID(o3)
276         sethi   %hi(sun4m_irq_percpu), %l5
277         sll     %o3, 2, %o3
278         or      %l5, %lo(sun4m_irq_percpu), %o5
279         sethi   %hi(0x70000000), %o2    ! Check all soft-IRQs
280         ld      [%o5 + %o3], %o1
281         ld      [%o1 + 0x00], %o3       ! sun4m_irq_percpu[cpu]->pending
282         andcc   %o3, %o2, %g0
283         be,a    smp4m_ticker
284          cmp    %l7, 14
285         /* Soft-IRQ IPI */
286         st      %o2, [%o1 + 0x04]       ! sun4m_irq_percpu[cpu]->clear=0x70000000
287         WRITE_PAUSE
288         ld      [%o1 + 0x00], %g0       ! sun4m_irq_percpu[cpu]->pending
289         WRITE_PAUSE
290         or      %l0, PSR_PIL, %l4
291         wr      %l4, 0x0, %psr
292         WRITE_PAUSE
293         wr      %l4, PSR_ET, %psr
294         WRITE_PAUSE
295         srl     %o3, 28, %o2            ! shift for simpler checks below
296 maybe_smp4m_msg_check_single:
297         andcc   %o2, 0x1, %g0
298         beq,a   maybe_smp4m_msg_check_mask
299          andcc  %o2, 0x2, %g0
300         call    smp_call_function_single_interrupt
301          nop
302         andcc   %o2, 0x2, %g0
303 maybe_smp4m_msg_check_mask:
304         beq,a   maybe_smp4m_msg_check_resched
305          andcc  %o2, 0x4, %g0
306         call    smp_call_function_interrupt
307          nop
308         andcc   %o2, 0x4, %g0
309 maybe_smp4m_msg_check_resched:
310         /* rescheduling is done in RESTORE_ALL regardless, but incr stats */
311         beq,a   maybe_smp4m_msg_out
312          nop
313         call    smp_resched_interrupt
314          nop
315 maybe_smp4m_msg_out:
316         RESTORE_ALL
318         .align  4
319         .globl  linux_trap_ipi15
320 linux_trap_ipi15:
321         SAVE_ALL
322         sethi   %hi(0x80000000), %o2
323         GET_PROCESSOR4M_ID(o0)
324         sethi   %hi(sun4m_irq_percpu), %l5
325         or      %l5, %lo(sun4m_irq_percpu), %o5
326         sll     %o0, 2, %o0
327         ld      [%o5 + %o0], %o5
328         ld      [%o5 + 0x00], %o3       ! sun4m_irq_percpu[cpu]->pending
329         andcc   %o3, %o2, %g0
330         be      1f                      ! Must be an NMI async memory error
331          st     %o2, [%o5 + 0x04]       ! sun4m_irq_percpu[cpu]->clear=0x80000000
332         WRITE_PAUSE
333         ld      [%o5 + 0x00], %g0       ! sun4m_irq_percpu[cpu]->pending
334         WRITE_PAUSE
335         or      %l0, PSR_PIL, %l4
336         wr      %l4, 0x0, %psr
337         WRITE_PAUSE
338         wr      %l4, PSR_ET, %psr
339         WRITE_PAUSE
340         call    smp4m_cross_call_irq
341          nop
342         b       ret_trap_lockless_ipi
343          clr    %l6
345         /* NMI async memory error handling. */
346         sethi   %hi(0x80000000), %l4
347         sethi   %hi(sun4m_irq_global), %o5
348         ld      [%o5 + %lo(sun4m_irq_global)], %l5
349         st      %l4, [%l5 + 0x0c]       ! sun4m_irq_global->mask_set=0x80000000
350         WRITE_PAUSE
351         ld      [%l5 + 0x00], %g0       ! sun4m_irq_global->pending
352         WRITE_PAUSE
353         or      %l0, PSR_PIL, %l4
354         wr      %l4, 0x0, %psr
355         WRITE_PAUSE
356         wr      %l4, PSR_ET, %psr
357         WRITE_PAUSE
358         call    sun4m_nmi
359          nop
360         st      %l4, [%l5 + 0x08]       ! sun4m_irq_global->mask_clear=0x80000000
361         WRITE_PAUSE
362         ld      [%l5 + 0x00], %g0       ! sun4m_irq_global->pending
363         WRITE_PAUSE
364         RESTORE_ALL
366         .globl  smp4d_ticker
367         /* SMP per-cpu ticker interrupts are handled specially. */
368 smp4d_ticker:
369         SAVE_ALL
370         or      %l0, PSR_PIL, %g2
371         sethi   %hi(CC_ICLR), %o0
372         sethi   %hi(1 << 14), %o1
373         or      %o0, %lo(CC_ICLR), %o0
374         stha    %o1, [%o0] ASI_M_MXCC   /* Clear PIL 14 in MXCC's ICLR */
375         wr      %g2, 0x0, %psr
376         WRITE_PAUSE
377         wr      %g2, PSR_ET, %psr
378         WRITE_PAUSE
379         call    smp4d_percpu_timer_interrupt
380          add    %sp, STACKFRAME_SZ, %o0
381         wr      %l0, PSR_ET, %psr
382         WRITE_PAUSE
383         RESTORE_ALL
385         .align  4
386         .globl  linux_trap_ipi15_sun4d
387 linux_trap_ipi15_sun4d:
388         SAVE_ALL
389         sethi   %hi(CC_BASE), %o4
390         sethi   %hi(MXCC_ERR_ME|MXCC_ERR_PEW|MXCC_ERR_ASE|MXCC_ERR_PEE), %o2
391         or      %o4, (CC_EREG - CC_BASE), %o0
392         ldda    [%o0] ASI_M_MXCC, %o0
393         andcc   %o0, %o2, %g0
394         bne     1f
395          sethi  %hi(BB_STAT2), %o2
396         lduba   [%o2] ASI_M_CTL, %o2
397         andcc   %o2, BB_STAT2_MASK, %g0
398         bne     2f
399          or     %o4, (CC_ICLR - CC_BASE), %o0
400         sethi   %hi(1 << 15), %o1
401         stha    %o1, [%o0] ASI_M_MXCC   /* Clear PIL 15 in MXCC's ICLR */
402         or      %l0, PSR_PIL, %l4
403         wr      %l4, 0x0, %psr
404         WRITE_PAUSE
405         wr      %l4, PSR_ET, %psr
406         WRITE_PAUSE
407         call    smp4d_cross_call_irq
408          nop
409         b       ret_trap_lockless_ipi
410          clr    %l6
412 1:      /* MXCC error */
413 2:      /* BB error */
414         /* Disable PIL 15 */
415         set     CC_IMSK, %l4
416         lduha   [%l4] ASI_M_MXCC, %l5
417         sethi   %hi(1 << 15), %l7
418         or      %l5, %l7, %l5
419         stha    %l5, [%l4] ASI_M_MXCC
420         /* FIXME */
421 1:      b,a     1b
423 #ifdef CONFIG_SPARC_LEON
424         .globl  smpleon_ipi
425         .extern leon_ipi_interrupt
426         /* SMP per-cpu IPI interrupts are handled specially. */
427 smpleon_ipi:
428         SAVE_ALL
429         or      %l0, PSR_PIL, %g2
430         wr      %g2, 0x0, %psr
431         WRITE_PAUSE
432         wr      %g2, PSR_ET, %psr
433         WRITE_PAUSE
434         call    leonsmp_ipi_interrupt
435          add    %sp, STACKFRAME_SZ, %o1 ! pt_regs
436         wr      %l0, PSR_ET, %psr
437         WRITE_PAUSE
438         RESTORE_ALL
440         .align  4
441         .globl  linux_trap_ipi15_leon
442 linux_trap_ipi15_leon:
443         SAVE_ALL
444         or      %l0, PSR_PIL, %l4
445         wr      %l4, 0x0, %psr
446         WRITE_PAUSE
447         wr      %l4, PSR_ET, %psr
448         WRITE_PAUSE
449         call    leon_cross_call_irq
450          nop
451         b       ret_trap_lockless_ipi
452          clr    %l6
454 #endif /* CONFIG_SPARC_LEON */
456 #endif /* CONFIG_SMP */
458         /* This routine handles illegal instructions and privileged
459          * instruction attempts from user code.
460          */
461         .align  4
462         .globl  bad_instruction
463 bad_instruction:
464         sethi   %hi(0xc1f80000), %l4
465         ld      [%l1], %l5
466         sethi   %hi(0x81d80000), %l7
467         and     %l5, %l4, %l5
468         cmp     %l5, %l7
469         be      1f
470         SAVE_ALL
472         wr      %l0, PSR_ET, %psr               ! re-enable traps
473         WRITE_PAUSE
475         add     %sp, STACKFRAME_SZ, %o0
476         mov     %l1, %o1
477         mov     %l2, %o2
478         call    do_illegal_instruction
479          mov    %l0, %o3
481         RESTORE_ALL
483 1:      /* unimplemented flush - just skip */
484         jmpl    %l2, %g0
485          rett   %l2 + 4
487         .align  4
488         .globl  priv_instruction
489 priv_instruction:
490         SAVE_ALL
492         wr      %l0, PSR_ET, %psr
493         WRITE_PAUSE
495         add     %sp, STACKFRAME_SZ, %o0
496         mov     %l1, %o1
497         mov     %l2, %o2
498         call    do_priv_instruction
499          mov    %l0, %o3
501         RESTORE_ALL
503         /* This routine handles unaligned data accesses. */
504         .align  4
505         .globl  mna_handler
506 mna_handler:
507         andcc   %l0, PSR_PS, %g0
508         be      mna_fromuser
509          nop
511         SAVE_ALL
513         wr      %l0, PSR_ET, %psr
514         WRITE_PAUSE
516         ld      [%l1], %o1
517         call    kernel_unaligned_trap
518          add    %sp, STACKFRAME_SZ, %o0
520         RESTORE_ALL
522 mna_fromuser:
523         SAVE_ALL
525         wr      %l0, PSR_ET, %psr               ! re-enable traps
526         WRITE_PAUSE
528         ld      [%l1], %o1
529         call    user_unaligned_trap
530          add    %sp, STACKFRAME_SZ, %o0
532         RESTORE_ALL
534         /* This routine handles floating point disabled traps. */
535         .align  4
536         .globl  fpd_trap_handler
537 fpd_trap_handler:
538         SAVE_ALL
540         wr      %l0, PSR_ET, %psr               ! re-enable traps
541         WRITE_PAUSE
543         add     %sp, STACKFRAME_SZ, %o0
544         mov     %l1, %o1
545         mov     %l2, %o2
546         call    do_fpd_trap
547          mov    %l0, %o3
549         RESTORE_ALL
551         /* This routine handles Floating Point Exceptions. */
552         .align  4
553         .globl  fpe_trap_handler
554 fpe_trap_handler:
555         set     fpsave_magic, %l5
556         cmp     %l1, %l5
557         be      1f
558          sethi  %hi(fpsave), %l5
559         or      %l5, %lo(fpsave), %l5
560         cmp     %l1, %l5
561         bne     2f
562          sethi  %hi(fpsave_catch2), %l5
563         or      %l5, %lo(fpsave_catch2), %l5
564         wr      %l0, 0x0, %psr
565         WRITE_PAUSE
566         jmp     %l5
567          rett   %l5 + 4
568 1:      
569         sethi   %hi(fpsave_catch), %l5
570         or      %l5, %lo(fpsave_catch), %l5
571         wr      %l0, 0x0, %psr
572         WRITE_PAUSE
573         jmp     %l5
574          rett   %l5 + 4
577         SAVE_ALL
579         wr      %l0, PSR_ET, %psr               ! re-enable traps
580         WRITE_PAUSE
582         add     %sp, STACKFRAME_SZ, %o0
583         mov     %l1, %o1
584         mov     %l2, %o2
585         call    do_fpe_trap
586          mov    %l0, %o3
588         RESTORE_ALL
590         /* This routine handles Tag Overflow Exceptions. */
591         .align  4
592         .globl  do_tag_overflow
593 do_tag_overflow:
594         SAVE_ALL
596         wr      %l0, PSR_ET, %psr               ! re-enable traps
597         WRITE_PAUSE
599         add     %sp, STACKFRAME_SZ, %o0
600         mov     %l1, %o1
601         mov     %l2, %o2
602         call    handle_tag_overflow
603          mov    %l0, %o3
605         RESTORE_ALL
607         /* This routine handles Watchpoint Exceptions. */
608         .align  4
609         .globl  do_watchpoint
610 do_watchpoint:
611         SAVE_ALL
613         wr      %l0, PSR_ET, %psr               ! re-enable traps
614         WRITE_PAUSE
616         add     %sp, STACKFRAME_SZ, %o0
617         mov     %l1, %o1
618         mov     %l2, %o2
619         call    handle_watchpoint
620          mov    %l0, %o3
622         RESTORE_ALL
624         /* This routine handles Register Access Exceptions. */
625         .align  4
626         .globl  do_reg_access
627 do_reg_access:
628         SAVE_ALL
630         wr      %l0, PSR_ET, %psr               ! re-enable traps
631         WRITE_PAUSE
633         add     %sp, STACKFRAME_SZ, %o0
634         mov     %l1, %o1
635         mov     %l2, %o2
636         call    handle_reg_access
637          mov    %l0, %o3
639         RESTORE_ALL
641         /* This routine handles Co-Processor Disabled Exceptions. */
642         .align  4
643         .globl  do_cp_disabled
644 do_cp_disabled:
645         SAVE_ALL
647         wr      %l0, PSR_ET, %psr               ! re-enable traps
648         WRITE_PAUSE
650         add     %sp, STACKFRAME_SZ, %o0
651         mov     %l1, %o1
652         mov     %l2, %o2
653         call    handle_cp_disabled
654          mov    %l0, %o3
656         RESTORE_ALL
658         /* This routine handles Co-Processor Exceptions. */
659         .align  4
660         .globl  do_cp_exception
661 do_cp_exception:
662         SAVE_ALL
664         wr      %l0, PSR_ET, %psr               ! re-enable traps
665         WRITE_PAUSE
667         add     %sp, STACKFRAME_SZ, %o0
668         mov     %l1, %o1
669         mov     %l2, %o2
670         call    handle_cp_exception
671          mov    %l0, %o3
673         RESTORE_ALL
675         /* This routine handles Hardware Divide By Zero Exceptions. */
676         .align  4
677         .globl  do_hw_divzero
678 do_hw_divzero:
679         SAVE_ALL
681         wr      %l0, PSR_ET, %psr               ! re-enable traps
682         WRITE_PAUSE
684         add     %sp, STACKFRAME_SZ, %o0
685         mov     %l1, %o1
686         mov     %l2, %o2
687         call    handle_hw_divzero
688          mov    %l0, %o3
690         RESTORE_ALL
692         .align  4
693         .globl  do_flush_windows
694 do_flush_windows:
695         SAVE_ALL
697         wr      %l0, PSR_ET, %psr
698         WRITE_PAUSE
700         andcc   %l0, PSR_PS, %g0
701         bne     dfw_kernel
702          nop
704         call    flush_user_windows
705          nop
707         /* Advance over the trap instruction. */
708         ld      [%sp + STACKFRAME_SZ + PT_NPC], %l1
709         add     %l1, 0x4, %l2
710         st      %l1, [%sp + STACKFRAME_SZ + PT_PC]
711         st      %l2, [%sp + STACKFRAME_SZ + PT_NPC]
713         RESTORE_ALL
715         .globl  flush_patch_one
717         /* We get these for debugging routines using __builtin_return_address() */
718 dfw_kernel:
719 flush_patch_one:
720         FLUSH_ALL_KERNEL_WINDOWS
722         /* Advance over the trap instruction. */
723         ld      [%sp + STACKFRAME_SZ + PT_NPC], %l1
724         add     %l1, 0x4, %l2
725         st      %l1, [%sp + STACKFRAME_SZ + PT_PC]
726         st      %l2, [%sp + STACKFRAME_SZ + PT_NPC]
728         RESTORE_ALL
730         /* The getcc software trap.  The user wants the condition codes from
731          * the %psr in register %g1.
732          */
734         .align  4
735         .globl  getcc_trap_handler
736 getcc_trap_handler:
737         srl     %l0, 20, %g1    ! give user
738         and     %g1, 0xf, %g1   ! only ICC bits in %psr
739         jmp     %l2             ! advance over trap instruction
740         rett    %l2 + 0x4       ! like this...
742         /* The setcc software trap.  The user has condition codes in %g1
743          * that it would like placed in the %psr.  Be careful not to flip
744          * any unintentional bits!
745          */
747         .align  4
748         .globl  setcc_trap_handler
749 setcc_trap_handler:
750         sll     %g1, 0x14, %l4
751         set     PSR_ICC, %l5
752         andn    %l0, %l5, %l0   ! clear ICC bits in %psr
753         and     %l4, %l5, %l4   ! clear non-ICC bits in user value
754         or      %l4, %l0, %l4   ! or them in... mix mix mix
756         wr      %l4, 0x0, %psr  ! set new %psr
757         WRITE_PAUSE             ! TI scumbags...
759         jmp     %l2             ! advance over trap instruction
760         rett    %l2 + 0x4       ! like this...
762 #ifndef CONFIG_SMP
763         .align  4
764         .globl  linux_trap_ipi15
765 linux_trap_ipi15:
766         SAVE_ALL
768         /* Now it is safe to re-enable traps without recursion. */
769         or      %l0, PSR_PIL, %l0
770         wr      %l0, PSR_ET, %psr
771         WRITE_PAUSE
773         /* Now call the c-code with the pt_regs frame ptr and the
774          * memory error registers as arguments.  The ordering chosen
775          * here is due to unlatching semantics.
776          */
777         sethi   %hi(AC_SYNC_ERR), %o0
778         add     %o0, 0x4, %o0
779         lda     [%o0] ASI_CONTROL, %o2  ! sync vaddr
780         sub     %o0, 0x4, %o0
781         lda     [%o0] ASI_CONTROL, %o1  ! sync error
782         add     %o0, 0xc, %o0
783         lda     [%o0] ASI_CONTROL, %o4  ! async vaddr
784         sub     %o0, 0x4, %o0
785         lda     [%o0] ASI_CONTROL, %o3  ! async error
786         call    sparc_lvl15_nmi
787          add    %sp, STACKFRAME_SZ, %o0
789         RESTORE_ALL
791 #endif /* CONFIG_SMP */
793         .align  4
794         .globl  invalid_segment_patch1_ff
795         .globl  invalid_segment_patch2_ff
796 invalid_segment_patch1_ff:      cmp     %l4, 0xff
797 invalid_segment_patch2_ff:      mov     0xff, %l3
799         .align  4
800         .globl  invalid_segment_patch1_1ff
801         .globl  invalid_segment_patch2_1ff
802 invalid_segment_patch1_1ff:     cmp     %l4, 0x1ff
803 invalid_segment_patch2_1ff:     mov     0x1ff, %l3
805         .align  4
806         .globl  num_context_patch1_16, num_context_patch2_16
807 num_context_patch1_16:          mov     0x10, %l7
808 num_context_patch2_16:          mov     0x10, %l7
810         .align  4
811         .globl  vac_linesize_patch_32
812 vac_linesize_patch_32:          subcc   %l7, 32, %l7
814         .align  4
815         .globl  vac_hwflush_patch1_on, vac_hwflush_patch2_on
818  * Ugly, but we can't use hardware flushing on the sun4 and we'd require
819  * two instructions (Anton)
820  */
821 vac_hwflush_patch1_on:          addcc   %l7, -PAGE_SIZE, %l7
823 vac_hwflush_patch2_on:          sta     %g0, [%l3 + %l7] ASI_HWFLUSHSEG
825         .globl  invalid_segment_patch1, invalid_segment_patch2
826         .globl  num_context_patch1
827         .globl  vac_linesize_patch, vac_hwflush_patch1
828         .globl  vac_hwflush_patch2
830         .align  4
831         .globl  srmmu_fault
832 srmmu_fault:
833         mov     0x400, %l5
834         mov     0x300, %l4
836         lda     [%l5] ASI_M_MMUREGS, %l6        ! read sfar first
837         lda     [%l4] ASI_M_MMUREGS, %l5        ! read sfsr last
839         andn    %l6, 0xfff, %l6
840         srl     %l5, 6, %l5                     ! and encode all info into l7
842         and     %l5, 2, %l5
843         or      %l5, %l6, %l6
845         or      %l6, %l7, %l7                   ! l7 = [addr,write,txtfault]
847         SAVE_ALL
849         mov     %l7, %o1
850         mov     %l7, %o2
851         and     %o1, 1, %o1             ! arg2 = text_faultp
852         mov     %l7, %o3
853         and     %o2, 2, %o2             ! arg3 = writep
854         andn    %o3, 0xfff, %o3         ! arg4 = faulting address
856         wr      %l0, PSR_ET, %psr
857         WRITE_PAUSE
859         call    do_sparc_fault
860          add    %sp, STACKFRAME_SZ, %o0 ! arg1 = pt_regs ptr
862         RESTORE_ALL
864         .align  4
865         .globl  sys_nis_syscall
866 sys_nis_syscall:
867         mov     %o7, %l5
868         add     %sp, STACKFRAME_SZ, %o0         ! pt_regs *regs arg
869         call    c_sys_nis_syscall
870          mov    %l5, %o7
872         .align  4
873         .globl  sys_execve
874 sys_execve:
875         mov     %o7, %l5
876         add     %sp, STACKFRAME_SZ, %o0         ! pt_regs *regs arg
877         call    sparc_execve
878          mov    %l5, %o7
880         .globl  sunos_execv
881 sunos_execv:
882         st      %g0, [%sp + STACKFRAME_SZ + PT_I2]
884         call    sparc_execve
885          add    %sp, STACKFRAME_SZ, %o0
887         b       ret_sys_call
888          ld     [%sp + STACKFRAME_SZ + PT_I0], %o0
890         .align  4
891         .globl  sys_sparc_pipe
892 sys_sparc_pipe:
893         mov     %o7, %l5
894         add     %sp, STACKFRAME_SZ, %o0         ! pt_regs *regs arg
895         call    sparc_pipe
896          mov    %l5, %o7
898         .align  4
899         .globl  sys_sigaltstack
900 sys_sigaltstack:
901         mov     %o7, %l5
902         mov     %fp, %o2
903         call    do_sigaltstack
904          mov    %l5, %o7
906         .align  4
907         .globl  sys_sigstack
908 sys_sigstack:
909         mov     %o7, %l5
910         mov     %fp, %o2
911         call    do_sys_sigstack
912          mov    %l5, %o7
914         .align  4
915         .globl  sys_sigreturn
916 sys_sigreturn:
917         call    do_sigreturn
918          add    %sp, STACKFRAME_SZ, %o0
920         ld      [%curptr + TI_FLAGS], %l5
921         andcc   %l5, _TIF_SYSCALL_TRACE, %g0
922         be      1f
923          nop
925         call    syscall_trace
926          nop
929         /* We don't want to muck with user registers like a
930          * normal syscall, just return.
931          */
932         RESTORE_ALL
934         .align  4
935         .globl  sys_rt_sigreturn
936 sys_rt_sigreturn:
937         call    do_rt_sigreturn
938          add    %sp, STACKFRAME_SZ, %o0
940         ld      [%curptr + TI_FLAGS], %l5
941         andcc   %l5, _TIF_SYSCALL_TRACE, %g0
942         be      1f
943          nop
945         add     %sp, STACKFRAME_SZ, %o0
946         call    syscall_trace
947          mov    1, %o1
950         /* We are returning to a signal handler. */
951         RESTORE_ALL
953         /* Now that we have a real sys_clone, sys_fork() is
954          * implemented in terms of it.  Our _real_ implementation
955          * of SunOS vfork() will use sys_vfork().
956          *
957          * XXX These three should be consolidated into mostly shared
958          * XXX code just like on sparc64... -DaveM
959          */
960         .align  4
961         .globl  sys_fork, flush_patch_two
962 sys_fork:
963         mov     %o7, %l5
964 flush_patch_two:
965         FLUSH_ALL_KERNEL_WINDOWS;
966         ld      [%curptr + TI_TASK], %o4
967         rd      %psr, %g4
968         WRITE_PAUSE
969         mov     SIGCHLD, %o0                    ! arg0: clone flags
970         rd      %wim, %g5
971         WRITE_PAUSE
972         mov     %fp, %o1                        ! arg1: usp
973         std     %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
974         add     %sp, STACKFRAME_SZ, %o2         ! arg2: pt_regs ptr
975         mov     0, %o3
976         call    sparc_do_fork
977          mov    %l5, %o7
979         /* Whee, kernel threads! */
980         .globl  sys_clone, flush_patch_three
981 sys_clone:
982         mov     %o7, %l5
983 flush_patch_three:
984         FLUSH_ALL_KERNEL_WINDOWS;
985         ld      [%curptr + TI_TASK], %o4
986         rd      %psr, %g4
987         WRITE_PAUSE
989         /* arg0,1: flags,usp  -- loaded already */
990         cmp     %o1, 0x0                        ! Is new_usp NULL?
991         rd      %wim, %g5
992         WRITE_PAUSE
993         be,a    1f
994          mov    %fp, %o1                        ! yes, use callers usp
995         andn    %o1, 7, %o1                     ! no, align to 8 bytes
997         std     %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
998         add     %sp, STACKFRAME_SZ, %o2         ! arg2: pt_regs ptr
999         mov     0, %o3
1000         call    sparc_do_fork
1001          mov    %l5, %o7
1003         /* Whee, real vfork! */
1004         .globl  sys_vfork, flush_patch_four
1005 sys_vfork:
1006 flush_patch_four:
1007         FLUSH_ALL_KERNEL_WINDOWS;
1008         ld      [%curptr + TI_TASK], %o4
1009         rd      %psr, %g4
1010         WRITE_PAUSE
1011         rd      %wim, %g5
1012         WRITE_PAUSE
1013         std     %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr]
1014         sethi   %hi(0x4000 | 0x0100 | SIGCHLD), %o0
1015         mov     %fp, %o1
1016         or      %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
1017         sethi   %hi(sparc_do_fork), %l1
1018         mov     0, %o3
1019         jmpl    %l1 + %lo(sparc_do_fork), %g0
1020          add    %sp, STACKFRAME_SZ, %o2
1022         .align  4
1023 linux_sparc_ni_syscall:
1024         sethi   %hi(sys_ni_syscall), %l7
1025         b       syscall_is_too_hard
1026          or     %l7, %lo(sys_ni_syscall), %l7
1028 linux_fast_syscall:
1029         andn    %l7, 3, %l7
1030         mov     %i0, %o0
1031         mov     %i1, %o1
1032         mov     %i2, %o2
1033         jmpl    %l7 + %g0, %g0
1034          mov    %i3, %o3
1036 linux_syscall_trace:
1037         add     %sp, STACKFRAME_SZ, %o0
1038         call    syscall_trace
1039          mov    0, %o1
1040         cmp     %o0, 0
1041         bne     3f
1042          mov    -ENOSYS, %o0
1043         mov     %i0, %o0
1044         mov     %i1, %o1
1045         mov     %i2, %o2
1046         mov     %i3, %o3
1047         b       2f
1048          mov    %i4, %o4
1050         .globl  ret_from_fork
1051 ret_from_fork:
1052         call    schedule_tail
1053          ld     [%g3 + TI_TASK], %o0
1054         b       ret_sys_call
1055          ld     [%sp + STACKFRAME_SZ + PT_I0], %o0
1057         /* Linux native system calls enter here... */
1058         .align  4
1059         .globl  linux_sparc_syscall
1060 linux_sparc_syscall:
1061         sethi   %hi(PSR_SYSCALL), %l4
1062         or      %l0, %l4, %l0
1063         /* Direct access to user regs, must faster. */
1064         cmp     %g1, NR_syscalls
1065         bgeu    linux_sparc_ni_syscall
1066          sll    %g1, 2, %l4
1067         ld      [%l7 + %l4], %l7
1068         andcc   %l7, 1, %g0
1069         bne     linux_fast_syscall
1070          /* Just do first insn from SAVE_ALL in the delay slot */
1072 syscall_is_too_hard:
1073         SAVE_ALL_HEAD
1074          rd     %wim, %l3
1076         wr      %l0, PSR_ET, %psr
1077         mov     %i0, %o0
1078         mov     %i1, %o1
1079         mov     %i2, %o2
1081         ld      [%curptr + TI_FLAGS], %l5
1082         mov     %i3, %o3
1083         andcc   %l5, _TIF_SYSCALL_TRACE, %g0
1084         mov     %i4, %o4
1085         bne     linux_syscall_trace
1086          mov    %i0, %l5
1088         call    %l7
1089          mov    %i5, %o5
1092         st      %o0, [%sp + STACKFRAME_SZ + PT_I0]
1094 ret_sys_call:
1095         ld      [%curptr + TI_FLAGS], %l6
1096         cmp     %o0, -ERESTART_RESTARTBLOCK
1097         ld      [%sp + STACKFRAME_SZ + PT_PSR], %g3
1098         set     PSR_C, %g2
1099         bgeu    1f
1100          andcc  %l6, _TIF_SYSCALL_TRACE, %g0
1102         /* System call success, clear Carry condition code. */
1103         andn    %g3, %g2, %g3
1104         clr     %l6
1105         st      %g3, [%sp + STACKFRAME_SZ + PT_PSR]     
1106         bne     linux_syscall_trace2
1107          ld     [%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */
1108         add     %l1, 0x4, %l2                   /* npc = npc+4 */
1109         st      %l1, [%sp + STACKFRAME_SZ + PT_PC]
1110         b       ret_trap_entry
1111          st     %l2, [%sp + STACKFRAME_SZ + PT_NPC]
1113         /* System call failure, set Carry condition code.
1114          * Also, get abs(errno) to return to the process.
1115          */
1116         sub     %g0, %o0, %o0
1117         or      %g3, %g2, %g3
1118         st      %o0, [%sp + STACKFRAME_SZ + PT_I0]
1119         mov     1, %l6
1120         st      %g3, [%sp + STACKFRAME_SZ + PT_PSR]
1121         bne     linux_syscall_trace2
1122          ld     [%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */
1123         add     %l1, 0x4, %l2                   /* npc = npc+4 */
1124         st      %l1, [%sp + STACKFRAME_SZ + PT_PC]
1125         b       ret_trap_entry
1126          st     %l2, [%sp + STACKFRAME_SZ + PT_NPC]
1128 linux_syscall_trace2:
1129         add     %sp, STACKFRAME_SZ, %o0
1130         mov     1, %o1
1131         call    syscall_trace
1132          add    %l1, 0x4, %l2                   /* npc = npc+4 */
1133         st      %l1, [%sp + STACKFRAME_SZ + PT_PC]
1134         b       ret_trap_entry
1135          st     %l2, [%sp + STACKFRAME_SZ + PT_NPC]
1138 /* Saving and restoring the FPU state is best done from lowlevel code.
1140  * void fpsave(unsigned long *fpregs, unsigned long *fsr,
1141  *             void *fpqueue, unsigned long *fpqdepth)
1142  */
1144         .globl  fpsave
1145 fpsave:
1146         st      %fsr, [%o1]     ! this can trap on us if fpu is in bogon state
1147         ld      [%o1], %g1
1148         set     0x2000, %g4
1149         andcc   %g1, %g4, %g0
1150         be      2f
1151          mov    0, %g2
1153         /* We have an fpqueue to save. */
1155         std     %fq, [%o2]
1156 fpsave_magic:
1157         st      %fsr, [%o1]
1158         ld      [%o1], %g3
1159         andcc   %g3, %g4, %g0
1160         add     %g2, 1, %g2
1161         bne     1b
1162          add    %o2, 8, %o2
1165         st      %g2, [%o3]
1167         std     %f0, [%o0 + 0x00]
1168         std     %f2, [%o0 + 0x08]
1169         std     %f4, [%o0 + 0x10]
1170         std     %f6, [%o0 + 0x18]
1171         std     %f8, [%o0 + 0x20]
1172         std     %f10, [%o0 + 0x28]
1173         std     %f12, [%o0 + 0x30]
1174         std     %f14, [%o0 + 0x38]
1175         std     %f16, [%o0 + 0x40]
1176         std     %f18, [%o0 + 0x48]
1177         std     %f20, [%o0 + 0x50]
1178         std     %f22, [%o0 + 0x58]
1179         std     %f24, [%o0 + 0x60]
1180         std     %f26, [%o0 + 0x68]
1181         std     %f28, [%o0 + 0x70]
1182         retl
1183          std    %f30, [%o0 + 0x78]
1185         /* Thanks for Theo Deraadt and the authors of the Sprite/netbsd/openbsd
1186          * code for pointing out this possible deadlock, while we save state
1187          * above we could trap on the fsr store so our low level fpu trap
1188          * code has to know how to deal with this.
1189          */
1190 fpsave_catch:
1191         b       fpsave_magic + 4
1192          st     %fsr, [%o1]
1194 fpsave_catch2:
1195         b       fpsave + 4
1196          st     %fsr, [%o1]
1198         /* void fpload(unsigned long *fpregs, unsigned long *fsr); */
1200         .globl  fpload
1201 fpload:
1202         ldd     [%o0 + 0x00], %f0
1203         ldd     [%o0 + 0x08], %f2
1204         ldd     [%o0 + 0x10], %f4
1205         ldd     [%o0 + 0x18], %f6
1206         ldd     [%o0 + 0x20], %f8
1207         ldd     [%o0 + 0x28], %f10
1208         ldd     [%o0 + 0x30], %f12
1209         ldd     [%o0 + 0x38], %f14
1210         ldd     [%o0 + 0x40], %f16
1211         ldd     [%o0 + 0x48], %f18
1212         ldd     [%o0 + 0x50], %f20
1213         ldd     [%o0 + 0x58], %f22
1214         ldd     [%o0 + 0x60], %f24
1215         ldd     [%o0 + 0x68], %f26
1216         ldd     [%o0 + 0x70], %f28
1217         ldd     [%o0 + 0x78], %f30
1218         ld      [%o1], %fsr
1219         retl
1220          nop
1222         /* __ndelay and __udelay take two arguments:
1223          * 0 - nsecs or usecs to delay
1224          * 1 - per_cpu udelay_val (loops per jiffy)
1225          *
1226          * Note that ndelay gives HZ times higher resolution but has a 10ms
1227          * limit.  udelay can handle up to 1s.
1228          */
1229         .globl  __ndelay
1230 __ndelay:
1231         save    %sp, -STACKFRAME_SZ, %sp
1232         mov     %i0, %o0
1233         call    .umul                   ! round multiplier up so large ns ok
1234          mov    0x1ae, %o1              ! 2**32 / (1 000 000 000 / HZ)
1235         call    .umul
1236          mov    %i1, %o1                ! udelay_val
1237         ba      delay_continue
1238          mov    %o1, %o0                ! >>32 later for better resolution
1240         .globl  __udelay
1241 __udelay:
1242         save    %sp, -STACKFRAME_SZ, %sp
1243         mov     %i0, %o0
1244         sethi   %hi(0x10c7), %o1        ! round multiplier up so large us ok
1245         call    .umul
1246          or     %o1, %lo(0x10c7), %o1   ! 2**32 / 1 000 000
1247         call    .umul
1248          mov    %i1, %o1                ! udelay_val
1249         sethi   %hi(0x028f4b62), %l0    ! Add in rounding constant * 2**32,
1250         or      %g0, %lo(0x028f4b62), %l0
1251         addcc   %o0, %l0, %o0           ! 2**32 * 0.009 999
1252         bcs,a   3f
1253          add    %o1, 0x01, %o1
1255         call    .umul
1256          mov    HZ, %o0                 ! >>32 earlier for wider range
1258 delay_continue:
1259         cmp     %o0, 0x0
1261         bne     1b
1262          subcc  %o0, 1, %o0
1263         
1264         ret
1265         restore
1267         /* Handle a software breakpoint */
1268         /* We have to inform parent that child has stopped */
1269         .align 4
1270         .globl breakpoint_trap
1271 breakpoint_trap:
1272         rd      %wim,%l3
1273         SAVE_ALL
1274         wr      %l0, PSR_ET, %psr
1275         WRITE_PAUSE
1277         st      %i0, [%sp + STACKFRAME_SZ + PT_G0] ! for restarting syscalls
1278         call    sparc_breakpoint
1279          add    %sp, STACKFRAME_SZ, %o0
1281         RESTORE_ALL
1283 #ifdef CONFIG_KGDB
1284         .align  4
1285         .globl  kgdb_trap_low
1286         .type   kgdb_trap_low,#function
1287 kgdb_trap_low:
1288         rd      %wim,%l3
1289         SAVE_ALL
1290         wr      %l0, PSR_ET, %psr
1291         WRITE_PAUSE
1293         call    kgdb_trap
1294          add    %sp, STACKFRAME_SZ, %o0
1296         RESTORE_ALL
1297         .size   kgdb_trap_low,.-kgdb_trap_low
1298 #endif
1300         .align  4
1301         .globl  flush_patch_exception
1302 flush_patch_exception:
1303         FLUSH_ALL_KERNEL_WINDOWS;
1304         ldd     [%o0], %o6
1305         jmpl    %o7 + 0xc, %g0                  ! see asm-sparc/processor.h
1306          mov    1, %g1                          ! signal EFAULT condition
1308         .align  4
1309         .globl  kill_user_windows, kuw_patch1_7win
1310         .globl  kuw_patch1
1311 kuw_patch1_7win:        sll     %o3, 6, %o3
1313         /* No matter how much overhead this routine has in the worst
1314          * case scenerio, it is several times better than taking the
1315          * traps with the old method of just doing flush_user_windows().
1316          */
1317 kill_user_windows:
1318         ld      [%g6 + TI_UWINMASK], %o0        ! get current umask
1319         orcc    %g0, %o0, %g0                   ! if no bits set, we are done
1320         be      3f                              ! nothing to do
1321          rd     %psr, %o5                       ! must clear interrupts
1322         or      %o5, PSR_PIL, %o4               ! or else that could change
1323         wr      %o4, 0x0, %psr                  ! the uwinmask state
1324         WRITE_PAUSE                             ! burn them cycles
1326         ld      [%g6 + TI_UWINMASK], %o0        ! get consistent state
1327         orcc    %g0, %o0, %g0                   ! did an interrupt come in?
1328         be      4f                              ! yep, we are done
1329          rd     %wim, %o3                       ! get current wim
1330         srl     %o3, 1, %o4                     ! simulate a save
1331 kuw_patch1:
1332         sll     %o3, 7, %o3                     ! compute next wim
1333         or      %o4, %o3, %o3                   ! result
1334         andncc  %o0, %o3, %o0                   ! clean this bit in umask
1335         bne     kuw_patch1                      ! not done yet
1336          srl    %o3, 1, %o4                     ! begin another save simulation
1337         wr      %o3, 0x0, %wim                  ! set the new wim
1338         st      %g0, [%g6 + TI_UWINMASK]        ! clear uwinmask
1340         wr      %o5, 0x0, %psr                  ! re-enable interrupts
1341         WRITE_PAUSE                             ! burn baby burn
1343         retl                                    ! return
1344          st     %g0, [%g6 + TI_W_SAVED]         ! no windows saved
1346         .align  4
1347         .globl  restore_current
1348 restore_current:
1349         LOAD_CURRENT(g6, o0)
1350         retl
1351          nop
1353 #ifdef CONFIG_PCIC_PCI
1354 #include <asm/pcic.h>
1356         .align  4
1357         .globl  linux_trap_ipi15_pcic
1358 linux_trap_ipi15_pcic:
1359         rd      %wim, %l3
1360         SAVE_ALL
1362         /*
1363          * First deactivate NMI
1364          * or we cannot drop ET, cannot get window spill traps.
1365          * The busy loop is necessary because the PIO error
1366          * sometimes does not go away quickly and we trap again.
1367          */
1368         sethi   %hi(pcic_regs), %o1
1369         ld      [%o1 + %lo(pcic_regs)], %o2
1371         ! Get pending status for printouts later.
1372         ld      [%o2 + PCI_SYS_INT_PENDING], %o0
1374         mov     PCI_SYS_INT_PENDING_CLEAR_ALL, %o1
1375         stb     %o1, [%o2 + PCI_SYS_INT_PENDING_CLEAR]
1377         ld      [%o2 + PCI_SYS_INT_PENDING], %o1
1378         andcc   %o1, ((PCI_SYS_INT_PENDING_PIO|PCI_SYS_INT_PENDING_PCI)>>24), %g0
1379         bne     1b
1380          nop
1382         or      %l0, PSR_PIL, %l4
1383         wr      %l4, 0x0, %psr
1384         WRITE_PAUSE
1385         wr      %l4, PSR_ET, %psr
1386         WRITE_PAUSE
1388         call    pcic_nmi
1389          add    %sp, STACKFRAME_SZ, %o1 ! struct pt_regs *regs
1390         RESTORE_ALL
1392         .globl  pcic_nmi_trap_patch
1393 pcic_nmi_trap_patch:
1394         sethi   %hi(linux_trap_ipi15_pcic), %l3
1395         jmpl    %l3 + %lo(linux_trap_ipi15_pcic), %g0
1396          rd     %psr, %l0
1397         .word   0
1399 #endif /* CONFIG_PCIC_PCI */
1401         .globl  flushw_all
1402 flushw_all:
1403         save    %sp, -0x40, %sp
1404         save    %sp, -0x40, %sp
1405         save    %sp, -0x40, %sp
1406         save    %sp, -0x40, %sp
1407         save    %sp, -0x40, %sp
1408         save    %sp, -0x40, %sp
1409         save    %sp, -0x40, %sp
1410         restore
1411         restore
1412         restore
1413         restore
1414         restore
1415         restore
1416         ret
1417          restore
1419 /* End of entry.S */