[SPARC64]: Use ASI_SCRATCHPAD address 0x0 properly.
[linux-2.6] / arch / sparc64 / kernel / entry.S
1 /* $Id: entry.S,v 1.144 2002/02/09 19:49:30 davem Exp $
2  * arch/sparc64/kernel/entry.S:  Sparc64 trap low-level entry points.
3  *
4  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
5  * Copyright (C) 1996 Eddie C. Dost        (ecd@skynet.be)
6  * Copyright (C) 1996 Miguel de Icaza      (miguel@nuclecu.unam.mx)
7  * Copyright (C) 1996,98,99 Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
8  */
9
10 #include <linux/config.h>
11 #include <linux/errno.h>
12
13 #include <asm/head.h>
14 #include <asm/asi.h>
15 #include <asm/smp.h>
16 #include <asm/ptrace.h>
17 #include <asm/page.h>
18 #include <asm/signal.h>
19 #include <asm/pgtable.h>
20 #include <asm/processor.h>
21 #include <asm/visasm.h>
22 #include <asm/estate.h>
23 #include <asm/auxio.h>
24 #include <asm/sfafsr.h>
25
26 #define curptr      g6
27
28 #define NR_SYSCALLS 300      /* Each OS is different... */
29
30         .text
31         .align          32
32
33         /* This is trivial with the new code... */
34         .globl          do_fpdis
35 do_fpdis:
36         sethi           %hi(TSTATE_PEF), %g4
37         rdpr            %tstate, %g5
38         andcc           %g5, %g4, %g0
39         be,pt           %xcc, 1f
40          nop
41         rd              %fprs, %g5
42         andcc           %g5, FPRS_FEF, %g0
43         be,pt           %xcc, 1f
44          nop
45
46         /* Legal state when DCR_IFPOE is set in Cheetah %dcr. */
47         sethi           %hi(109f), %g7
48         ba,pt           %xcc, etrap
49 109:     or             %g7, %lo(109b), %g7
50         add             %g0, %g0, %g0
51         ba,a,pt         %xcc, rtrap_clr_l6
52
53 1:      TRAP_LOAD_THREAD_REG(%g6, %g1)
54         ldub            [%g6 + TI_FPSAVED], %g5
55         wr              %g0, FPRS_FEF, %fprs
56         andcc           %g5, FPRS_FEF, %g0
57         be,a,pt         %icc, 1f
58          clr            %g7
59         ldx             [%g6 + TI_GSR], %g7
60 1:      andcc           %g5, FPRS_DL, %g0
61         bne,pn          %icc, 2f
62          fzero          %f0
63         andcc           %g5, FPRS_DU, %g0
64         bne,pn          %icc, 1f
65          fzero          %f2
66         faddd           %f0, %f2, %f4
67         fmuld           %f0, %f2, %f6
68         faddd           %f0, %f2, %f8
69         fmuld           %f0, %f2, %f10
70         faddd           %f0, %f2, %f12
71         fmuld           %f0, %f2, %f14
72         faddd           %f0, %f2, %f16
73         fmuld           %f0, %f2, %f18
74         faddd           %f0, %f2, %f20
75         fmuld           %f0, %f2, %f22
76         faddd           %f0, %f2, %f24
77         fmuld           %f0, %f2, %f26
78         faddd           %f0, %f2, %f28
79         fmuld           %f0, %f2, %f30
80         faddd           %f0, %f2, %f32
81         fmuld           %f0, %f2, %f34
82         faddd           %f0, %f2, %f36
83         fmuld           %f0, %f2, %f38
84         faddd           %f0, %f2, %f40
85         fmuld           %f0, %f2, %f42
86         faddd           %f0, %f2, %f44
87         fmuld           %f0, %f2, %f46
88         faddd           %f0, %f2, %f48
89         fmuld           %f0, %f2, %f50
90         faddd           %f0, %f2, %f52
91         fmuld           %f0, %f2, %f54
92         faddd           %f0, %f2, %f56
93         fmuld           %f0, %f2, %f58
94         b,pt            %xcc, fpdis_exit2
95          faddd          %f0, %f2, %f60
96 1:      mov             SECONDARY_CONTEXT, %g3
97         add             %g6, TI_FPREGS + 0x80, %g1
98         faddd           %f0, %f2, %f4
99         fmuld           %f0, %f2, %f6
100
101 661:    ldxa            [%g3] ASI_DMMU, %g5
102         .section        .sun4v_1insn_patch, "ax"
103         .word           661b
104         ldxa            [%g3] ASI_MMU, %g5
105         .previous
106
107         sethi           %hi(sparc64_kern_sec_context), %g2
108         ldx             [%g2 + %lo(sparc64_kern_sec_context)], %g2
109
110 661:    stxa            %g2, [%g3] ASI_DMMU
111         .section        .sun4v_1insn_patch, "ax"
112         .word           661b
113         stxa            %g2, [%g3] ASI_MMU
114         .previous
115
116         membar          #Sync
117         add             %g6, TI_FPREGS + 0xc0, %g2
118         faddd           %f0, %f2, %f8
119         fmuld           %f0, %f2, %f10
120         membar          #Sync
121         ldda            [%g1] ASI_BLK_S, %f32
122         ldda            [%g2] ASI_BLK_S, %f48
123         membar          #Sync
124         faddd           %f0, %f2, %f12
125         fmuld           %f0, %f2, %f14
126         faddd           %f0, %f2, %f16
127         fmuld           %f0, %f2, %f18
128         faddd           %f0, %f2, %f20
129         fmuld           %f0, %f2, %f22
130         faddd           %f0, %f2, %f24
131         fmuld           %f0, %f2, %f26
132         faddd           %f0, %f2, %f28
133         fmuld           %f0, %f2, %f30
134         b,pt            %xcc, fpdis_exit
135          nop
136 2:      andcc           %g5, FPRS_DU, %g0
137         bne,pt          %icc, 3f
138          fzero          %f32
139         mov             SECONDARY_CONTEXT, %g3
140         fzero           %f34
141
142 661:    ldxa            [%g3] ASI_DMMU, %g5
143         .section        .sun4v_1insn_patch, "ax"
144         .word           661b
145         ldxa            [%g3] ASI_MMU, %g5
146         .previous
147
148         add             %g6, TI_FPREGS, %g1
149         sethi           %hi(sparc64_kern_sec_context), %g2
150         ldx             [%g2 + %lo(sparc64_kern_sec_context)], %g2
151
152 661:    stxa            %g2, [%g3] ASI_DMMU
153         .section        .sun4v_1insn_patch, "ax"
154         .word           661b
155         stxa            %g2, [%g3] ASI_MMU
156         .previous
157
158         membar          #Sync
159         add             %g6, TI_FPREGS + 0x40, %g2
160         faddd           %f32, %f34, %f36
161         fmuld           %f32, %f34, %f38
162         membar          #Sync
163         ldda            [%g1] ASI_BLK_S, %f0
164         ldda            [%g2] ASI_BLK_S, %f16
165         membar          #Sync
166         faddd           %f32, %f34, %f40
167         fmuld           %f32, %f34, %f42
168         faddd           %f32, %f34, %f44
169         fmuld           %f32, %f34, %f46
170         faddd           %f32, %f34, %f48
171         fmuld           %f32, %f34, %f50
172         faddd           %f32, %f34, %f52
173         fmuld           %f32, %f34, %f54
174         faddd           %f32, %f34, %f56
175         fmuld           %f32, %f34, %f58
176         faddd           %f32, %f34, %f60
177         fmuld           %f32, %f34, %f62
178         ba,pt           %xcc, fpdis_exit
179          nop
180 3:      mov             SECONDARY_CONTEXT, %g3
181         add             %g6, TI_FPREGS, %g1
182
183 661:    ldxa            [%g3] ASI_DMMU, %g5
184         .section        .sun4v_1insn_patch, "ax"
185         .word           661b
186         ldxa            [%g3] ASI_MMU, %g5
187         .previous
188
189         sethi           %hi(sparc64_kern_sec_context), %g2
190         ldx             [%g2 + %lo(sparc64_kern_sec_context)], %g2
191
192 661:    stxa            %g2, [%g3] ASI_DMMU
193         .section        .sun4v_1insn_patch, "ax"
194         .word           661b
195         stxa            %g2, [%g3] ASI_MMU
196         .previous
197
198         membar          #Sync
199         mov             0x40, %g2
200         membar          #Sync
201         ldda            [%g1] ASI_BLK_S, %f0
202         ldda            [%g1 + %g2] ASI_BLK_S, %f16
203         add             %g1, 0x80, %g1
204         ldda            [%g1] ASI_BLK_S, %f32
205         ldda            [%g1 + %g2] ASI_BLK_S, %f48
206         membar          #Sync
207 fpdis_exit:
208
209 661:    stxa            %g5, [%g3] ASI_DMMU
210         .section        .sun4v_1insn_patch, "ax"
211         .word           661b
212         stxa            %g5, [%g3] ASI_MMU
213         .previous
214
215         membar          #Sync
216 fpdis_exit2:
217         wr              %g7, 0, %gsr
218         ldx             [%g6 + TI_XFSR], %fsr
219         rdpr            %tstate, %g3
220         or              %g3, %g4, %g3           ! anal...
221         wrpr            %g3, %tstate
222         wr              %g0, FPRS_FEF, %fprs    ! clean DU/DL bits
223         retry
224
225         .align          32
226 fp_other_bounce:
227         call            do_fpother
228          add            %sp, PTREGS_OFF, %o0
229         ba,pt           %xcc, rtrap
230          clr            %l6
231
232         .globl          do_fpother_check_fitos
233         .align          32
234 do_fpother_check_fitos:
235         TRAP_LOAD_THREAD_REG(%g6, %g1)
236         sethi           %hi(fp_other_bounce - 4), %g7
237         or              %g7, %lo(fp_other_bounce - 4), %g7
238
239         /* NOTE: Need to preserve %g7 until we fully commit
240          *       to the fitos fixup.
241          */
242         stx             %fsr, [%g6 + TI_XFSR]
243         rdpr            %tstate, %g3
244         andcc           %g3, TSTATE_PRIV, %g0
245         bne,pn          %xcc, do_fptrap_after_fsr
246          nop
247         ldx             [%g6 + TI_XFSR], %g3
248         srlx            %g3, 14, %g1
249         and             %g1, 7, %g1
250         cmp             %g1, 2                  ! Unfinished FP-OP
251         bne,pn          %xcc, do_fptrap_after_fsr
252          sethi          %hi(1 << 23), %g1       ! Inexact
253         andcc           %g3, %g1, %g0
254         bne,pn          %xcc, do_fptrap_after_fsr
255          rdpr           %tpc, %g1
256         lduwa           [%g1] ASI_AIUP, %g3     ! This cannot ever fail
257 #define FITOS_MASK      0xc1f83fe0
258 #define FITOS_COMPARE   0x81a01880
259         sethi           %hi(FITOS_MASK), %g1
260         or              %g1, %lo(FITOS_MASK), %g1
261         and             %g3, %g1, %g1
262         sethi           %hi(FITOS_COMPARE), %g2
263         or              %g2, %lo(FITOS_COMPARE), %g2
264         cmp             %g1, %g2
265         bne,pn          %xcc, do_fptrap_after_fsr
266          nop
267         std             %f62, [%g6 + TI_FPREGS + (62 * 4)]
268         sethi           %hi(fitos_table_1), %g1
269         and             %g3, 0x1f, %g2
270         or              %g1, %lo(fitos_table_1),  %g1
271         sllx            %g2, 2, %g2
272         jmpl            %g1 + %g2, %g0
273          ba,pt          %xcc, fitos_emul_continue
274
275 fitos_table_1:
276         fitod           %f0, %f62
277         fitod           %f1, %f62
278         fitod           %f2, %f62
279         fitod           %f3, %f62
280         fitod           %f4, %f62
281         fitod           %f5, %f62
282         fitod           %f6, %f62
283         fitod           %f7, %f62
284         fitod           %f8, %f62
285         fitod           %f9, %f62
286         fitod           %f10, %f62
287         fitod           %f11, %f62
288         fitod           %f12, %f62
289         fitod           %f13, %f62
290         fitod           %f14, %f62
291         fitod           %f15, %f62
292         fitod           %f16, %f62
293         fitod           %f17, %f62
294         fitod           %f18, %f62
295         fitod           %f19, %f62
296         fitod           %f20, %f62
297         fitod           %f21, %f62
298         fitod           %f22, %f62
299         fitod           %f23, %f62
300         fitod           %f24, %f62
301         fitod           %f25, %f62
302         fitod           %f26, %f62
303         fitod           %f27, %f62
304         fitod           %f28, %f62
305         fitod           %f29, %f62
306         fitod           %f30, %f62
307         fitod           %f31, %f62
308
309 fitos_emul_continue:
310         sethi           %hi(fitos_table_2), %g1
311         srl             %g3, 25, %g2
312         or              %g1, %lo(fitos_table_2), %g1
313         and             %g2, 0x1f, %g2
314         sllx            %g2, 2, %g2
315         jmpl            %g1 + %g2, %g0
316          ba,pt          %xcc, fitos_emul_fini
317
318 fitos_table_2:
319         fdtos           %f62, %f0
320         fdtos           %f62, %f1
321         fdtos           %f62, %f2
322         fdtos           %f62, %f3
323         fdtos           %f62, %f4
324         fdtos           %f62, %f5
325         fdtos           %f62, %f6
326         fdtos           %f62, %f7
327         fdtos           %f62, %f8
328         fdtos           %f62, %f9
329         fdtos           %f62, %f10
330         fdtos           %f62, %f11
331         fdtos           %f62, %f12
332         fdtos           %f62, %f13
333         fdtos           %f62, %f14
334         fdtos           %f62, %f15
335         fdtos           %f62, %f16
336         fdtos           %f62, %f17
337         fdtos           %f62, %f18
338         fdtos           %f62, %f19
339         fdtos           %f62, %f20
340         fdtos           %f62, %f21
341         fdtos           %f62, %f22
342         fdtos           %f62, %f23
343         fdtos           %f62, %f24
344         fdtos           %f62, %f25
345         fdtos           %f62, %f26
346         fdtos           %f62, %f27
347         fdtos           %f62, %f28
348         fdtos           %f62, %f29
349         fdtos           %f62, %f30
350         fdtos           %f62, %f31
351
352 fitos_emul_fini:
353         ldd             [%g6 + TI_FPREGS + (62 * 4)], %f62
354         done
355
356         .globl          do_fptrap
357         .align          32
358 do_fptrap:
359         stx             %fsr, [%g6 + TI_XFSR]
360 do_fptrap_after_fsr:
361         ldub            [%g6 + TI_FPSAVED], %g3
362         rd              %fprs, %g1
363         or              %g3, %g1, %g3
364         stb             %g3, [%g6 + TI_FPSAVED]
365         rd              %gsr, %g3
366         stx             %g3, [%g6 + TI_GSR]
367         mov             SECONDARY_CONTEXT, %g3
368
369 661:    ldxa            [%g3] ASI_DMMU, %g5
370         .section        .sun4v_1insn_patch, "ax"
371         .word           661b
372         ldxa            [%g3] ASI_MMU, %g5
373         .previous
374
375         sethi           %hi(sparc64_kern_sec_context), %g2
376         ldx             [%g2 + %lo(sparc64_kern_sec_context)], %g2
377
378 661:    stxa            %g2, [%g3] ASI_DMMU
379         .section        .sun4v_1insn_patch, "ax"
380         .word           661b
381         stxa            %g2, [%g3] ASI_MMU
382         .previous
383
384         membar          #Sync
385         add             %g6, TI_FPREGS, %g2
386         andcc           %g1, FPRS_DL, %g0
387         be,pn           %icc, 4f
388          mov            0x40, %g3
389         stda            %f0, [%g2] ASI_BLK_S
390         stda            %f16, [%g2 + %g3] ASI_BLK_S
391         andcc           %g1, FPRS_DU, %g0
392         be,pn           %icc, 5f
393 4:       add            %g2, 128, %g2
394         stda            %f32, [%g2] ASI_BLK_S
395         stda            %f48, [%g2 + %g3] ASI_BLK_S
396 5:      mov             SECONDARY_CONTEXT, %g1
397         membar          #Sync
398
399 661:    stxa            %g5, [%g1] ASI_DMMU
400         .section        .sun4v_1insn_patch, "ax"
401         .word           661b
402         stxa            %g5, [%g1] ASI_MMU
403         .previous
404
405         membar          #Sync
406         ba,pt           %xcc, etrap
407          wr             %g0, 0, %fprs
408
409         /* The registers for cross calls will be:
410          *
411          * DATA 0: [low 32-bits]  Address of function to call, jmp to this
412          *         [high 32-bits] MMU Context Argument 0, place in %g5
413          * DATA 1: Address Argument 1, place in %g1
414          * DATA 2: Address Argument 2, place in %g7
415          *
416          * With this method we can do most of the cross-call tlb/cache
417          * flushing very quickly.
418          */
419         .text
420         .align          32
421         .globl          do_ivec
422 do_ivec:
423         mov             0x40, %g3
424         ldxa            [%g3 + %g0] ASI_INTR_R, %g3
425         sethi           %hi(KERNBASE), %g4
426         cmp             %g3, %g4
427         bgeu,pn         %xcc, do_ivec_xcall
428          srlx           %g3, 32, %g5
429         stxa            %g0, [%g0] ASI_INTR_RECEIVE
430         membar          #Sync
431
432         sethi           %hi(ivector_table), %g2
433         sllx            %g3, 5, %g3
434         or              %g2, %lo(ivector_table), %g2
435         add             %g2, %g3, %g3
436         ldub            [%g3 + 0x04], %g4       /* pil */
437         mov             1, %g2
438         sllx            %g2, %g4, %g2
439         sllx            %g4, 2, %g4
440
441         TRAP_LOAD_IRQ_WORK(%g6, %g1)
442
443         lduw            [%g6 + %g4], %g5        /* g5 = irq_work(cpu, pil) */
444         stw             %g5, [%g3 + 0x00]       /* bucket->irq_chain = g5 */
445         stw             %g3, [%g6 + %g4]        /* irq_work(cpu, pil) = bucket */
446         wr              %g2, 0x0, %set_softint
447         retry
448 do_ivec_xcall:
449         mov             0x50, %g1
450         ldxa            [%g1 + %g0] ASI_INTR_R, %g1
451         srl             %g3, 0, %g3
452
453         mov             0x60, %g7
454         ldxa            [%g7 + %g0] ASI_INTR_R, %g7
455         stxa            %g0, [%g0] ASI_INTR_RECEIVE
456         membar          #Sync
457         ba,pt           %xcc, 1f
458          nop
459
460         .align          32
461 1:      jmpl            %g3, %g0
462          nop
463
464         .globl          getcc, setcc
465 getcc:
466         ldx             [%o0 + PT_V9_TSTATE], %o1
467         srlx            %o1, 32, %o1
468         and             %o1, 0xf, %o1
469         retl
470          stx            %o1, [%o0 + PT_V9_G1]
471 setcc:
472         ldx             [%o0 + PT_V9_TSTATE], %o1
473         ldx             [%o0 + PT_V9_G1], %o2
474         or              %g0, %ulo(TSTATE_ICC), %o3
475         sllx            %o3, 32, %o3
476         andn            %o1, %o3, %o1
477         sllx            %o2, 32, %o2
478         and             %o2, %o3, %o2
479         or              %o1, %o2, %o1
480         retl
481          stx            %o1, [%o0 + PT_V9_TSTATE]
482
483         .globl          utrap_trap
484 utrap_trap:             /* %g3=handler,%g4=level */
485         TRAP_LOAD_THREAD_REG(%g6, %g1)
486         ldx             [%g6 + TI_UTRAPS], %g1
487         brnz,pt         %g1, invoke_utrap
488          nop
489
490         ba,pt           %xcc, etrap
491          rd             %pc, %g7
492         mov             %l4, %o1
493         call            bad_trap
494          add            %sp, PTREGS_OFF, %o0
495         ba,pt           %xcc, rtrap
496          clr            %l6
497
498 invoke_utrap:
499         sllx            %g3, 3, %g3
500         ldx             [%g1 + %g3], %g1
501         save            %sp, -128, %sp
502         rdpr            %tstate, %l6
503         rdpr            %cwp, %l7
504         andn            %l6, TSTATE_CWP, %l6
505         wrpr            %l6, %l7, %tstate
506         rdpr            %tpc, %l6
507         rdpr            %tnpc, %l7
508         wrpr            %g1, 0, %tnpc
509         done
510
511         /* We need to carefully read the error status, ACK
512          * the errors, prevent recursive traps, and pass the
513          * information on to C code for logging.
514          *
515          * We pass the AFAR in as-is, and we encode the status
516          * information as described in asm-sparc64/sfafsr.h
517          */
518         .globl          __spitfire_access_error
519 __spitfire_access_error:
520         /* Disable ESTATE error reporting so that we do not
521          * take recursive traps and RED state the processor.
522          */
523         stxa            %g0, [%g0] ASI_ESTATE_ERROR_EN
524         membar          #Sync
525
526         mov             UDBE_UE, %g1
527         ldxa            [%g0] ASI_AFSR, %g4     ! Get AFSR
528
529         /* __spitfire_cee_trap branches here with AFSR in %g4 and
530          * UDBE_CE in %g1.  It only clears ESTATE_ERR_CE in the
531          * ESTATE Error Enable register.
532          */
533 __spitfire_cee_trap_continue:
534         ldxa            [%g0] ASI_AFAR, %g5     ! Get AFAR
535
536         rdpr            %tt, %g3
537         and             %g3, 0x1ff, %g3         ! Paranoia
538         sllx            %g3, SFSTAT_TRAP_TYPE_SHIFT, %g3
539         or              %g4, %g3, %g4
540         rdpr            %tl, %g3
541         cmp             %g3, 1
542         mov             1, %g3
543         bleu            %xcc, 1f
544          sllx           %g3, SFSTAT_TL_GT_ONE_SHIFT, %g3
545
546         or              %g4, %g3, %g4
547
548         /* Read in the UDB error register state, clearing the
549          * sticky error bits as-needed.  We only clear them if
550          * the UE bit is set.  Likewise, __spitfire_cee_trap
551          * below will only do so if the CE bit is set.
552          *
553          * NOTE: UltraSparc-I/II have high and low UDB error
554          *       registers, corresponding to the two UDB units
555          *       present on those chips.  UltraSparc-IIi only
556          *       has a single UDB, called "SDB" in the manual.
557          *       For IIi the upper UDB register always reads
558          *       as zero so for our purposes things will just
559          *       work with the checks below.
560          */
561 1:      ldxa            [%g0] ASI_UDBH_ERROR_R, %g3
562         and             %g3, 0x3ff, %g7         ! Paranoia
563         sllx            %g7, SFSTAT_UDBH_SHIFT, %g7
564         or              %g4, %g7, %g4
565         andcc           %g3, %g1, %g3           ! UDBE_UE or UDBE_CE
566         be,pn           %xcc, 1f
567          nop
568         stxa            %g3, [%g0] ASI_UDB_ERROR_W
569         membar          #Sync
570
571 1:      mov             0x18, %g3
572         ldxa            [%g3] ASI_UDBL_ERROR_R, %g3
573         and             %g3, 0x3ff, %g7         ! Paranoia
574         sllx            %g7, SFSTAT_UDBL_SHIFT, %g7
575         or              %g4, %g7, %g4
576         andcc           %g3, %g1, %g3           ! UDBE_UE or UDBE_CE
577         be,pn           %xcc, 1f
578          nop
579         mov             0x18, %g7
580         stxa            %g3, [%g7] ASI_UDB_ERROR_W
581         membar          #Sync
582
583 1:      /* Ok, now that we've latched the error state,
584          * clear the sticky bits in the AFSR.
585          */
586         stxa            %g4, [%g0] ASI_AFSR
587         membar          #Sync
588
589         rdpr            %tl, %g2
590         cmp             %g2, 1
591         rdpr            %pil, %g2
592         bleu,pt         %xcc, 1f
593          wrpr           %g0, 15, %pil
594
595         ba,pt           %xcc, etraptl1
596          rd             %pc, %g7
597
598         ba,pt           %xcc, 2f
599          nop
600
601 1:      ba,pt           %xcc, etrap_irq
602          rd             %pc, %g7
603
604 2:      mov             %l4, %o1
605         mov             %l5, %o2
606         call            spitfire_access_error
607          add            %sp, PTREGS_OFF, %o0
608         ba,pt           %xcc, rtrap
609          clr            %l6
610
611         /* This is the trap handler entry point for ECC correctable
612          * errors.  They are corrected, but we listen for the trap
613          * so that the event can be logged.
614          *
615          * Disrupting errors are either:
616          * 1) single-bit ECC errors during UDB reads to system
617          *    memory
618          * 2) data parity errors during write-back events
619          *
620          * As far as I can make out from the manual, the CEE trap
621          * is only for correctable errors during memory read
622          * accesses by the front-end of the processor.
623          *
624          * The code below is only for trap level 1 CEE events,
625          * as it is the only situation where we can safely record
626          * and log.  For trap level >1 we just clear the CE bit
627          * in the AFSR and return.
628          *
629          * This is just like __spiftire_access_error above, but it
630          * specifically handles correctable errors.  If an
631          * uncorrectable error is indicated in the AFSR we
632          * will branch directly above to __spitfire_access_error
633          * to handle it instead.  Uncorrectable therefore takes
634          * priority over correctable, and the error logging
635          * C code will notice this case by inspecting the
636          * trap type.
637          */
638         .globl          __spitfire_cee_trap
639 __spitfire_cee_trap:
640         ldxa            [%g0] ASI_AFSR, %g4     ! Get AFSR
641         mov             1, %g3
642         sllx            %g3, SFAFSR_UE_SHIFT, %g3
643         andcc           %g4, %g3, %g0           ! Check for UE
644         bne,pn          %xcc, __spitfire_access_error
645          nop
646
647         /* Ok, in this case we only have a correctable error.
648          * Indicate we only wish to capture that state in register
649          * %g1, and we only disable CE error reporting unlike UE
650          * handling which disables all errors.
651          */
652         ldxa            [%g0] ASI_ESTATE_ERROR_EN, %g3
653         andn            %g3, ESTATE_ERR_CE, %g3
654         stxa            %g3, [%g0] ASI_ESTATE_ERROR_EN
655         membar          #Sync
656
657         /* Preserve AFSR in %g4, indicate UDB state to capture in %g1 */
658         ba,pt           %xcc, __spitfire_cee_trap_continue
659          mov            UDBE_CE, %g1
660
661         .globl          __spitfire_data_access_exception
662         .globl          __spitfire_data_access_exception_tl1
663 __spitfire_data_access_exception_tl1:
664         rdpr            %pstate, %g4
665         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
666         mov             TLB_SFSR, %g3
667         mov             DMMU_SFAR, %g5
668         ldxa            [%g3] ASI_DMMU, %g4     ! Get SFSR
669         ldxa            [%g5] ASI_DMMU, %g5     ! Get SFAR
670         stxa            %g0, [%g3] ASI_DMMU     ! Clear SFSR.FaultValid bit
671         membar          #Sync
672         rdpr            %tt, %g3
673         cmp             %g3, 0x80               ! first win spill/fill trap
674         blu,pn          %xcc, 1f
675          cmp            %g3, 0xff               ! last win spill/fill trap
676         bgu,pn          %xcc, 1f
677          nop
678         ba,pt           %xcc, winfix_dax
679          rdpr           %tpc, %g3
680 1:      sethi           %hi(109f), %g7
681         ba,pt           %xcc, etraptl1
682 109:     or             %g7, %lo(109b), %g7
683         mov             %l4, %o1
684         mov             %l5, %o2
685         call            spitfire_data_access_exception_tl1
686          add            %sp, PTREGS_OFF, %o0
687         ba,pt           %xcc, rtrap
688          clr            %l6
689
690 __spitfire_data_access_exception:
691         rdpr            %pstate, %g4
692         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
693         mov             TLB_SFSR, %g3
694         mov             DMMU_SFAR, %g5
695         ldxa            [%g3] ASI_DMMU, %g4     ! Get SFSR
696         ldxa            [%g5] ASI_DMMU, %g5     ! Get SFAR
697         stxa            %g0, [%g3] ASI_DMMU     ! Clear SFSR.FaultValid bit
698         membar          #Sync
699         sethi           %hi(109f), %g7
700         ba,pt           %xcc, etrap
701 109:     or             %g7, %lo(109b), %g7
702         mov             %l4, %o1
703         mov             %l5, %o2
704         call            spitfire_data_access_exception
705          add            %sp, PTREGS_OFF, %o0
706         ba,pt           %xcc, rtrap
707          clr            %l6
708
709         .globl          __spitfire_insn_access_exception
710         .globl          __spitfire_insn_access_exception_tl1
711 __spitfire_insn_access_exception_tl1:
712         rdpr            %pstate, %g4
713         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
714         mov             TLB_SFSR, %g3
715         ldxa            [%g3] ASI_IMMU, %g4     ! Get SFSR
716         rdpr            %tpc, %g5               ! IMMU has no SFAR, use TPC
717         stxa            %g0, [%g3] ASI_IMMU     ! Clear FaultValid bit
718         membar          #Sync
719         sethi           %hi(109f), %g7
720         ba,pt           %xcc, etraptl1
721 109:     or             %g7, %lo(109b), %g7
722         mov             %l4, %o1
723         mov             %l5, %o2
724         call            spitfire_insn_access_exception_tl1
725          add            %sp, PTREGS_OFF, %o0
726         ba,pt           %xcc, rtrap
727          clr            %l6
728
729 __spitfire_insn_access_exception:
730         rdpr            %pstate, %g4
731         wrpr            %g4, PSTATE_MG|PSTATE_AG, %pstate
732         mov             TLB_SFSR, %g3
733         ldxa            [%g3] ASI_IMMU, %g4     ! Get SFSR
734         rdpr            %tpc, %g5               ! IMMU has no SFAR, use TPC
735         stxa            %g0, [%g3] ASI_IMMU     ! Clear FaultValid bit
736         membar          #Sync
737         sethi           %hi(109f), %g7
738         ba,pt           %xcc, etrap
739 109:     or             %g7, %lo(109b), %g7
740         mov             %l4, %o1
741         mov             %l5, %o2
742         call            spitfire_insn_access_exception
743          add            %sp, PTREGS_OFF, %o0
744         ba,pt           %xcc, rtrap
745          clr            %l6
746
747         /* These get patched into the trap table at boot time
748          * once we know we have a cheetah processor.
749          */
750         .globl          cheetah_fecc_trap_vector, cheetah_fecc_trap_vector_tl1
751 cheetah_fecc_trap_vector:
752         membar          #Sync
753         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
754         andn            %g1, DCU_DC | DCU_IC, %g1
755         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
756         membar          #Sync
757         sethi           %hi(cheetah_fast_ecc), %g2
758         jmpl            %g2 + %lo(cheetah_fast_ecc), %g0
759          mov            0, %g1
760 cheetah_fecc_trap_vector_tl1:
761         membar          #Sync
762         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
763         andn            %g1, DCU_DC | DCU_IC, %g1
764         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
765         membar          #Sync
766         sethi           %hi(cheetah_fast_ecc), %g2
767         jmpl            %g2 + %lo(cheetah_fast_ecc), %g0
768          mov            1, %g1
769         .globl  cheetah_cee_trap_vector, cheetah_cee_trap_vector_tl1
770 cheetah_cee_trap_vector:
771         membar          #Sync
772         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
773         andn            %g1, DCU_IC, %g1
774         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
775         membar          #Sync
776         sethi           %hi(cheetah_cee), %g2
777         jmpl            %g2 + %lo(cheetah_cee), %g0
778          mov            0, %g1
779 cheetah_cee_trap_vector_tl1:
780         membar          #Sync
781         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
782         andn            %g1, DCU_IC, %g1
783         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
784         membar          #Sync
785         sethi           %hi(cheetah_cee), %g2
786         jmpl            %g2 + %lo(cheetah_cee), %g0
787          mov            1, %g1
788         .globl  cheetah_deferred_trap_vector, cheetah_deferred_trap_vector_tl1
789 cheetah_deferred_trap_vector:
790         membar          #Sync
791         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1;
792         andn            %g1, DCU_DC | DCU_IC, %g1;
793         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG;
794         membar          #Sync;
795         sethi           %hi(cheetah_deferred_trap), %g2
796         jmpl            %g2 + %lo(cheetah_deferred_trap), %g0
797          mov            0, %g1
798 cheetah_deferred_trap_vector_tl1:
799         membar          #Sync;
800         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1;
801         andn            %g1, DCU_DC | DCU_IC, %g1;
802         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG;
803         membar          #Sync;
804         sethi           %hi(cheetah_deferred_trap), %g2
805         jmpl            %g2 + %lo(cheetah_deferred_trap), %g0
806          mov            1, %g1
807
808         /* Cheetah+ specific traps. These are for the new I/D cache parity
809          * error traps.  The first argument to cheetah_plus_parity_handler
810          * is encoded as follows:
811          *
812          * Bit0:        0=dcache,1=icache
813          * Bit1:        0=recoverable,1=unrecoverable
814          */
815         .globl          cheetah_plus_dcpe_trap_vector, cheetah_plus_dcpe_trap_vector_tl1
816 cheetah_plus_dcpe_trap_vector:
817         membar          #Sync
818         sethi           %hi(do_cheetah_plus_data_parity), %g7
819         jmpl            %g7 + %lo(do_cheetah_plus_data_parity), %g0
820          nop
821         nop
822         nop
823         nop
824         nop
825
826 do_cheetah_plus_data_parity:
827         rdpr            %pil, %g2
828         wrpr            %g0, 15, %pil
829         ba,pt           %xcc, etrap_irq
830          rd             %pc, %g7
831         mov             0x0, %o0
832         call            cheetah_plus_parity_error
833          add            %sp, PTREGS_OFF, %o1
834         ba,a,pt         %xcc, rtrap_irq
835
836 cheetah_plus_dcpe_trap_vector_tl1:
837         membar          #Sync
838         wrpr            PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
839         sethi           %hi(do_dcpe_tl1), %g3
840         jmpl            %g3 + %lo(do_dcpe_tl1), %g0
841          nop
842         nop
843         nop
844         nop
845
846         .globl          cheetah_plus_icpe_trap_vector, cheetah_plus_icpe_trap_vector_tl1
847 cheetah_plus_icpe_trap_vector:
848         membar          #Sync
849         sethi           %hi(do_cheetah_plus_insn_parity), %g7
850         jmpl            %g7 + %lo(do_cheetah_plus_insn_parity), %g0
851          nop
852         nop
853         nop
854         nop
855         nop
856
857 do_cheetah_plus_insn_parity:
858         rdpr            %pil, %g2
859         wrpr            %g0, 15, %pil
860         ba,pt           %xcc, etrap_irq
861          rd             %pc, %g7
862         mov             0x1, %o0
863         call            cheetah_plus_parity_error
864          add            %sp, PTREGS_OFF, %o1
865         ba,a,pt         %xcc, rtrap_irq
866
867 cheetah_plus_icpe_trap_vector_tl1:
868         membar          #Sync
869         wrpr            PSTATE_IG | PSTATE_PEF | PSTATE_PRIV, %pstate
870         sethi           %hi(do_icpe_tl1), %g3
871         jmpl            %g3 + %lo(do_icpe_tl1), %g0
872          nop
873         nop
874         nop
875         nop
876
877         /* If we take one of these traps when tl >= 1, then we
878          * jump to interrupt globals.  If some trap level above us
879          * was also using interrupt globals, we cannot recover.
880          * We may use all interrupt global registers except %g6.
881          */
882         .globl          do_dcpe_tl1, do_icpe_tl1
883 do_dcpe_tl1:
884         rdpr            %tl, %g1                ! Save original trap level
885         mov             1, %g2                  ! Setup TSTATE checking loop
886         sethi           %hi(TSTATE_IG), %g3     ! TSTATE mask bit
887 1:      wrpr            %g2, %tl                ! Set trap level to check
888         rdpr            %tstate, %g4            ! Read TSTATE for this level
889         andcc           %g4, %g3, %g0           ! Interrupt globals in use?
890         bne,a,pn        %xcc, do_dcpe_tl1_fatal ! Yep, irrecoverable
891          wrpr           %g1, %tl                ! Restore original trap level
892         add             %g2, 1, %g2             ! Next trap level
893         cmp             %g2, %g1                ! Hit them all yet?
894         ble,pt          %icc, 1b                ! Not yet
895          nop
896         wrpr            %g1, %tl                ! Restore original trap level
897 do_dcpe_tl1_nonfatal:   /* Ok we may use interrupt globals safely. */
898         sethi           %hi(dcache_parity_tl1_occurred), %g2
899         lduw            [%g2 + %lo(dcache_parity_tl1_occurred)], %g1
900         add             %g1, 1, %g1
901         stw             %g1, [%g2 + %lo(dcache_parity_tl1_occurred)]
902         /* Reset D-cache parity */
903         sethi           %hi(1 << 16), %g1       ! D-cache size
904         mov             (1 << 5), %g2           ! D-cache line size
905         sub             %g1, %g2, %g1           ! Move down 1 cacheline
906 1:      srl             %g1, 14, %g3            ! Compute UTAG
907         membar          #Sync
908         stxa            %g3, [%g1] ASI_DCACHE_UTAG
909         membar          #Sync
910         sub             %g2, 8, %g3             ! 64-bit data word within line
911 2:      membar          #Sync
912         stxa            %g0, [%g1 + %g3] ASI_DCACHE_DATA
913         membar          #Sync
914         subcc           %g3, 8, %g3             ! Next 64-bit data word
915         bge,pt          %icc, 2b
916          nop
917         subcc           %g1, %g2, %g1           ! Next cacheline
918         bge,pt          %icc, 1b
919          nop
920         ba,pt           %xcc, dcpe_icpe_tl1_common
921          nop
922
923 do_dcpe_tl1_fatal:
924         sethi           %hi(1f), %g7
925         ba,pt           %xcc, etraptl1
926 1:      or              %g7, %lo(1b), %g7
927         mov             0x2, %o0
928         call            cheetah_plus_parity_error
929          add            %sp, PTREGS_OFF, %o1
930         ba,pt           %xcc, rtrap
931          clr            %l6
932
933 do_icpe_tl1:
934         rdpr            %tl, %g1                ! Save original trap level
935         mov             1, %g2                  ! Setup TSTATE checking loop
936         sethi           %hi(TSTATE_IG), %g3     ! TSTATE mask bit
937 1:      wrpr            %g2, %tl                ! Set trap level to check
938         rdpr            %tstate, %g4            ! Read TSTATE for this level
939         andcc           %g4, %g3, %g0           ! Interrupt globals in use?
940         bne,a,pn        %xcc, do_icpe_tl1_fatal ! Yep, irrecoverable
941          wrpr           %g1, %tl                ! Restore original trap level
942         add             %g2, 1, %g2             ! Next trap level
943         cmp             %g2, %g1                ! Hit them all yet?
944         ble,pt          %icc, 1b                ! Not yet
945          nop
946         wrpr            %g1, %tl                ! Restore original trap level
947 do_icpe_tl1_nonfatal:   /* Ok we may use interrupt globals safely. */
948         sethi           %hi(icache_parity_tl1_occurred), %g2
949         lduw            [%g2 + %lo(icache_parity_tl1_occurred)], %g1
950         add             %g1, 1, %g1
951         stw             %g1, [%g2 + %lo(icache_parity_tl1_occurred)]
952         /* Flush I-cache */
953         sethi           %hi(1 << 15), %g1       ! I-cache size
954         mov             (1 << 5), %g2           ! I-cache line size
955         sub             %g1, %g2, %g1
956 1:      or              %g1, (2 << 3), %g3
957         stxa            %g0, [%g3] ASI_IC_TAG
958         membar          #Sync
959         subcc           %g1, %g2, %g1
960         bge,pt          %icc, 1b
961          nop
962         ba,pt           %xcc, dcpe_icpe_tl1_common
963          nop
964
965 do_icpe_tl1_fatal:
966         sethi           %hi(1f), %g7
967         ba,pt           %xcc, etraptl1
968 1:      or              %g7, %lo(1b), %g7
969         mov             0x3, %o0
970         call            cheetah_plus_parity_error
971          add            %sp, PTREGS_OFF, %o1
972         ba,pt           %xcc, rtrap
973          clr            %l6
974         
975 dcpe_icpe_tl1_common:
976         /* Flush D-cache, re-enable D/I caches in DCU and finally
977          * retry the trapping instruction.
978          */
979         sethi           %hi(1 << 16), %g1       ! D-cache size
980         mov             (1 << 5), %g2           ! D-cache line size
981         sub             %g1, %g2, %g1
982 1:      stxa            %g0, [%g1] ASI_DCACHE_TAG
983         membar          #Sync
984         subcc           %g1, %g2, %g1
985         bge,pt          %icc, 1b
986          nop
987         ldxa            [%g0] ASI_DCU_CONTROL_REG, %g1
988         or              %g1, (DCU_DC | DCU_IC), %g1
989         stxa            %g1, [%g0] ASI_DCU_CONTROL_REG
990         membar          #Sync
991         retry
992
993         /* Capture I/D/E-cache state into per-cpu error scoreboard.
994          *
995          * %g1:         (TL>=0) ? 1 : 0
996          * %g2:         scratch
997          * %g3:         scratch
998          * %g4:         AFSR
999          * %g5:         AFAR
1000          * %g6:         unused, will have current thread ptr after etrap
1001          * %g7:         scratch
1002          */
1003 __cheetah_log_error:
1004         /* Put "TL1" software bit into AFSR. */
1005         and             %g1, 0x1, %g1
1006         sllx            %g1, 63, %g2
1007         or              %g4, %g2, %g4
1008
1009         /* Get log entry pointer for this cpu at this trap level. */
1010         BRANCH_IF_JALAPENO(g2,g3,50f)
1011         ldxa            [%g0] ASI_SAFARI_CONFIG, %g2
1012         srlx            %g2, 17, %g2
1013         ba,pt           %xcc, 60f
1014          and            %g2, 0x3ff, %g2
1015
1016 50:     ldxa            [%g0] ASI_JBUS_CONFIG, %g2
1017         srlx            %g2, 17, %g2
1018         and             %g2, 0x1f, %g2
1019
1020 60:     sllx            %g2, 9, %g2
1021         sethi           %hi(cheetah_error_log), %g3
1022         ldx             [%g3 + %lo(cheetah_error_log)], %g3
1023         brz,pn          %g3, 80f
1024          nop
1025
1026         add             %g3, %g2, %g3
1027         sllx            %g1, 8, %g1
1028         add             %g3, %g1, %g1
1029
1030         /* %g1 holds pointer to the top of the logging scoreboard */
1031         ldx             [%g1 + 0x0], %g7
1032         cmp             %g7, -1
1033         bne,pn          %xcc, 80f
1034          nop
1035
1036         stx             %g4, [%g1 + 0x0]
1037         stx             %g5, [%g1 + 0x8]
1038         add             %g1, 0x10, %g1
1039
1040         /* %g1 now points to D-cache logging area */
1041         set             0x3ff8, %g2     /* DC_addr mask         */
1042         and             %g5, %g2, %g2   /* DC_addr bits of AFAR */
1043         srlx            %g5, 12, %g3
1044         or              %g3, 1, %g3     /* PHYS tag + valid     */
1045
1046 10:     ldxa            [%g2] ASI_DCACHE_TAG, %g7
1047         cmp             %g3, %g7        /* TAG match?           */
1048         bne,pt          %xcc, 13f
1049          nop
1050
1051         /* Yep, what we want, capture state. */
1052         stx             %g2, [%g1 + 0x20]
1053         stx             %g7, [%g1 + 0x28]
1054
1055         /* A membar Sync is required before and after utag access. */
1056         membar          #Sync
1057         ldxa            [%g2] ASI_DCACHE_UTAG, %g7
1058         membar          #Sync
1059         stx             %g7, [%g1 + 0x30]
1060         ldxa            [%g2] ASI_DCACHE_SNOOP_TAG, %g7
1061         stx             %g7, [%g1 + 0x38]
1062         clr             %g3
1063
1064 12:     ldxa            [%g2 + %g3] ASI_DCACHE_DATA, %g7
1065         stx             %g7, [%g1]
1066         add             %g3, (1 << 5), %g3
1067         cmp             %g3, (4 << 5)
1068         bl,pt           %xcc, 12b
1069          add            %g1, 0x8, %g1
1070
1071         ba,pt           %xcc, 20f
1072          add            %g1, 0x20, %g1
1073
1074 13:     sethi           %hi(1 << 14), %g7
1075         add             %g2, %g7, %g2
1076         srlx            %g2, 14, %g7
1077         cmp             %g7, 4
1078         bl,pt           %xcc, 10b
1079          nop
1080
1081         add             %g1, 0x40, %g1
1082
1083         /* %g1 now points to I-cache logging area */
1084 20:     set             0x1fe0, %g2     /* IC_addr mask         */
1085         and             %g5, %g2, %g2   /* IC_addr bits of AFAR */
1086         sllx            %g2, 1, %g2     /* IC_addr[13:6]==VA[12:5] */
1087         srlx            %g5, (13 - 8), %g3 /* Make PTAG */
1088         andn            %g3, 0xff, %g3  /* Mask off undefined bits */
1089
1090 21:     ldxa            [%g2] ASI_IC_TAG, %g7
1091         andn            %g7, 0xff, %g7
1092         cmp             %g3, %g7
1093         bne,pt          %xcc, 23f
1094          nop
1095
1096         /* Yep, what we want, capture state. */
1097         stx             %g2, [%g1 + 0x40]
1098         stx             %g7, [%g1 + 0x48]
1099         add             %g2, (1 << 3), %g2
1100         ldxa            [%g2] ASI_IC_TAG, %g7
1101         add             %g2, (1 << 3), %g2
1102         stx             %g7, [%g1 + 0x50]
1103         ldxa            [%g2] ASI_IC_TAG, %g7
1104         add             %g2, (1 << 3), %g2
1105         stx             %g7, [%g1 + 0x60]
1106         ldxa            [%g2] ASI_IC_TAG, %g7
1107         stx             %g7, [%g1 + 0x68]
1108         sub             %g2, (3 << 3), %g2
1109         ldxa            [%g2] ASI_IC_STAG, %g7
1110         stx             %g7, [%g1 + 0x58]
1111         clr             %g3
1112         srlx            %g2, 2, %g2
1113
1114 22:     ldxa            [%g2 + %g3] ASI_IC_INSTR, %g7
1115         stx             %g7, [%g1]
1116         add             %g3, (1 << 3), %g3
1117         cmp             %g3, (8 << 3)
1118         bl,pt           %xcc, 22b
1119          add            %g1, 0x8, %g1
1120
1121         ba,pt           %xcc, 30f
1122          add            %g1, 0x30, %g1
1123
1124 23:     sethi           %hi(1 << 14), %g7
1125         add             %g2, %g7, %g2
1126         srlx            %g2, 14, %g7
1127         cmp             %g7, 4
1128         bl,pt           %xcc, 21b
1129          nop
1130
1131         add             %g1, 0x70, %g1
1132
1133         /* %g1 now points to E-cache logging area */
1134 30:     andn            %g5, (32 - 1), %g2
1135         stx             %g2, [%g1 + 0x20]
1136         ldxa            [%g2] ASI_EC_TAG_DATA, %g7
1137         stx             %g7, [%g1 + 0x28]
1138         ldxa            [%g2] ASI_EC_R, %g0
1139         clr             %g3
1140
1141 31:     ldxa            [%g3] ASI_EC_DATA, %g7
1142         stx             %g7, [%g1 + %g3]
1143         add             %g3, 0x8, %g3
1144         cmp             %g3, 0x20
1145
1146         bl,pt           %xcc, 31b
1147          nop
1148 80:
1149         rdpr            %tt, %g2
1150         cmp             %g2, 0x70
1151         be              c_fast_ecc
1152          cmp            %g2, 0x63
1153         be              c_cee
1154          nop
1155         ba,pt           %xcc, c_deferred
1156
1157         /* Cheetah FECC trap handling, we get here from tl{0,1}_fecc
1158          * in the trap table.  That code has done a memory barrier
1159          * and has disabled both the I-cache and D-cache in the DCU
1160          * control register.  The I-cache is disabled so that we may
1161          * capture the corrupted cache line, and the D-cache is disabled
1162          * because corrupt data may have been placed there and we don't
1163          * want to reference it.
1164          *
1165          * %g1 is one if this trap occurred at %tl >= 1.
1166          *
1167          * Next, we turn off error reporting so that we don't recurse.
1168          */
1169         .globl          cheetah_fast_ecc
1170 cheetah_fast_ecc:
1171         ldxa            [%g0] ASI_ESTATE_ERROR_EN, %g2
1172         andn            %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2
1173         stxa            %g2, [%g0] ASI_ESTATE_ERROR_EN
1174         membar          #Sync
1175
1176         /* Fetch and clear AFSR/AFAR */
1177         ldxa            [%g0] ASI_AFSR, %g4
1178         ldxa            [%g0] ASI_AFAR, %g5
1179         stxa            %g4, [%g0] ASI_AFSR
1180         membar          #Sync
1181
1182         ba,pt           %xcc, __cheetah_log_error
1183          nop
1184
1185 c_fast_ecc:
1186         rdpr            %pil, %g2
1187         wrpr            %g0, 15, %pil
1188         ba,pt           %xcc, etrap_irq
1189          rd             %pc, %g7
1190         mov             %l4, %o1
1191         mov             %l5, %o2
1192         call            cheetah_fecc_handler
1193          add            %sp, PTREGS_OFF, %o0
1194         ba,a,pt         %xcc, rtrap_irq
1195
1196         /* Our caller has disabled I-cache and performed membar Sync. */
1197         .globl          cheetah_cee
1198 cheetah_cee:
1199         ldxa            [%g0] ASI_ESTATE_ERROR_EN, %g2
1200         andn            %g2, ESTATE_ERROR_CEEN, %g2
1201         stxa            %g2, [%g0] ASI_ESTATE_ERROR_EN
1202         membar          #Sync
1203
1204         /* Fetch and clear AFSR/AFAR */
1205         ldxa            [%g0] ASI_AFSR, %g4
1206         ldxa            [%g0] ASI_AFAR, %g5
1207         stxa            %g4, [%g0] ASI_AFSR
1208         membar          #Sync
1209
1210         ba,pt           %xcc, __cheetah_log_error
1211          nop
1212
1213 c_cee:
1214         rdpr            %pil, %g2
1215         wrpr            %g0, 15, %pil
1216         ba,pt           %xcc, etrap_irq
1217          rd             %pc, %g7
1218         mov             %l4, %o1
1219         mov             %l5, %o2
1220         call            cheetah_cee_handler
1221          add            %sp, PTREGS_OFF, %o0
1222         ba,a,pt         %xcc, rtrap_irq
1223
1224         /* Our caller has disabled I-cache+D-cache and performed membar Sync. */
1225         .globl          cheetah_deferred_trap
1226 cheetah_deferred_trap:
1227         ldxa            [%g0] ASI_ESTATE_ERROR_EN, %g2
1228         andn            %g2, ESTATE_ERROR_NCEEN | ESTATE_ERROR_CEEN, %g2
1229         stxa            %g2, [%g0] ASI_ESTATE_ERROR_EN
1230         membar          #Sync
1231
1232         /* Fetch and clear AFSR/AFAR */
1233         ldxa            [%g0] ASI_AFSR, %g4
1234         ldxa            [%g0] ASI_AFAR, %g5
1235         stxa            %g4, [%g0] ASI_AFSR
1236         membar          #Sync
1237
1238         ba,pt           %xcc, __cheetah_log_error
1239          nop
1240
1241 c_deferred:
1242         rdpr            %pil, %g2
1243         wrpr            %g0, 15, %pil
1244         ba,pt           %xcc, etrap_irq
1245          rd             %pc, %g7
1246         mov             %l4, %o1
1247         mov             %l5, %o2
1248         call            cheetah_deferred_handler
1249          add            %sp, PTREGS_OFF, %o0
1250         ba,a,pt         %xcc, rtrap_irq
1251
1252         .globl          __do_privact
1253 __do_privact:
1254         mov             TLB_SFSR, %g3
1255         stxa            %g0, [%g3] ASI_DMMU     ! Clear FaultValid bit
1256         membar          #Sync
1257         sethi           %hi(109f), %g7
1258         ba,pt           %xcc, etrap
1259 109:    or              %g7, %lo(109b), %g7
1260         call            do_privact
1261          add            %sp, PTREGS_OFF, %o0
1262         ba,pt           %xcc, rtrap
1263          clr            %l6
1264
1265         .globl          do_mna
1266 do_mna:
1267         rdpr            %tl, %g3
1268         cmp             %g3, 1
1269
1270         /* Setup %g4/%g5 now as they are used in the
1271          * winfixup code.
1272          */
1273         mov             TLB_SFSR, %g3
1274         mov             DMMU_SFAR, %g4
1275         ldxa            [%g4] ASI_DMMU, %g4
1276         ldxa            [%g3] ASI_DMMU, %g5
1277         stxa            %g0, [%g3] ASI_DMMU     ! Clear FaultValid bit
1278         membar          #Sync
1279         bgu,pn          %icc, winfix_mna
1280          rdpr           %tpc, %g3
1281
1282 1:      sethi           %hi(109f), %g7
1283         ba,pt           %xcc, etrap
1284 109:     or             %g7, %lo(109b), %g7
1285         mov             %l4, %o1
1286         mov             %l5, %o2
1287         call            mem_address_unaligned
1288          add            %sp, PTREGS_OFF, %o0
1289         ba,pt           %xcc, rtrap
1290          clr            %l6
1291
1292         .globl          do_lddfmna
1293 do_lddfmna:
1294         sethi           %hi(109f), %g7
1295         mov             TLB_SFSR, %g4
1296         ldxa            [%g4] ASI_DMMU, %g5
1297         stxa            %g0, [%g4] ASI_DMMU     ! Clear FaultValid bit
1298         membar          #Sync
1299         mov             DMMU_SFAR, %g4
1300         ldxa            [%g4] ASI_DMMU, %g4
1301         ba,pt           %xcc, etrap
1302 109:     or             %g7, %lo(109b), %g7
1303         mov             %l4, %o1
1304         mov             %l5, %o2
1305         call            handle_lddfmna
1306          add            %sp, PTREGS_OFF, %o0
1307         ba,pt           %xcc, rtrap
1308          clr            %l6
1309
1310         .globl          do_stdfmna
1311 do_stdfmna:
1312         sethi           %hi(109f), %g7
1313         mov             TLB_SFSR, %g4
1314         ldxa            [%g4] ASI_DMMU, %g5
1315         stxa            %g0, [%g4] ASI_DMMU     ! Clear FaultValid bit
1316         membar          #Sync
1317         mov             DMMU_SFAR, %g4
1318         ldxa            [%g4] ASI_DMMU, %g4
1319         ba,pt           %xcc, etrap
1320 109:     or             %g7, %lo(109b), %g7
1321         mov             %l4, %o1
1322         mov             %l5, %o2
1323         call            handle_stdfmna
1324          add            %sp, PTREGS_OFF, %o0
1325         ba,pt           %xcc, rtrap
1326          clr            %l6
1327
1328         .globl  breakpoint_trap
1329 breakpoint_trap:
1330         call            sparc_breakpoint
1331          add            %sp, PTREGS_OFF, %o0
1332         ba,pt           %xcc, rtrap
1333          nop
1334
1335 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
1336     defined(CONFIG_SOLARIS_EMUL_MODULE)
1337         /* SunOS uses syscall zero as the 'indirect syscall' it looks
1338          * like indir_syscall(scall_num, arg0, arg1, arg2...);  etc.
1339          * This is complete brain damage.
1340          */
1341         .globl  sunos_indir
1342 sunos_indir:
1343         srl             %o0, 0, %o0
1344         mov             %o7, %l4
1345         cmp             %o0, NR_SYSCALLS
1346         blu,a,pt        %icc, 1f
1347          sll            %o0, 0x2, %o0
1348         sethi           %hi(sunos_nosys), %l6
1349         b,pt            %xcc, 2f
1350          or             %l6, %lo(sunos_nosys), %l6
1351 1:      sethi           %hi(sunos_sys_table), %l7
1352         or              %l7, %lo(sunos_sys_table), %l7
1353         lduw            [%l7 + %o0], %l6
1354 2:      mov             %o1, %o0
1355         mov             %o2, %o1
1356         mov             %o3, %o2
1357         mov             %o4, %o3
1358         mov             %o5, %o4
1359         call            %l6
1360          mov            %l4, %o7
1361
1362         .globl  sunos_getpid
1363 sunos_getpid:
1364         call    sys_getppid
1365          nop
1366         call    sys_getpid
1367          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I1]
1368         b,pt    %xcc, ret_sys_call
1369          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1370
1371         /* SunOS getuid() returns uid in %o0 and euid in %o1 */
1372         .globl  sunos_getuid
1373 sunos_getuid:
1374         call    sys32_geteuid16
1375          nop
1376         call    sys32_getuid16
1377          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I1]
1378         b,pt    %xcc, ret_sys_call
1379          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1380
1381         /* SunOS getgid() returns gid in %o0 and egid in %o1 */
1382         .globl  sunos_getgid
1383 sunos_getgid:
1384         call    sys32_getegid16
1385          nop
1386         call    sys32_getgid16
1387          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I1]
1388         b,pt    %xcc, ret_sys_call
1389          stx    %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1390 #endif
1391
1392         /* SunOS's execv() call only specifies the argv argument, the
1393          * environment settings are the same as the calling processes.
1394          */
1395         .globl  sunos_execv
1396 sys_execve:
1397         sethi           %hi(sparc_execve), %g1
1398         ba,pt           %xcc, execve_merge
1399          or             %g1, %lo(sparc_execve), %g1
1400 #ifdef CONFIG_COMPAT
1401         .globl  sys_execve
1402 sunos_execv:
1403         stx             %g0, [%sp + PTREGS_OFF + PT_V9_I2]
1404         .globl  sys32_execve
1405 sys32_execve:
1406         sethi           %hi(sparc32_execve), %g1
1407         or              %g1, %lo(sparc32_execve), %g1
1408 #endif
1409 execve_merge:
1410         flushw
1411         jmpl            %g1, %g0
1412          add            %sp, PTREGS_OFF, %o0
1413
1414         .globl  sys_pipe, sys_sigpause, sys_nis_syscall
1415         .globl  sys_rt_sigreturn
1416         .globl  sys_ptrace
1417         .globl  sys_sigaltstack
1418         .align  32
1419 sys_pipe:       ba,pt           %xcc, sparc_pipe
1420                  add            %sp, PTREGS_OFF, %o0
1421 sys_nis_syscall:ba,pt           %xcc, c_sys_nis_syscall
1422                  add            %sp, PTREGS_OFF, %o0
1423 sys_memory_ordering:
1424                 ba,pt           %xcc, sparc_memory_ordering
1425                  add            %sp, PTREGS_OFF, %o1
1426 sys_sigaltstack:ba,pt           %xcc, do_sigaltstack
1427                  add            %i6, STACK_BIAS, %o2
1428 #ifdef CONFIG_COMPAT
1429         .globl  sys32_sigstack
1430 sys32_sigstack: ba,pt           %xcc, do_sys32_sigstack
1431                  mov            %i6, %o2
1432         .globl  sys32_sigaltstack
1433 sys32_sigaltstack:
1434                 ba,pt           %xcc, do_sys32_sigaltstack
1435                  mov            %i6, %o2
1436 #endif
1437                 .align          32
1438 #ifdef CONFIG_COMPAT
1439         .globl  sys32_sigreturn
1440 sys32_sigreturn:
1441                 add             %sp, PTREGS_OFF, %o0
1442                 call            do_sigreturn32
1443                  add            %o7, 1f-.-4, %o7
1444                 nop
1445 #endif
1446 sys_rt_sigreturn:
1447                 add             %sp, PTREGS_OFF, %o0
1448                 call            do_rt_sigreturn
1449                  add            %o7, 1f-.-4, %o7
1450                 nop
1451 #ifdef CONFIG_COMPAT
1452         .globl  sys32_rt_sigreturn
1453 sys32_rt_sigreturn:
1454                 add             %sp, PTREGS_OFF, %o0
1455                 call            do_rt_sigreturn32
1456                  add            %o7, 1f-.-4, %o7
1457                 nop
1458 #endif
1459 sys_ptrace:     add             %sp, PTREGS_OFF, %o0
1460                 call            do_ptrace
1461                  add            %o7, 1f-.-4, %o7
1462                 nop
1463                 .align          32
1464 1:              ldx             [%curptr + TI_FLAGS], %l5
1465                 andcc           %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
1466                 be,pt           %icc, rtrap
1467                  clr            %l6
1468                 add             %sp, PTREGS_OFF, %o0
1469                 call            syscall_trace
1470                  mov            1, %o1
1471
1472                 ba,pt           %xcc, rtrap
1473                  clr            %l6
1474
1475         /* This is how fork() was meant to be done, 8 instruction entry.
1476          *
1477          * I questioned the following code briefly, let me clear things
1478          * up so you must not reason on it like I did.
1479          *
1480          * Know the fork_kpsr etc. we use in the sparc32 port?  We don't
1481          * need it here because the only piece of window state we copy to
1482          * the child is the CWP register.  Even if the parent sleeps,
1483          * we are safe because we stuck it into pt_regs of the parent
1484          * so it will not change.
1485          *
1486          * XXX This raises the question, whether we can do the same on
1487          * XXX sparc32 to get rid of fork_kpsr _and_ fork_kwim.  The
1488          * XXX answer is yes.  We stick fork_kpsr in UREG_G0 and
1489          * XXX fork_kwim in UREG_G1 (global registers are considered
1490          * XXX volatile across a system call in the sparc ABI I think
1491          * XXX if it isn't we can use regs->y instead, anyone who depends
1492          * XXX upon the Y register being preserved across a fork deserves
1493          * XXX to lose).
1494          *
1495          * In fact we should take advantage of that fact for other things
1496          * during system calls...
1497          */
1498         .globl  sys_fork, sys_vfork, sys_clone, sparc_exit
1499         .globl  ret_from_syscall
1500         .align  32
1501 sys_vfork:      /* Under Linux, vfork and fork are just special cases of clone. */
1502                 sethi           %hi(0x4000 | 0x0100 | SIGCHLD), %o0
1503                 or              %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0
1504                 ba,pt           %xcc, sys_clone
1505 sys_fork:        clr            %o1
1506                 mov             SIGCHLD, %o0
1507 sys_clone:      flushw
1508                 movrz           %o1, %fp, %o1
1509                 mov             0, %o3
1510                 ba,pt           %xcc, sparc_do_fork
1511                  add            %sp, PTREGS_OFF, %o2
1512 ret_from_syscall:
1513                 /* Clear current_thread_info()->new_child, and
1514                  * check performance counter stuff too.
1515                  */
1516                 stb             %g0, [%g6 + TI_NEW_CHILD]
1517                 ldx             [%g6 + TI_FLAGS], %l0
1518                 call            schedule_tail
1519                  mov            %g7, %o0
1520                 andcc           %l0, _TIF_PERFCTR, %g0
1521                 be,pt           %icc, 1f
1522                  nop
1523                 ldx             [%g6 + TI_PCR], %o7
1524                 wr              %g0, %o7, %pcr
1525
1526                 /* Blackbird errata workaround.  See commentary in
1527                  * smp.c:smp_percpu_timer_interrupt() for more
1528                  * information.
1529                  */
1530                 ba,pt           %xcc, 99f
1531                  nop
1532                 .align          64
1533 99:             wr              %g0, %g0, %pic
1534                 rd              %pic, %g0
1535
1536 1:              b,pt            %xcc, ret_sys_call
1537                  ldx            [%sp + PTREGS_OFF + PT_V9_I0], %o0
1538 sparc_exit:     rdpr            %pstate, %g2
1539                 wrpr            %g2, PSTATE_IE, %pstate
1540                 rdpr            %otherwin, %g1
1541                 rdpr            %cansave, %g3
1542                 add             %g3, %g1, %g3
1543                 wrpr            %g3, 0x0, %cansave
1544                 wrpr            %g0, 0x0, %otherwin
1545                 wrpr            %g2, 0x0, %pstate
1546                 ba,pt           %xcc, sys_exit
1547                  stb            %g0, [%g6 + TI_WSAVED]
1548
1549 linux_sparc_ni_syscall:
1550         sethi           %hi(sys_ni_syscall), %l7
1551         b,pt            %xcc, 4f
1552          or             %l7, %lo(sys_ni_syscall), %l7
1553
1554 linux_syscall_trace32:
1555         add             %sp, PTREGS_OFF, %o0
1556         call            syscall_trace
1557          clr            %o1
1558         srl             %i0, 0, %o0
1559         srl             %i4, 0, %o4
1560         srl             %i1, 0, %o1
1561         srl             %i2, 0, %o2
1562         b,pt            %xcc, 2f
1563          srl            %i3, 0, %o3
1564
1565 linux_syscall_trace:
1566         add             %sp, PTREGS_OFF, %o0
1567         call            syscall_trace
1568          clr            %o1
1569         mov             %i0, %o0
1570         mov             %i1, %o1
1571         mov             %i2, %o2
1572         mov             %i3, %o3
1573         b,pt            %xcc, 2f
1574          mov            %i4, %o4
1575
1576
1577         /* Linux 32-bit and SunOS system calls enter here... */
1578         .align  32
1579         .globl  linux_sparc_syscall32
1580 linux_sparc_syscall32:
1581         /* Direct access to user regs, much faster. */
1582         cmp             %g1, NR_SYSCALLS                        ! IEU1  Group
1583         bgeu,pn         %xcc, linux_sparc_ni_syscall            ! CTI
1584          srl            %i0, 0, %o0                             ! IEU0
1585         sll             %g1, 2, %l4                             ! IEU0  Group
1586         srl             %i4, 0, %o4                             ! IEU1
1587         lduw            [%l7 + %l4], %l7                        ! Load
1588         srl             %i1, 0, %o1                             ! IEU0  Group
1589         ldx             [%curptr + TI_FLAGS], %l0               ! Load
1590
1591         srl             %i5, 0, %o5                             ! IEU1
1592         srl             %i2, 0, %o2                             ! IEU0  Group
1593         andcc           %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
1594         bne,pn          %icc, linux_syscall_trace32             ! CTI
1595          mov            %i0, %l5                                ! IEU1
1596         call            %l7                                     ! CTI   Group brk forced
1597          srl            %i3, 0, %o3                             ! IEU0
1598         ba,a,pt         %xcc, 3f
1599
1600         /* Linux native and SunOS system calls enter here... */
1601         .align  32
1602         .globl  linux_sparc_syscall, ret_sys_call
1603 linux_sparc_syscall:
1604         /* Direct access to user regs, much faster. */
1605         cmp             %g1, NR_SYSCALLS                        ! IEU1  Group
1606         bgeu,pn         %xcc, linux_sparc_ni_syscall            ! CTI
1607          mov            %i0, %o0                                ! IEU0
1608         sll             %g1, 2, %l4                             ! IEU0  Group
1609         mov             %i1, %o1                                ! IEU1
1610         lduw            [%l7 + %l4], %l7                        ! Load
1611 4:      mov             %i2, %o2                                ! IEU0  Group
1612         ldx             [%curptr + TI_FLAGS], %l0               ! Load
1613
1614         mov             %i3, %o3                                ! IEU1
1615         mov             %i4, %o4                                ! IEU0  Group
1616         andcc           %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
1617         bne,pn          %icc, linux_syscall_trace               ! CTI   Group
1618          mov            %i0, %l5                                ! IEU0
1619 2:      call            %l7                                     ! CTI   Group brk forced
1620          mov            %i5, %o5                                ! IEU0
1621         nop
1622
1623 3:      stx             %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1624 ret_sys_call:
1625         ldx             [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3
1626         ldx             [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc
1627         sra             %o0, 0, %o0
1628         mov             %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
1629         sllx            %g2, 32, %g2
1630
1631         /* Check if force_successful_syscall_return()
1632          * was invoked.
1633          */
1634         ldub            [%curptr + TI_SYS_NOERROR], %l2
1635         brnz,a,pn       %l2, 80f
1636          stb            %g0, [%curptr + TI_SYS_NOERROR]
1637
1638         cmp             %o0, -ERESTART_RESTARTBLOCK
1639         bgeu,pn         %xcc, 1f
1640          andcc          %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6
1641 80:
1642         /* System call success, clear Carry condition code. */
1643         andn            %g3, %g2, %g3
1644         stx             %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]  
1645         bne,pn          %icc, linux_syscall_trace2
1646          add            %l1, 0x4, %l2                   ! npc = npc+4
1647         stx             %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
1648         ba,pt           %xcc, rtrap_clr_l6
1649          stx            %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
1650
1651 1:
1652         /* System call failure, set Carry condition code.
1653          * Also, get abs(errno) to return to the process.
1654          */
1655         andcc           %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %l6  
1656         sub             %g0, %o0, %o0
1657         or              %g3, %g2, %g3
1658         stx             %o0, [%sp + PTREGS_OFF + PT_V9_I0]
1659         mov             1, %l6
1660         stx             %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE]
1661         bne,pn          %icc, linux_syscall_trace2
1662          add            %l1, 0x4, %l2                   ! npc = npc+4
1663         stx             %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
1664
1665         b,pt            %xcc, rtrap
1666          stx            %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
1667 linux_syscall_trace2:
1668         add             %sp, PTREGS_OFF, %o0
1669         call            syscall_trace
1670          mov            1, %o1
1671         stx             %l1, [%sp + PTREGS_OFF + PT_V9_TPC]
1672         ba,pt           %xcc, rtrap
1673          stx            %l2, [%sp + PTREGS_OFF + PT_V9_TNPC]
1674
1675         .align          32
1676         .globl          __flushw_user
1677 __flushw_user:
1678         rdpr            %otherwin, %g1
1679         brz,pn          %g1, 2f
1680          clr            %g2
1681 1:      save            %sp, -128, %sp
1682         rdpr            %otherwin, %g1
1683         brnz,pt         %g1, 1b
1684          add            %g2, 1, %g2
1685 1:      sub             %g2, 1, %g2
1686         brnz,pt         %g2, 1b
1687          restore        %g0, %g0, %g0
1688 2:      retl
1689          nop
1690
1691 #ifdef CONFIG_SMP
1692         .globl          hard_smp_processor_id
1693 hard_smp_processor_id:
1694         __GET_CPUID(%o0)
1695         retl
1696          nop
1697 #endif