Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / sparc64 / vectors.S
1 /*
2  * <vectors.S>
3  *
4  * Sparc V9 Trap Table(s) with SpitFire/Cheetah extensions.
5  *
6  *   Copyright (C) 1996, 2001 David S. Miller (davem@caip.rutgers.edu)
7  *
8  *   This program is free software; you can redistribute it and/or
9  *   modify it under the terms of the GNU General Public License
10  *   version 2 as published by the Free Software Foundation.
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, write to the Free Software
19  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20  *   MA  02110-1301, USA.
21  *   This program is free software; you can redistribute it and/or
22  *   modify it under the terms of the GNU General Public License V2
23  *   as published by the Free Software Foundation
24  */
25
26 #define __ASSEMBLY__
27 #include "pstate.h"
28 #include <asm/asi.h>
29 #define ASI_BP ASI_PHYS_BYPASS_EC_E
30 #define PROM_ADDR 0x1fff0000000
31 #define SER_ADDR 0x1fe020003f8
32 #define TICK_INT_DIS 0x8000000000000000
33 #define TICK_INTERVAL 1*1000*1000
34
35         .section ".text.vectors", "ax"
36         .align 16384
37 /* Sparc64 trap table */
38         .globl trap_table, __divide_error, softint_irq, softint_irq_tl1
39         .register %g2, #scratch
40         .register %g3, #scratch
41         .register %g6, #scratch
42         .register %g7, #scratch
43 trap_table:
44 #define SPILL_WINDOW                                    \
45         btst    1, %sp;                                 \
46         be      spill_32bit;                            \
47          nop;                                           \
48         stx     %l0, [%sp + STACK_BIAS + 0x00];         \
49         stx     %l1, [%sp + STACK_BIAS + 0x08];         \
50         stx     %l2, [%sp + STACK_BIAS + 0x10];         \
51         stx     %l3, [%sp + STACK_BIAS + 0x18];         \
52         stx     %l4, [%sp + STACK_BIAS + 0x20];         \
53         stx     %l5, [%sp + STACK_BIAS + 0x28];         \
54         stx     %l6, [%sp + STACK_BIAS + 0x30];         \
55         stx     %l7, [%sp + STACK_BIAS + 0x38];         \
56         stx     %i0, [%sp + STACK_BIAS + 0x40];         \
57         stx     %i1, [%sp + STACK_BIAS + 0x48];         \
58         stx     %i2, [%sp + STACK_BIAS + 0x50];         \
59         stx     %i3, [%sp + STACK_BIAS + 0x58];         \
60         stx     %i4, [%sp + STACK_BIAS + 0x60];         \
61         stx     %i5, [%sp + STACK_BIAS + 0x68];         \
62         stx     %i6, [%sp + STACK_BIAS + 0x70];         \
63         stx     %i7, [%sp + STACK_BIAS + 0x78];         \
64         saved; retry; nop; nop; nop; nop; nop; nop;     \
65         nop; nop; nop; nop; nop;
66
67 #define FILL_WINDOW                                     \
68         btst    1, %sp;                                 \
69         be      fill_32bit;                             \
70          nop;                                           \
71         ldx     [%sp + STACK_BIAS + 0x00], %l0;         \
72         ldx     [%sp + STACK_BIAS + 0x08], %l1;         \
73         ldx     [%sp + STACK_BIAS + 0x10], %l2;         \
74         ldx     [%sp + STACK_BIAS + 0x18], %l3;         \
75         ldx     [%sp + STACK_BIAS + 0x20], %l4;         \
76         ldx     [%sp + STACK_BIAS + 0x28], %l5;         \
77         ldx     [%sp + STACK_BIAS + 0x30], %l6;         \
78         ldx     [%sp + STACK_BIAS + 0x38], %l7;         \
79         ldx     [%sp + STACK_BIAS + 0x40], %i0;         \
80         ldx     [%sp + STACK_BIAS + 0x48], %i1;         \
81         ldx     [%sp + STACK_BIAS + 0x50], %i2;         \
82         ldx     [%sp + STACK_BIAS + 0x58], %i3;         \
83         ldx     [%sp + STACK_BIAS + 0x60], %i4;         \
84         ldx     [%sp + STACK_BIAS + 0x68], %i5;         \
85         ldx     [%sp + STACK_BIAS + 0x70], %i6;         \
86         ldx     [%sp + STACK_BIAS + 0x78], %i7;         \
87         restored; retry; nop; nop; nop; nop; nop; nop;  \
88         nop; nop; nop; nop; nop;
89
90 #define CLEAN_WINDOW                                                    \
91         rdpr    %cleanwin, %l0;         add     %l0, 1, %l0;            \
92         wrpr    %l0, 0x0, %cleanwin;                                    \
93         clr     %o0;    clr     %o1;    clr     %o2;    clr     %o3;    \
94         clr     %o4;    clr     %o5;    clr     %o6;    clr     %o7;    \
95         clr     %l0;    clr     %l1;    clr     %l2;    clr     %l3;    \
96         clr     %l4;    clr     %l5;    clr     %l6;    clr     %l7;    \
97         retry;                                                          \
98         nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;
99
100 #define TRAP_IRQ(routine, level)                        \
101                 ba routine;  mov level, %g1; nop; nop; nop; nop; nop; nop;
102 #define BTRAP(lvl)                                      \
103                  ba bug; mov lvl, %g1; nop; nop; nop; nop; nop; nop;
104 #define BTRAPTL1(lvl) BTRAP(lvl)
105 #define BTRAPS(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) BTRAP(x+4) BTRAP(x+5) BTRAP(x+6) BTRAP(x+7)
106 #define BTRAPS4(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3)
107 #define TRAP_HANDLER(routine) ba routine; nop; nop; nop; nop; nop; nop; nop;
108
109 #define STACK_BIAS              2047
110         .globl  sparc64_ttable_tl0, sparc64_ttable_tl1
111 sparc64_ttable_tl0:
112                 ba entry; nop; nop; nop; nop; nop; nop; nop;! XXX remove
113                 ba entry; nop; nop; nop; nop; nop; nop; nop;! Power-on reset
114                 ba entry; nop; nop; nop; nop; nop; nop; nop;! Watchdog reset
115                 ba entry; nop; nop; nop; nop; nop; nop; nop;! External reset
116                 ba entry; nop; nop; nop; nop; nop; nop; nop;! Software reset
117                 ba entry; nop; nop; nop; nop; nop; nop; nop;! RED state
118                 BTRAP(0x06) BTRAP(0x07) BTRAPS(0x08)
119                 BTRAPS(0x10) BTRAPS(0x18)
120                 BTRAP(0x20) BTRAP(0x21) BTRAP(0x22) BTRAP(0x23)
121                 CLEAN_WINDOW ! 24-27
122                 BTRAPS(0x28)
123                 BTRAPS(0x30) BTRAPS(0x38)
124                 BTRAP(0x40) BTRAP(0x41) BTRAP(0x42) BTRAP(0x43)
125 tl0_irq4:       TRAP_IRQ(handler_irq, 4)
126 tl0_irq5:       TRAP_IRQ(handler_irq, 5)  TRAP_IRQ(handler_irq, 6)
127 tl0_irq7:       TRAP_IRQ(handler_irq, 7)  TRAP_IRQ(handler_irq, 8)
128 tl0_irq9:       TRAP_IRQ(handler_irq, 9)  TRAP_IRQ(handler_irq, 10)
129 tl0_irq11:      TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12)
130 tl0_irq13:      TRAP_IRQ(handler_irq, 13)
131 tl0_irq14:      TRAP_IRQ(softint_irq, 14)
132 tl0_irq15:      TRAP_IRQ(handler_irq, 15)
133                 BTRAPS(0x50) BTRAPS(0x58)
134                 BTRAPS4(0x60)
135                 TRAP_HANDLER(reload_IMMU_tlb)    ! 0x64 : instruction_access_MMU_miss
136                 TRAP_HANDLER(reload_IMMU_tlb)    ! 0x65 : instruction_access_MMU_miss
137                 TRAP_HANDLER(reload_IMMU_tlb)    ! 0x66 : instruction_access_MMU_miss
138                 TRAP_HANDLER(reload_IMMU_tlb)    ! 0x67 : instruction_access_MMU_miss
139                 TRAP_HANDLER(reload_DMMU_tlb)    ! 0x68 : data_access_MMU_miss
140                 TRAP_HANDLER(reload_DMMU_tlb)    ! 0x69 : data_access_MMU_miss
141                 TRAP_HANDLER(reload_DMMU_tlb)    ! 0x6A : data_access_MMU_miss
142                 TRAP_HANDLER(reload_DMMU_tlb)    ! 0x6B : data_access_MMU_miss
143                 BTRAPS4(0x6C)    ! data_access_protection
144                 BTRAPS(0x70) BTRAPS(0x78)
145 tl0_s0n:        SPILL_WINDOW
146 tl0_s1n:        SPILL_WINDOW
147 tl0_s2n:        SPILL_WINDOW
148 tl0_s3n:        SPILL_WINDOW
149 tl0_s4n:        SPILL_WINDOW
150 tl0_s5n:        SPILL_WINDOW
151 tl0_s6n:        SPILL_WINDOW
152 tl0_s7n:        SPILL_WINDOW
153 tl0_s0o:        SPILL_WINDOW
154 tl0_s1o:        SPILL_WINDOW
155 tl0_s2o:        SPILL_WINDOW
156 tl0_s3o:        SPILL_WINDOW
157 tl0_s4o:        SPILL_WINDOW
158 tl0_s5o:        SPILL_WINDOW
159 tl0_s6o:        SPILL_WINDOW
160 tl0_s7o:        SPILL_WINDOW
161 tl0_f0n:        FILL_WINDOW
162 tl0_f1n:        FILL_WINDOW
163 tl0_f2n:        FILL_WINDOW
164 tl0_f3n:        FILL_WINDOW
165 tl0_f4n:        FILL_WINDOW
166 tl0_f5n:        FILL_WINDOW
167 tl0_f6n:        FILL_WINDOW
168 tl0_f7n:        FILL_WINDOW
169 tl0_f0o:        FILL_WINDOW
170 tl0_f1o:        FILL_WINDOW
171 tl0_f2o:        FILL_WINDOW
172 tl0_f3o:        FILL_WINDOW
173 tl0_f4o:        FILL_WINDOW
174 tl0_f5o:        FILL_WINDOW
175 tl0_f6o:        FILL_WINDOW
176 tl0_f7o:        FILL_WINDOW
177 tl0_resv100:    BTRAPS(0x100) BTRAPS(0x108)
178 tl0_resv110:    BTRAPS(0x110) BTRAPS(0x118)
179 tl0_resv120:    BTRAPS(0x120) BTRAPS(0x128)
180 tl0_resv130:    BTRAPS(0x130) BTRAPS(0x138)
181 tl0_resv140:    BTRAPS(0x140) BTRAPS(0x148)
182 tl0_resv150:    BTRAPS(0x150) BTRAPS(0x158)
183 tl0_resv160:    BTRAPS(0x160) BTRAPS(0x168)
184 tl0_resv170:    BTRAPS(0x170) BTRAPS(0x178)
185 tl0_resv180:    BTRAPS(0x180) BTRAPS(0x188)
186 tl0_resv190:    BTRAPS(0x190) BTRAPS(0x198)
187 tl0_resv1a0:    BTRAPS(0x1a0) BTRAPS(0x1a8)
188 tl0_resv1b0:    BTRAPS(0x1b0) BTRAPS(0x1b8)
189 tl0_resv1c0:    BTRAPS(0x1c0) BTRAPS(0x1c8)
190 tl0_resv1d0:    BTRAPS(0x1d0) BTRAPS(0x1d8)
191 tl0_resv1e0:    BTRAPS(0x1e0) BTRAPS(0x1e8)
192 tl0_resv1f0:    BTRAPS(0x1f0) BTRAPS(0x1f8)
193
194 #undef BTRAPS
195 #define BTRAPS(x) BTRAPTL1(x) BTRAPTL1(x+1) BTRAPTL1(x+2) BTRAPTL1(x+3) BTRAPTL1(x+4) BTRAPTL1(x+5) BTRAPTL1(x+6) BTRAPTL1(x+7)
196
197 #define SKIP_IRQ(routine, level) \
198                 retry;  nop; nop; nop; nop; nop; nop; nop;
199
200 sparc64_ttable_tl1:
201                 BTRAPS(0x00) BTRAPS(0x08)
202                 BTRAPS(0x10) BTRAPS(0x18)
203                 BTRAPTL1(0x20) BTRAPTL1(0x21) BTRAPTL1(0x22) BTRAPTL1(0x23)
204                 CLEAN_WINDOW ! 24-27
205                 BTRAPS(0x28)
206                 BTRAPS(0x30) BTRAPS(0x38)
207                 BTRAPTL1(0x40) BTRAPTL1(0x41) BTRAPTL1(0x42) BTRAPTL1(0x43)
208 tl1_irq4:       TRAP_IRQ(handler_irq, 4)
209 tl1_irq5:       TRAP_IRQ(handler_irq, 5)  TRAP_IRQ(handler_irq, 6)
210 tl1_irq7:       TRAP_IRQ(handler_irq, 7)  TRAP_IRQ(handler_irq, 8)
211 tl1_irq9:       TRAP_IRQ(handler_irq, 9)  TRAP_IRQ(handler_irq, 10)
212 tl1_irq11:      TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12)
213 tl1_irq13:      TRAP_IRQ(handler_irq, 13)
214 tl1_irq14:      SKIP_IRQ(softint_irq, 14)
215 tl1_irq15:      TRAP_IRQ(handler_irq, 15)
216                 BTRAPS(0x50) BTRAPS(0x58)
217                 BTRAPS4(0x60)
218                 TRAP_HANDLER(reload_IMMU_tlb)    ! 0x64 : instruction_access_MMU_miss
219                 TRAP_HANDLER(reload_IMMU_tlb)    ! 0x65 : instruction_access_MMU_miss
220                 TRAP_HANDLER(reload_IMMU_tlb)    ! 0x66 : instruction_access_MMU_miss
221                 TRAP_HANDLER(reload_IMMU_tlb)    ! 0x67 : instruction_access_MMU_miss
222                 TRAP_HANDLER(reload_DMMU_tlb)    ! 0x68 : data_access_MMU_miss
223                 TRAP_HANDLER(reload_DMMU_tlb)    ! 0x69 : data_access_MMU_miss
224                 TRAP_HANDLER(reload_DMMU_tlb)    ! 0x6A : data_access_MMU_miss
225                 TRAP_HANDLER(reload_DMMU_tlb)    ! 0x6B : data_access_MMU_miss
226                 BTRAPS4(0x6C)    ! data_access_protection
227                 BTRAPS(0x70) BTRAPS(0x78)
228 tl1_s0n:        SPILL_WINDOW
229 tl1_s1n:        SPILL_WINDOW
230 tl1_s2n:        SPILL_WINDOW
231 tl1_s3n:        SPILL_WINDOW
232 tl1_s4n:        SPILL_WINDOW
233 tl1_s5n:        SPILL_WINDOW
234 tl1_s6n:        SPILL_WINDOW
235 tl1_s7n:        SPILL_WINDOW
236 tl1_s0o:        SPILL_WINDOW
237 tl1_s1o:        SPILL_WINDOW
238 tl1_s2o:        SPILL_WINDOW
239 tl1_s3o:        SPILL_WINDOW
240 tl1_s4o:        SPILL_WINDOW
241 tl1_s5o:        SPILL_WINDOW
242 tl1_s6o:        SPILL_WINDOW
243 tl1_s7o:        SPILL_WINDOW
244 tl1_f0n:        FILL_WINDOW
245 tl1_f1n:        FILL_WINDOW
246 tl1_f2n:        FILL_WINDOW
247 tl1_f3n:        FILL_WINDOW
248 tl1_f4n:        FILL_WINDOW
249 tl1_f5n:        FILL_WINDOW
250 tl1_f6n:        FILL_WINDOW
251 tl1_f7n:        FILL_WINDOW
252 tl1_f0o:        FILL_WINDOW
253 tl1_f1o:        FILL_WINDOW
254 tl1_f2o:        FILL_WINDOW
255 tl1_f3o:        FILL_WINDOW
256 tl1_f4o:        FILL_WINDOW
257 tl1_f5o:        FILL_WINDOW
258 tl1_f6o:        FILL_WINDOW
259 tl1_f7o:        FILL_WINDOW
260 tl1_resv100:    BTRAPS(0x100) BTRAPS(0x108)
261 tl1_resv110:    BTRAPS(0x110) BTRAPS(0x118)
262 tl1_resv120:    BTRAPS(0x120) BTRAPS(0x128)
263 tl1_resv130:    BTRAPS(0x130) BTRAPS(0x138)
264 tl1_resv140:    BTRAPS(0x140) BTRAPS(0x148)
265 tl1_resv150:    BTRAPS(0x150) BTRAPS(0x158)
266 tl1_resv160:    BTRAPS(0x160) BTRAPS(0x168)
267 tl1_resv170:    BTRAPS(0x170) BTRAPS(0x178)
268 tl1_resv180:    BTRAPS(0x180) BTRAPS(0x188)
269 tl1_resv190:    BTRAPS(0x190) BTRAPS(0x198)
270 tl1_resv1a0:    BTRAPS(0x1a0) BTRAPS(0x1a8)
271 tl1_resv1b0:    BTRAPS(0x1b0) BTRAPS(0x1b8)
272 tl1_resv1c0:    BTRAPS(0x1c0) BTRAPS(0x1c8)
273 tl1_resv1d0:    BTRAPS(0x1d0) BTRAPS(0x1d8)
274 tl1_resv1e0:    BTRAPS(0x1e0) BTRAPS(0x1e8)
275 tl1_resv1f0:    BTRAPS(0x1f0) BTRAPS(0x1f8)
276
277         .section ".data"
278         .align 8
279         .globl tlb_handler_stack_top, tlb_handler_stack_pointer, obp_ticks_pointer
280
281         ! Stack for the tlb MMU trap handlers
282 tlb_handler_stack_bottom:
283         .skip 8192
284 tlb_handler_stack_top:
285         .skip 8
286
287         ! MMU trap handler stack pointer
288 tlb_handler_stack_pointer:
289         .xword tlb_handler_stack_top
290
291         ! Pointer to current tick value
292 obp_ticks_pointer:
293         .xword 0
294
295         .section ".text", "ax"
296
297 spill_32bit:
298         srl     %sp, 0, %sp
299         stw     %l0, [%sp + 0x00]
300         stw     %l1, [%sp + 0x04]
301         stw     %l2, [%sp + 0x08]
302         stw     %l3, [%sp + 0x0c]
303         stw     %l4, [%sp + 0x10]
304         stw     %l5, [%sp + 0x14]
305         stw     %l6, [%sp + 0x18]
306         stw     %l7, [%sp + 0x1c]
307         stw     %i0, [%sp + 0x20]
308         stw     %i1, [%sp + 0x24]
309         stw     %i2, [%sp + 0x28]
310         stw     %i3, [%sp + 0x2c]
311         stw     %i4, [%sp + 0x30]
312         stw     %i5, [%sp + 0x34]
313         stw     %i6, [%sp + 0x38]
314         stw     %i7, [%sp + 0x3c]
315         saved
316         retry
317
318 fill_32bit:
319         srl     %sp, 0, %sp
320         lduw    [%sp + 0x00], %l0
321         lduw    [%sp + 0x04], %l1
322         lduw    [%sp + 0x08], %l2
323         lduw    [%sp + 0x0c], %l3
324         lduw    [%sp + 0x10], %l4
325         lduw    [%sp + 0x14], %l5
326         lduw    [%sp + 0x18], %l6
327         lduw    [%sp + 0x1c], %l7
328         lduw    [%sp + 0x20], %i0
329         lduw    [%sp + 0x24], %i1
330         lduw    [%sp + 0x28], %i2
331         lduw    [%sp + 0x2c], %i3
332         lduw    [%sp + 0x30], %i4
333         lduw    [%sp + 0x34], %i5
334         lduw    [%sp + 0x38], %i6
335         lduw    [%sp + 0x3c], %i7
336         restored
337         retry
338
339 /*
340  * SAVE_CPU_STATE and RESTORE_CPU_STATE are macros used to enable a context switch
341  * to C to occur within the MMU I/D TLB miss handlers.
342  *
343  * Because these handlers are called on a TLB miss, we cannot use flushw to store
344  * processor window state on the stack, as the memory areas used by each window's
345  * stack pointer may not be in the TLB, causing recursive TLB miss traps.
346  *
347  * For this reason, we save window state by manually rotating the window registers
348  * and saving their contents (along with other vital registers) into a special
349  * tlb_handler_stack defined above which is guaranteed to be locked in the TLB, and
350  * so won't cause issues with trap recursion.
351  *
352  * Once this process is complete, we remain in a TL=0, CWP=0 state (with IE=1 to allow
353  * window fill/spill traps if required), switch to our safe tlb_handler_stack and 
354  * invoke the miss handler.
355  */
356
357 #define SAVE_CPU_STATE(type) \
358         /* Set up our exception stack pointer in %g1 */ \
359         setx    tlb_handler_stack_pointer, %g7, %g6; \
360         ldx     [%g6], %g1; \
361         add     %g1, -0x510, %g1; \
362         \
363         /* First save the various state registers */ \
364         rdpr    %cwp, %g7; \
365         stx     %g7, [%g1]; \
366         rdpr    %cansave, %g7; \
367         stx     %g7, [%g1 + 0x8]; \
368         rdpr    %canrestore, %g7; \
369         stx     %g7, [%g1 + 0x10]; \
370         rdpr    %otherwin, %g7; \
371         stx     %g7, [%g1 + 0x18]; \
372         rdpr    %wstate, %g7; \
373         stx     %g7, [%g1 + 0x20]; \
374         rdpr    %cleanwin, %g7; \
375         stx     %g7, [%g1 + 0x28]; \
376         rdpr    %pstate, %g7; \
377         stx     %g7, [%g1 + 0x30]; \
378         \
379         rd      %y, %g7; \
380         stx     %g7, [%g1 + 0x38]; \
381         rd      %fprs, %g7; \
382         stx     %g7, [%g1 + 0x40]; \
383         \
384         rdpr    %tl, %g7; \
385         stx     %g7, [%g1 + 0x48]; \
386         \
387         /* Trap state */ \
388         add     %g1, 0x50, %g5; \
389         mov     4, %g6; \
390         \
391 save_trap_state_##type: \
392         deccc   %g6; \
393         wrpr    %g6, %tl; \
394         rdpr    %tpc, %g7; \
395         stx     %g7, [%g5]; \
396         rdpr    %tnpc, %g7; \
397         stx     %g7, [%g5 + 0x8]; \
398         rdpr    %tstate, %g7; \
399         stx     %g7, [%g5 + 0x10]; \
400         rdpr    %tt, %g7; \
401         stx     %g7, [%g5 + 0x18]; \
402         bne     save_trap_state_##type; \
403          add    %g5, 0x20, %g5; \
404         \
405         /* For 4 trap levels with 4 registers, memory required is 
406         4*8*4 = 0x80 bytes */ \
407         \
408         /* Save the o registers */ \
409         stx     %o0, [%g1 + 0xd0]; \
410         stx     %o1, [%g1 + 0xd8]; \
411         stx     %o2, [%g1 + 0xe0]; \
412         stx     %o3, [%g1 + 0xe8]; \
413         stx     %o4, [%g1 + 0xf0]; \
414         stx     %o5, [%g1 + 0xf8]; \
415         stx     %o6, [%g1 + 0x100]; \
416         stx     %o7, [%g1 + 0x108]; \
417         \
418         /* Now iterate through all of the windows saving all l and i registers */ \
419         add     %g1, 0x110, %g5; \
420         \
421         /* Get the number of windows in %g6 */ \
422         rdpr    %ver, %g6; \
423         and     %g6, 0xf, %g6; \
424         inc     %g6; \
425         \
426 save_cpu_window_##type: \
427         deccc   %g6; \
428         wrpr    %g6, %cwp; \
429         stx     %l0, [%g5]; \
430         stx     %l1, [%g5 + 0x8]; \
431         stx     %l2, [%g5 + 0x10]; \
432         stx     %l3, [%g5 + 0x18]; \
433         stx     %l4, [%g5 + 0x20]; \
434         stx     %l5, [%g5 + 0x28]; \
435         stx     %l6, [%g5 + 0x30]; \
436         stx     %l7, [%g5 + 0x38]; \
437         stx     %i0, [%g5 + 0x40]; \
438         stx     %i1, [%g5 + 0x48]; \
439         stx     %i2, [%g5 + 0x50]; \
440         stx     %i3, [%g5 + 0x58]; \
441         stx     %i4, [%g5 + 0x60]; \
442         stx     %i5, [%g5 + 0x68]; \
443         stx     %i6, [%g5 + 0x70]; \
444         stx     %i7, [%g5 + 0x78]; \
445         bne     save_cpu_window_##type; \
446          add    %g5, 0x80, %g5; \
447         \
448         /* For 8 windows with 16 registers to save in the window, memory required
449         is 16*8*8 = 0x400 bytes */ \
450         \
451         /* Now we should be in window 0 so update the other window registers */ \
452         rdpr    %ver, %g6; \
453         and     %g6, 0xf, %g6; \
454         dec     %g6; \
455         wrpr    %g6, %cansave; \
456         \
457         wrpr    %g0, %cleanwin; \
458         wrpr    %g0, %canrestore; \
459         wrpr    %g0, %otherwin; \
460         \
461         /* Update our exception stack pointer */ \
462         setx    tlb_handler_stack_pointer, %g7, %g6; \
463         stx     %g1, [%g6];
464
465
466 #define RESTORE_CPU_STATE(type) \
467         /* Set up our exception stack pointer in %g1 */ \
468         setx    tlb_handler_stack_pointer, %g7, %g6; \
469         ldx     [%g6], %g1; \
470         \
471         /* Get the number of windows in %g6 */ \
472         rdpr    %ver, %g6; \
473         and     %g6, 0xf, %g6; \
474         inc     %g6; \
475         \
476         /* Now iterate through all of the windows restoring all l and i registers */ \
477         add     %g1, 0x110, %g5; \
478         \
479 restore_cpu_window_##type: \
480         deccc   %g6; \
481         wrpr    %g6, %cwp; \
482         ldx     [%g5], %l0; \
483         ldx     [%g5 + 0x8], %l1; \
484         ldx     [%g5 + 0x10], %l2; \
485         ldx     [%g5 + 0x18], %l3; \
486         ldx     [%g5 + 0x20], %l4; \
487         ldx     [%g5 + 0x28], %l5; \
488         ldx     [%g5 + 0x30], %l6; \
489         ldx     [%g5 + 0x38], %l7; \
490         ldx     [%g5 + 0x40], %i0; \
491         ldx     [%g5 + 0x48], %i1; \
492         ldx     [%g5 + 0x50], %i2; \
493         ldx     [%g5 + 0x58], %i3; \
494         ldx     [%g5 + 0x60], %i4; \
495         ldx     [%g5 + 0x68], %i5; \
496         ldx     [%g5 + 0x70], %i6; \
497         ldx     [%g5 + 0x78], %i7; \
498         bne     restore_cpu_window_##type; \
499          add    %g5, 0x80, %g5; \
500         \
501         /* Restore the window registers to their original value */ \
502         ldx     [%g1], %g7; \
503         wrpr    %g7, %cwp; \
504         ldx     [%g1 + 0x8], %g7; \
505         wrpr    %g7, %cansave; \
506         ldx     [%g1 + 0x10], %g7; \
507         wrpr    %g7, %canrestore; \
508         ldx     [%g1 + 0x18], %g7; \
509         wrpr    %g7, %otherwin; \
510         ldx     [%g1 + 0x20], %g7; \
511         wrpr    %g7, %wstate; \
512         ldx     [%g1 + 0x28], %g7; \
513         wrpr    %g7, %cleanwin; \
514         ldx     [%g1 + 0x30], %g7; \
515         wrpr    %g7, %pstate; \
516         \
517         /* Restore the o registers */ \
518         ldx     [%g1 + 0xd0], %o0; \
519         ldx     [%g1 + 0xd8], %o1; \
520         ldx     [%g1 + 0xe0], %o2; \
521         ldx     [%g1 + 0xe8], %o3; \
522         ldx     [%g1 + 0xf0], %o4; \
523         ldx     [%g1 + 0xf8], %o5; \
524         ldx     [%g1 + 0x100], %o6; \
525         ldx     [%g1 + 0x108], %o7; \
526         \
527         /* Restore the trap state */ \
528         add     %g1, 0x50, %g5; \
529         mov     4, %g6; \
530         \
531 restore_trap_state_##type: \
532         deccc   %g6; \
533         wrpr    %g6, %tl; \
534         ldx     [%g5], %g7; \
535         wrpr    %g7, %tpc; \
536         ldx     [%g5 + 0x8], %g7; \
537         wrpr    %g7, %tnpc; \
538         ldx     [%g5 + 0x10], %g7; \
539         wrpr    %g7, %tstate; \
540         ldx     [%g5 + 0x18], %g7; \
541         wrpr    %g7, %tt; \
542         bne     restore_trap_state_##type; \
543          add    %g5, 0x20, %g5; \
544         \
545         ldx     [%g1 + 0x38], %g7; \
546         wr      %g7, 0, %y; \
547         ldx     [%g1 + 0x40], %g7; \
548         wr      %g7, 0, %fprs; \
549         ldx     [%g1 + 0x48], %g7; \
550         wrpr    %g7, %tl; \
551         \
552         /* Restore exception stack pointer to previous value */ \
553         setx    tlb_handler_stack_pointer, %g7, %g6; \
554         add     %g1, 0x510, %g1; \
555         stx     %g1, [%g6];
556
557
558         .globl reload_DMMU_tlb, reload_IMMU_tlb, bug
559
560 reload_DMMU_tlb:
561
562         SAVE_CPU_STATE(dtlb)
563
564         /* Switch to TLB locked stack space (note we add an additional 192 bytes required for
565            gcc to save its arguments when building with -O0) */
566         add     %g1, -STACK_BIAS - 192, %sp
567
568         /* Enable interrupts for window spill/fill traps */
569         rdpr    %pstate, %g7
570         or      %g7, PSTATE_IE, %g7
571         wrpr    %g7, %pstate    
572
573         call    dtlb_miss_handler
574          nop
575
576         /* Disable interrupts */
577         rdpr    %pstate, %g7
578         andn    %g7, PSTATE_IE, %g7
579         wrpr    %g7, %pstate
580
581         RESTORE_CPU_STATE(dtlb)
582
583         retry
584
585 reload_IMMU_tlb:
586
587         SAVE_CPU_STATE(itlb)
588
589         /* Switch to TLB locked stack space (note we add an additional 192 bytes required for
590            gcc to save its arguments when building with -O0) */
591         add     %g1, -STACK_BIAS - 192, %sp
592
593         /* Enable interrupts for window spill/fill traps */
594         rdpr    %pstate, %g7
595         or      %g7, PSTATE_IE, %g7
596         wrpr    %g7, %pstate    
597
598         call    itlb_miss_handler
599          nop
600
601         /* Disable interrupts */
602         rdpr    %pstate, %g7
603         andn    %g7, PSTATE_IE, %g7
604         wrpr    %g7, %pstate
605
606         RESTORE_CPU_STATE(itlb)
607
608         retry
609
610 softint_irq_tl1:
611 softint_irq:
612         mov     1, %g2
613         /* clear tick interrupt */
614         wr      %g2, 0x0, %clear_softint
615         sll     %g2, %g1, %g2
616         sra     %g2, 0, %g2
617         /* clear softint interrupt */
618         wr      %g2, 0x0, %clear_softint
619
620         setx    TICK_INT_DIS, %g2, %g1
621         rd      %tick, %g2
622         and     %g1, %g2, %g1
623         brnz,pn %g1, tick_compare_disabled
624          nop
625
626         /* update tick value if pointer set */
627         setx    obp_ticks_pointer, %g3, %g1
628         ldx     [%g1], %g3
629         brz     %g3, tick_rearm
630          nop
631
632         ldx     [%g3], %g1
633         add     %g1, 10, %g1    ! 100Hz = 10ms
634         stx     %g1, [%g3]
635          
636 tick_rearm:         
637         set     TICK_INTERVAL, %g1
638         add     %g1, %g2, %g1
639         wr      %g1, 0, %tick_cmpr
640 tick_compare_disabled:
641         retry
642
643 handler_irq:
644 __divide_error:
645 bug:
646         /* Dump the exception and its context */
647         ! Set up CPU state
648         ! Don't change the global register set or we lose %g1 (exception level)
649         rdpr    %pstate, %g2
650         or      %g2, PSTATE_PRIV, %g2
651         wrpr    %g2, %pstate
652         wr      %g0, 0, %fprs
653
654         ! Jump to ROM ...
655         setx    _start, %g2, %g3
656         setx    highmem, %g2, %g4
657         sub     %g4, %g3, %g4
658         setx    PROM_ADDR, %g2, %g3
659         add     %g4, %g3, %g3
660         jmp     %g3
661         ! ... while disabling I/D MMUs and caches
662          stxa    %g0, [%g0] ASI_LSU_CONTROL
663
664 highmem:
665         ! Extract NWINDOWS from %ver
666         rdpr    %ver, %g2
667         and     %g2, 0xf, %g2
668         wrpr    %g2, 0, %cleanwin
669         wrpr    %g2, 0, %cansave
670         wrpr    %g0, 0, %canrestore
671         wrpr    %g0, 0, %otherwin
672         wrpr    %g0, 0, %wstate
673
674         b       dump_exception
675          nop
676
677 outstr:
678         /* void outstr (unsigned long port, const unsigned char *str);
679          * Writes a string on an IO port.
680          */
681 1:      ldub    [%o1], %o3
682         cmp     %o3, 0
683         be      2f
684          nop
685         stba    %o3, [%o0] ASI_BP
686         b       1b
687          inc    %o1
688 2:      retl
689          nop
690
691 outdigit:
692         /* void outdigit (unsigned long port, uint8_t digit);
693          * Dumps a single digit on serial port.
694          */
695         add     %o1, '0', %o1
696         retl
697          stba   %o1, [%o0] ASI_BP
698
699 outhex:
700         /* void outhex (unsigned long port, uint64_t value);
701          * Dumps a 64 bits hex number on serial port
702          */
703         mov     %o1, %o2
704         set     60, %o3
705         srlx    %o2, %o3, %o1
706 1:      and     %o1, 0xf, %o1
707         cmp     %o1, 9
708         bgt     2f
709          nop
710         b       3f
711          add    %o1, '0', %o1
712 2:      add     %o1, 'a' - 10, %o1
713 3:      stba    %o1, [%o0] ASI_BP
714         subcc   %o3, 4, %o3
715         bge     1b
716          srlx   %o2, %o3, %o1
717         retl
718          nop
719
720         /* void dump_exception ();
721          *
722          * Dump a message when catching an exception
723          */
724 dump_exception:
725         setx    SER_ADDR, %o3, %o0
726         set     _start, %g3
727         set     (_BUG_message_0), %o1
728         sub     %o1, %g3, %g4
729         setx    PROM_ADDR, %g2, %g3
730         add     %g4, %g3, %g3
731         call    outstr
732          mov    %g3, %o1
733
734         call    outhex
735          mov    %g1, %o1
736
737         call    outstr
738          add    %g3, (_BUG_message_1 -  _BUG_message_0), %o1
739
740         call    outhex
741          rdpr   %tpc, %o1
742
743         call    outstr
744          add    %g3, (_BUG_message_2 -  _BUG_message_0), %o1
745
746         call    outhex
747          rdpr   %tnpc, %o1
748
749         call    outstr
750          add    %g3, (_BUG_message_3 -  _BUG_message_0), %o1
751
752 _forever:
753         /* Loop forever */
754         b       _forever                                  ;
755          nop
756
757         .section .rodata
758 _BUG_message_0:
759         .string "Unhandled Exception 0x"
760 _BUG_message_1:
761         .string "\nPC = 0x"
762 _BUG_message_2:
763         .string " NPC = 0x"
764 _BUG_message_3:
765         .string "\nStopping execution\n"