|
|
1.1 root 1: /*
2: * <vectors.S>
3: *
4: * Sparc V9 Trap Table(s) with SpitFire/Cheetah extensions.
5: *
6: * Copyright (C) 1996, 2001 David S. Miller ([email protected])
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 10*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
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: .section ".text", "ax"
292:
293: spill_32bit:
294: srl %sp, 0, %sp
295: stw %l0, [%sp + 0x00]
296: stw %l1, [%sp + 0x04]
297: stw %l2, [%sp + 0x08]
298: stw %l3, [%sp + 0x0c]
299: stw %l4, [%sp + 0x10]
300: stw %l5, [%sp + 0x14]
301: stw %l6, [%sp + 0x18]
302: stw %l7, [%sp + 0x1c]
303: stw %i0, [%sp + 0x20]
304: stw %i1, [%sp + 0x24]
305: stw %i2, [%sp + 0x28]
306: stw %i3, [%sp + 0x2c]
307: stw %i4, [%sp + 0x30]
308: stw %i5, [%sp + 0x34]
309: stw %i6, [%sp + 0x38]
310: stw %i7, [%sp + 0x3c]
311: saved
312: retry
313:
314: fill_32bit:
315: srl %sp, 0, %sp
316: lduw [%sp + 0x00], %l0
317: lduw [%sp + 0x04], %l1
318: lduw [%sp + 0x08], %l2
319: lduw [%sp + 0x0c], %l3
320: lduw [%sp + 0x10], %l4
321: lduw [%sp + 0x14], %l5
322: lduw [%sp + 0x18], %l6
323: lduw [%sp + 0x1c], %l7
324: lduw [%sp + 0x20], %i0
325: lduw [%sp + 0x24], %i1
326: lduw [%sp + 0x28], %i2
327: lduw [%sp + 0x2c], %i3
328: lduw [%sp + 0x30], %i4
329: lduw [%sp + 0x34], %i5
330: lduw [%sp + 0x38], %i6
331: lduw [%sp + 0x3c], %i7
332: restored
333: retry
334:
335: /*
336: * SAVE_CPU_STATE and RESTORE_CPU_STATE are macros used to enable a context switch
337: * to C to occur within the MMU I/D TLB miss handlers.
338: *
339: * Because these handlers are called on a TLB miss, we cannot use flushw to store
340: * processor window state on the stack, as the memory areas used by each window's
341: * stack pointer may not be in the TLB, causing recursive TLB miss traps.
342: *
343: * For this reason, we save window state by manually rotating the window registers
344: * and saving their contents (along with other vital registers) into a special
345: * tlb_handler_stack defined above which is guaranteed to be locked in the TLB, and
346: * so won't cause issues with trap recursion.
347: *
348: * Once this process is complete, we remain in a TL=0, CWP=0 state (with IE=1 to allow
349: * window fill/spill traps if required), switch to our safe tlb_handler_stack and
350: * invoke the miss handler.
351: */
352:
353: #define SAVE_CPU_STATE(type) \
354: /* Set up our exception stack pointer in %g1 */ \
355: setx tlb_handler_stack_pointer, %g7, %g6; \
356: ldx [%g6], %g1; \
357: add %g1, -0x510, %g1; \
358: \
359: /* First save the various state registers */ \
360: rdpr %cwp, %g7; \
361: stx %g7, [%g1]; \
362: rdpr %cansave, %g7; \
363: stx %g7, [%g1 + 0x8]; \
364: rdpr %canrestore, %g7; \
365: stx %g7, [%g1 + 0x10]; \
366: rdpr %otherwin, %g7; \
367: stx %g7, [%g1 + 0x18]; \
368: rdpr %wstate, %g7; \
369: stx %g7, [%g1 + 0x20]; \
370: rdpr %cleanwin, %g7; \
371: stx %g7, [%g1 + 0x28]; \
372: rdpr %pstate, %g7; \
373: stx %g7, [%g1 + 0x30]; \
374: \
375: rd %y, %g7; \
376: stx %g7, [%g1 + 0x38]; \
377: rd %fprs, %g7; \
378: stx %g7, [%g1 + 0x40]; \
379: \
380: rdpr %tl, %g7; \
381: stx %g7, [%g1 + 0x48]; \
382: \
383: /* Trap state */ \
384: add %g1, 0x50, %g5; \
385: mov 4, %g6; \
386: \
387: save_trap_state_##type: \
388: deccc %g6; \
389: wrpr %g6, %tl; \
390: rdpr %tpc, %g7; \
391: stx %g7, [%g5]; \
392: rdpr %tnpc, %g7; \
393: stx %g7, [%g5 + 0x8]; \
394: rdpr %tstate, %g7; \
395: stx %g7, [%g5 + 0x10]; \
396: rdpr %tt, %g7; \
397: stx %g7, [%g5 + 0x18]; \
398: bne save_trap_state_##type; \
399: add %g5, 0x20, %g5; \
400: \
401: /* For 4 trap levels with 4 registers, memory required is
402: 4*8*4 = 0x80 bytes */ \
403: \
404: /* Save the o registers */ \
405: stx %o0, [%g1 + 0xd0]; \
406: stx %o1, [%g1 + 0xd8]; \
407: stx %o2, [%g1 + 0xe0]; \
408: stx %o3, [%g1 + 0xe8]; \
409: stx %o4, [%g1 + 0xf0]; \
410: stx %o5, [%g1 + 0xf8]; \
411: stx %o6, [%g1 + 0x100]; \
412: stx %o7, [%g1 + 0x108]; \
413: \
414: /* Now iterate through all of the windows saving all l and i registers */ \
415: add %g1, 0x110, %g5; \
416: \
417: /* Get the number of windows in %g6 */ \
418: rdpr %ver, %g6; \
419: and %g6, 0xf, %g6; \
420: inc %g6; \
421: \
422: save_cpu_window_##type: \
423: deccc %g6; \
424: wrpr %g6, %cwp; \
425: stx %l0, [%g5]; \
426: stx %l1, [%g5 + 0x8]; \
427: stx %l2, [%g5 + 0x10]; \
428: stx %l3, [%g5 + 0x18]; \
429: stx %l4, [%g5 + 0x20]; \
430: stx %l5, [%g5 + 0x28]; \
431: stx %l6, [%g5 + 0x30]; \
432: stx %l7, [%g5 + 0x38]; \
433: stx %i0, [%g5 + 0x40]; \
434: stx %i1, [%g5 + 0x48]; \
435: stx %i2, [%g5 + 0x50]; \
436: stx %i3, [%g5 + 0x58]; \
437: stx %i4, [%g5 + 0x60]; \
438: stx %i5, [%g5 + 0x68]; \
439: stx %i6, [%g5 + 0x70]; \
440: stx %i7, [%g5 + 0x78]; \
441: bne save_cpu_window_##type; \
442: add %g5, 0x80, %g5; \
443: \
444: /* For 8 windows with 16 registers to save in the window, memory required
445: is 16*8*8 = 0x400 bytes */ \
446: \
447: /* Now we should be in window 0 so update the other window registers */ \
448: rdpr %ver, %g6; \
449: and %g6, 0xf, %g6; \
450: dec %g6; \
451: wrpr %g6, %cansave; \
452: \
453: wrpr %g0, %cleanwin; \
454: wrpr %g0, %canrestore; \
455: wrpr %g0, %otherwin; \
456: \
457: /* Update our exception stack pointer */ \
458: setx tlb_handler_stack_pointer, %g7, %g6; \
459: stx %g1, [%g6];
460:
461:
462: #define RESTORE_CPU_STATE(type) \
463: /* Set up our exception stack pointer in %g1 */ \
464: setx tlb_handler_stack_pointer, %g7, %g6; \
465: ldx [%g6], %g1; \
466: \
467: /* Get the number of windows in %g6 */ \
468: rdpr %ver, %g6; \
469: and %g6, 0xf, %g6; \
470: inc %g6; \
471: \
472: /* Now iterate through all of the windows restoring all l and i registers */ \
473: add %g1, 0x110, %g5; \
474: \
475: restore_cpu_window_##type: \
476: deccc %g6; \
477: wrpr %g6, %cwp; \
478: ldx [%g5], %l0; \
479: ldx [%g5 + 0x8], %l1; \
480: ldx [%g5 + 0x10], %l2; \
481: ldx [%g5 + 0x18], %l3; \
482: ldx [%g5 + 0x20], %l4; \
483: ldx [%g5 + 0x28], %l5; \
484: ldx [%g5 + 0x30], %l6; \
485: ldx [%g5 + 0x38], %l7; \
486: ldx [%g5 + 0x40], %i0; \
487: ldx [%g5 + 0x48], %i1; \
488: ldx [%g5 + 0x50], %i2; \
489: ldx [%g5 + 0x58], %i3; \
490: ldx [%g5 + 0x60], %i4; \
491: ldx [%g5 + 0x68], %i5; \
492: ldx [%g5 + 0x70], %i6; \
493: ldx [%g5 + 0x78], %i7; \
494: bne restore_cpu_window_##type; \
495: add %g5, 0x80, %g5; \
496: \
497: /* Restore the window registers to their original value */ \
498: ldx [%g1], %g7; \
499: wrpr %g7, %cwp; \
500: ldx [%g1 + 0x8], %g7; \
501: wrpr %g7, %cansave; \
502: ldx [%g1 + 0x10], %g7; \
503: wrpr %g7, %canrestore; \
504: ldx [%g1 + 0x18], %g7; \
505: wrpr %g7, %otherwin; \
506: ldx [%g1 + 0x20], %g7; \
507: wrpr %g7, %wstate; \
508: ldx [%g1 + 0x28], %g7; \
509: wrpr %g7, %cleanwin; \
510: ldx [%g1 + 0x30], %g7; \
511: wrpr %g7, %pstate; \
512: \
513: /* Restore the o registers */ \
514: ldx [%g1 + 0xd0], %o0; \
515: ldx [%g1 + 0xd8], %o1; \
516: ldx [%g1 + 0xe0], %o2; \
517: ldx [%g1 + 0xe8], %o3; \
518: ldx [%g1 + 0xf0], %o4; \
519: ldx [%g1 + 0xf8], %o5; \
520: ldx [%g1 + 0x100], %o6; \
521: ldx [%g1 + 0x108], %o7; \
522: \
523: /* Restore the trap state */ \
524: add %g1, 0x50, %g5; \
525: mov 4, %g6; \
526: \
527: restore_trap_state_##type: \
528: deccc %g6; \
529: wrpr %g6, %tl; \
530: ldx [%g5], %g7; \
531: wrpr %g7, %tpc; \
532: ldx [%g5 + 0x8], %g7; \
533: wrpr %g7, %tnpc; \
534: ldx [%g5 + 0x10], %g7; \
535: wrpr %g7, %tstate; \
536: ldx [%g5 + 0x18], %g7; \
537: wrpr %g7, %tt; \
538: bne restore_trap_state_##type; \
539: add %g5, 0x20, %g5; \
540: \
541: ldx [%g1 + 0x38], %g7; \
542: wr %g7, 0, %y; \
543: ldx [%g1 + 0x40], %g7; \
544: wr %g7, 0, %fprs; \
545: ldx [%g1 + 0x48], %g7; \
546: wrpr %g7, %tl; \
547: \
548: /* Restore exception stack pointer to previous value */ \
549: setx tlb_handler_stack_pointer, %g7, %g6; \
550: add %g1, 0x510, %g1; \
551: stx %g1, [%g6];
552:
553:
554: .globl reload_DMMU_tlb, reload_IMMU_tlb, bug
555:
556: reload_DMMU_tlb:
557:
558: SAVE_CPU_STATE(dtlb)
559:
560: /* Switch to TLB locked stack space (note we add an additional 192 bytes required for
561: gcc to save its arguments when building with -O0) */
562: add %g1, -STACK_BIAS - 192, %sp
563:
564: /* Enable interrupts for window spill/fill traps */
565: rdpr %pstate, %g7
566: or %g7, PSTATE_IE, %g7
567: wrpr %g7, %pstate
568:
569: call dtlb_miss_handler
570: nop
571:
572: /* Disable interrupts */
573: rdpr %pstate, %g7
574: andn %g7, PSTATE_IE, %g7
575: wrpr %g7, %pstate
576:
577: RESTORE_CPU_STATE(dtlb)
578:
579: retry
580:
581: reload_IMMU_tlb:
582:
583: SAVE_CPU_STATE(itlb)
584:
585: /* Switch to TLB locked stack space (note we add an additional 192 bytes required for
586: gcc to save its arguments when building with -O0) */
587: add %g1, -STACK_BIAS - 192, %sp
588:
589: /* Enable interrupts for window spill/fill traps */
590: rdpr %pstate, %g7
591: or %g7, PSTATE_IE, %g7
592: wrpr %g7, %pstate
593:
594: call itlb_miss_handler
595: nop
596:
597: /* Disable interrupts */
598: rdpr %pstate, %g7
599: andn %g7, PSTATE_IE, %g7
600: wrpr %g7, %pstate
601:
602: RESTORE_CPU_STATE(itlb)
603:
604: retry
605:
606: softint_irq_tl1:
607: softint_irq:
608: mov 1, %g2
609: /* clear tick interrupt */
610: wr %g2, 0x0, %clear_softint
611: sll %g2, %g1, %g2
612: sra %g2, 0, %g2
613: /* clear softint interrupt */
614: wr %g2, 0x0, %clear_softint
615:
616: setx TICK_INT_DIS, %g2, %g1
617: rd %tick, %g2
618: and %g1, %g2, %g1
619: brnz,pn %g1, tick_compare_disabled
620: nop
621: set TICK_INTERVAL, %g1
622: add %g1, %g2, %g1
623: wr %g1, 0, %tick_cmpr
624: tick_compare_disabled:
625: retry
626:
627: handler_irq:
628: __divide_error:
629: bug:
630: /* Dump the exception and its context */
631: ! Set up CPU state
632: ! Don't change the global register set or we lose %g1 (exception level)
633: rdpr %pstate, %g2
634: or %g2, PSTATE_PRIV, %g2
635: wrpr %g2, %pstate
636: wr %g0, 0, %fprs
637:
638: ! Jump to ROM ...
639: setx _start, %g2, %g3
640: setx highmem, %g2, %g4
641: sub %g4, %g3, %g4
642: setx PROM_ADDR, %g2, %g3
643: add %g4, %g3, %g3
644: jmp %g3
645: ! ... while disabling I/D MMUs and caches
646: stxa %g0, [%g0] ASI_LSU_CONTROL
647:
648: highmem:
649: ! Extract NWINDOWS from %ver
650: rdpr %ver, %g2
651: and %g2, 0xf, %g2
652: wrpr %g2, 0, %cleanwin
653: wrpr %g2, 0, %cansave
654: wrpr %g0, 0, %canrestore
655: wrpr %g0, 0, %otherwin
656: wrpr %g0, 0, %wstate
657:
658: b dump_exception
659: nop
660:
661: outstr:
662: /* void outstr (unsigned long port, const unsigned char *str);
663: * Writes a string on an IO port.
664: */
665: 1: ldub [%o1], %o3
666: cmp %o3, 0
667: be 2f
668: nop
669: stba %o3, [%o0] ASI_BP
670: b 1b
671: inc %o1
672: 2: retl
673: nop
674:
675: outdigit:
676: /* void outdigit (unsigned long port, uint8_t digit);
677: * Dumps a single digit on serial port.
678: */
679: add %o1, '0', %o1
680: retl
681: stba %o1, [%o0] ASI_BP
682:
683: outhex:
684: /* void outhex (unsigned long port, uint64_t value);
685: * Dumps a 64 bits hex number on serial port
686: */
687: mov %o1, %o2
688: set 60, %o3
689: srlx %o2, %o3, %o1
690: 1: and %o1, 0xf, %o1
691: cmp %o1, 9
692: bgt 2f
693: nop
694: b 3f
695: add %o1, '0', %o1
696: 2: add %o1, 'a' - 10, %o1
697: 3: stba %o1, [%o0] ASI_BP
698: subcc %o3, 4, %o3
699: bge 1b
700: srlx %o2, %o3, %o1
701: retl
702: nop
703:
704: /* void dump_exception ();
705: *
706: * Dump a message when catching an exception
707: */
708: dump_exception:
709: setx SER_ADDR, %o3, %o0
710: set _start, %g3
711: set (_BUG_message_0), %o1
712: sub %o1, %g3, %g4
713: setx PROM_ADDR, %g2, %g3
714: add %g4, %g3, %g3
715: call outstr
716: mov %g3, %o1
717:
718: call outhex
719: mov %g1, %o1
720:
721: call outstr
722: add %g3, (_BUG_message_1 - _BUG_message_0), %o1
723:
724: call outhex
725: rdpr %tpc, %o1
726:
727: call outstr
728: add %g3, (_BUG_message_2 - _BUG_message_0), %o1
729:
730: call outhex
731: rdpr %tnpc, %o1
732:
733: call outstr
734: add %g3, (_BUG_message_3 - _BUG_message_0), %o1
735:
736: _forever:
737: /* Loop forever */
738: b _forever ;
739: nop
740:
741: .section .rodata
742: _BUG_message_0:
743: .string "Unhandled Exception 0x"
744: _BUG_message_1:
745: .string "\nPC = 0x"
746: _BUG_message_2:
747: .string " NPC = 0x"
748: _BUG_message_3:
749: .string "\nStopping execution\n"
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.