source: mainline/kernel/arch/sparc64/src/trap/sun4u/trap_table.S@ cade9c1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since cade9c1 was aef669b, checked in by Jakub Jermar <jakub@…>, 11 years ago

Fix comment.

  • Property mode set to 100644
File size: 26.5 KB
Line 
1#
2# Copyright (c) 2005 Jakub Jermar
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions
7# are met:
8#
9# - Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# - Redistributions in binary form must reproduce the above copyright
12# notice, this list of conditions and the following disclaimer in the
13# documentation and/or other materials provided with the distribution.
14# - The name of the author may not be used to endorse or promote products
15# derived from this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28
29/**
30 * @file
31 * @brief This file contains kernel trap table.
32 */
33
34.register %g2, #scratch
35.register %g3, #scratch
36
37.text
38
39#include <arch/trap/trap_table.h>
40#include <arch/trap/regwin.h>
41#include <arch/trap/interrupt.h>
42#include <arch/trap/exception.h>
43#include <arch/trap/syscall.h>
44#include <arch/trap/mmu.h>
45#include <arch/mm/mmu.h>
46#include <arch/mm/page.h>
47#include <arch/stack.h>
48#include <arch/regdef.h>
49
50#define TABLE_SIZE TRAP_TABLE_SIZE
51#define ENTRY_SIZE TRAP_TABLE_ENTRY_SIZE
52
53/*
54 * Kernel trap table.
55 */
56.align TABLE_SIZE
57.global trap_table
58trap_table:
59
60/* TT = 0x08, TL = 0, instruction_access_exception */
61.org trap_table + TT_INSTRUCTION_ACCESS_EXCEPTION*ENTRY_SIZE
62.global instruction_access_exception_tl0
63instruction_access_exception_tl0:
64 wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
65 mov TT_INSTRUCTION_ACCESS_EXCEPTION, %g2
66 clr %g5
67 PREEMPTIBLE_HANDLER exc_dispatch
68
69/* TT = 0x0a, TL = 0, instruction_access_error */
70.org trap_table + TT_INSTRUCTION_ACCESS_ERROR*ENTRY_SIZE
71.global instruction_access_error_tl0
72instruction_access_error_tl0:
73 mov TT_INSTRUCTION_ACCESS_ERROR, %g2
74 clr %g5
75 PREEMPTIBLE_HANDLER exc_dispatch
76
77/* TT = 0x10, TL = 0, illegal_instruction */
78.org trap_table + TT_ILLEGAL_INSTRUCTION*ENTRY_SIZE
79.global illegal_instruction_tl0
80illegal_instruction_tl0:
81 mov TT_ILLEGAL_INSTRUCTION, %g2
82 clr %g5
83 PREEMPTIBLE_HANDLER exc_dispatch
84
85/* TT = 0x11, TL = 0, privileged_opcode */
86.org trap_table + TT_PRIVILEGED_OPCODE*ENTRY_SIZE
87.global privileged_opcode_tl0
88privileged_opcode_tl0:
89 mov TT_PRIVILEGED_OPCODE, %g2
90 clr %g5
91 PREEMPTIBLE_HANDLER exc_dispatch
92
93/* TT = 0x12, TL = 0, unimplemented_LDD */
94.org trap_table + TT_UNIMPLEMENTED_LDD*ENTRY_SIZE
95.global unimplemented_LDD_tl0
96unimplemented_LDD_tl0:
97 mov TT_UNIMPLEMENTED_LDD, %g2
98 clr %g5
99 PREEMPTIBLE_HANDLER exc_dispatch
100
101/* TT = 0x13, TL = 0, unimplemented_STD */
102.org trap_table + TT_UNIMPLEMENTED_STD*ENTRY_SIZE
103.global unimplemented_STD_tl0
104unimplemented_STD_tl0:
105 mov TT_UNIMPLEMENTED_STD, %g2
106 clr %g5
107 PREEMPTIBLE_HANDLER exc_dispatch
108
109/* TT = 0x20, TL = 0, fb_disabled handler */
110.org trap_table + TT_FP_DISABLED*ENTRY_SIZE
111.global fb_disabled_tl0
112fp_disabled_tl0:
113 mov TT_FP_DISABLED, %g2
114 clr %g5
115 PREEMPTIBLE_HANDLER exc_dispatch
116
117/* TT = 0x21, TL = 0, fb_exception_ieee_754 handler */
118.org trap_table + TT_FP_EXCEPTION_IEEE_754*ENTRY_SIZE
119.global fb_exception_ieee_754_tl0
120fp_exception_ieee_754_tl0:
121 mov TT_FP_EXCEPTION_IEEE_754, %g2
122 clr %g5
123 PREEMPTIBLE_HANDLER exc_dispatch
124
125/* TT = 0x22, TL = 0, fb_exception_other handler */
126.org trap_table + TT_FP_EXCEPTION_OTHER*ENTRY_SIZE
127.global fb_exception_other_tl0
128fp_exception_other_tl0:
129 mov TT_FP_EXCEPTION_OTHER, %g2
130 clr %g5
131 PREEMPTIBLE_HANDLER exc_dispatch
132
133/* TT = 0x23, TL = 0, tag_overflow */
134.org trap_table + TT_TAG_OVERFLOW*ENTRY_SIZE
135.global tag_overflow_tl0
136tag_overflow_tl0:
137 mov TT_TAG_OVERFLOW, %g2
138 clr %g5
139 PREEMPTIBLE_HANDLER exc_dispatch
140
141/* TT = 0x24, TL = 0, clean_window handler */
142.org trap_table + TT_CLEAN_WINDOW*ENTRY_SIZE
143.global clean_window_tl0
144clean_window_tl0:
145 CLEAN_WINDOW_HANDLER
146
147/* TT = 0x28, TL = 0, division_by_zero */
148.org trap_table + TT_DIVISION_BY_ZERO*ENTRY_SIZE
149.global division_by_zero_tl0
150division_by_zero_tl0:
151 mov TT_DIVISION_BY_ZERO, %g2
152 clr %g5
153 PREEMPTIBLE_HANDLER exc_dispatch
154
155/* TT = 0x30, TL = 0, data_access_exception */
156.org trap_table + TT_DATA_ACCESS_EXCEPTION*ENTRY_SIZE
157.global data_access_exception_tl0
158data_access_exception_tl0:
159 wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
160 mov TT_DATA_ACCESS_EXCEPTION, %g2
161 clr %g5
162 PREEMPTIBLE_HANDLER exc_dispatch
163
164/* TT = 0x32, TL = 0, data_access_error */
165.org trap_table + TT_DATA_ACCESS_ERROR*ENTRY_SIZE
166.global data_access_error_tl0
167data_access_error_tl0:
168 mov TT_DATA_ACCESS_ERROR, %g2
169 clr %g5
170 PREEMPTIBLE_HANDLER exc_dispatch
171
172/* TT = 0x34, TL = 0, mem_address_not_aligned */
173.org trap_table + TT_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
174.global mem_address_not_aligned_tl0
175mem_address_not_aligned_tl0:
176 mov TT_MEM_ADDRESS_NOT_ALIGNED, %g2
177 clr %g5
178 PREEMPTIBLE_HANDLER exc_dispatch
179
180/* TT = 0x35, TL = 0, LDDF_mem_address_not_aligned */
181.org trap_table + TT_LDDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
182.global LDDF_mem_address_not_aligned_tl0
183LDDF_mem_address_not_aligned_tl0:
184 mov TT_LDDF_MEM_ADDRESS_NOT_ALIGNED, %g2
185 clr %g5
186 PREEMPTIBLE_HANDLER exc_dispatch
187
188/* TT = 0x36, TL = 0, STDF_mem_address_not_aligned */
189.org trap_table + TT_STDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
190.global STDF_mem_address_not_aligned_tl0
191STDF_mem_address_not_aligned_tl0:
192 mov TT_STDF_MEM_ADDRESS_NOT_ALIGNED, %g2
193 clr %g5
194 PREEMPTIBLE_HANDLER exc_dispatch
195
196/* TT = 0x37, TL = 0, privileged_action */
197.org trap_table + TT_PRIVILEGED_ACTION*ENTRY_SIZE
198.global privileged_action_tl0
199privileged_action_tl0:
200 mov TT_PRIVILEGED_ACTION, %g2
201 clr %g5
202 PREEMPTIBLE_HANDLER exc_dispatch
203
204/* TT = 0x38, TL = 0, LDQF_mem_address_not_aligned */
205.org trap_table + TT_LDQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
206.global LDQF_mem_address_not_aligned_tl0
207LDQF_mem_address_not_aligned_tl0:
208 mov TT_LDQF_MEM_ADDRESS_NOT_ALIGNED, %g2
209 clr %g5
210 PREEMPTIBLE_HANDLER exc_dispatch
211
212/* TT = 0x39, TL = 0, STQF_mem_address_not_aligned */
213.org trap_table + TT_STQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
214.global STQF_mem_address_not_aligned_tl0
215STQF_mem_address_not_aligned_tl0:
216 mov TT_STQF_MEM_ADDRESS_NOT_ALIGNED, %g2
217 clr %g5
218 PREEMPTIBLE_HANDLER exc_dispatch
219
220/* TT = 0x41, TL = 0, interrupt_level_1 handler */
221.org trap_table + TT_INTERRUPT_LEVEL_1*ENTRY_SIZE
222.global interrupt_level_1_handler_tl0
223interrupt_level_1_handler_tl0:
224 mov TT_INTERRUPT_LEVEL_1, %g2
225 clr %g5
226 PREEMPTIBLE_HANDLER exc_dispatch
227
228/* TT = 0x42, TL = 0, interrupt_level_2 handler */
229.org trap_table + TT_INTERRUPT_LEVEL_2*ENTRY_SIZE
230.global interrupt_level_2_handler_tl0
231interrupt_level_2_handler_tl0:
232 mov TT_INTERRUPT_LEVEL_2, %g2
233 clr %g5
234 PREEMPTIBLE_HANDLER exc_dispatch
235
236/* TT = 0x43, TL = 0, interrupt_level_3 handler */
237.org trap_table + TT_INTERRUPT_LEVEL_3*ENTRY_SIZE
238.global interrupt_level_3_handler_tl0
239interrupt_level_3_handler_tl0:
240 mov TT_INTERRUPT_LEVEL_3, %g2
241 clr %g5
242 PREEMPTIBLE_HANDLER exc_dispatch
243
244/* TT = 0x44, TL = 0, interrupt_level_4 handler */
245.org trap_table + TT_INTERRUPT_LEVEL_4*ENTRY_SIZE
246.global interrupt_level_4_handler_tl0
247interrupt_level_4_handler_tl0:
248 mov TT_INTERRUPT_LEVEL_4, %g2
249 clr %g5
250 PREEMPTIBLE_HANDLER exc_dispatch
251
252/* TT = 0x45, TL = 0, interrupt_level_5 handler */
253.org trap_table + TT_INTERRUPT_LEVEL_5*ENTRY_SIZE
254.global interrupt_level_5_handler_tl0
255interrupt_level_5_handler_tl0:
256 mov TT_INTERRUPT_LEVEL_5, %g2
257 clr %g5
258 PREEMPTIBLE_HANDLER exc_dispatch
259
260/* TT = 0x46, TL = 0, interrupt_level_6 handler */
261.org trap_table + TT_INTERRUPT_LEVEL_6*ENTRY_SIZE
262.global interrupt_level_6_handler_tl0
263interrupt_level_6_handler_tl0:
264 mov TT_INTERRUPT_LEVEL_6, %g2
265 clr %g5
266 PREEMPTIBLE_HANDLER exc_dispatch
267
268/* TT = 0x47, TL = 0, interrupt_level_7 handler */
269.org trap_table + TT_INTERRUPT_LEVEL_7*ENTRY_SIZE
270.global interrupt_level_7_handler_tl0
271interrupt_level_7_handler_tl0:
272 mov TT_INTERRUPT_LEVEL_7, %g2
273 clr %g5
274 PREEMPTIBLE_HANDLER exc_dispatch
275
276/* TT = 0x48, TL = 0, interrupt_level_8 handler */
277.org trap_table + TT_INTERRUPT_LEVEL_8*ENTRY_SIZE
278.global interrupt_level_8_handler_tl0
279interrupt_level_8_handler_tl0:
280 mov TT_INTERRUPT_LEVEL_8, %g2
281 clr %g5
282 PREEMPTIBLE_HANDLER exc_dispatch
283
284/* TT = 0x49, TL = 0, interrupt_level_9 handler */
285.org trap_table + TT_INTERRUPT_LEVEL_9*ENTRY_SIZE
286.global interrupt_level_9_handler_tl0
287interrupt_level_9_handler_tl0:
288 mov TT_INTERRUPT_LEVEL_9, %g2
289 clr %g5
290 PREEMPTIBLE_HANDLER exc_dispatch
291
292/* TT = 0x4a, TL = 0, interrupt_level_10 handler */
293.org trap_table + TT_INTERRUPT_LEVEL_10*ENTRY_SIZE
294.global interrupt_level_10_handler_tl0
295interrupt_level_10_handler_tl0:
296 mov TT_INTERRUPT_LEVEL_10, %g2
297 clr %g5
298 PREEMPTIBLE_HANDLER exc_dispatch
299
300/* TT = 0x4b, TL = 0, interrupt_level_11 handler */
301.org trap_table + TT_INTERRUPT_LEVEL_11*ENTRY_SIZE
302.global interrupt_level_11_handler_tl0
303interrupt_level_11_handler_tl0:
304 mov TT_INTERRUPT_LEVEL_11, %g2
305 clr %g5
306 PREEMPTIBLE_HANDLER exc_dispatch
307
308/* TT = 0x4c, TL = 0, interrupt_level_12 handler */
309.org trap_table + TT_INTERRUPT_LEVEL_12*ENTRY_SIZE
310.global interrupt_level_12_handler_tl0
311interrupt_level_12_handler_tl0:
312 mov TT_INTERRUPT_LEVEL_12, %g2
313 clr %g5
314 PREEMPTIBLE_HANDLER exc_dispatch
315
316/* TT = 0x4d, TL = 0, interrupt_level_13 handler */
317.org trap_table + TT_INTERRUPT_LEVEL_13*ENTRY_SIZE
318.global interrupt_level_13_handler_tl0
319interrupt_level_13_handler_tl0:
320 mov TT_INTERRUPT_LEVEL_13, %g2
321 clr %g5
322 PREEMPTIBLE_HANDLER exc_dispatch
323
324/* TT = 0x4e, TL = 0, interrupt_level_14 handler */
325.org trap_table + TT_INTERRUPT_LEVEL_14*ENTRY_SIZE
326.global interrupt_level_14_handler_tl0
327interrupt_level_14_handler_tl0:
328 mov TT_INTERRUPT_LEVEL_14, %g2
329 clr %g5
330 PREEMPTIBLE_HANDLER exc_dispatch
331
332/* TT = 0x4f, TL = 0, interrupt_level_15 handler */
333.org trap_table + TT_INTERRUPT_LEVEL_15*ENTRY_SIZE
334.global interrupt_level_15_handler_tl0
335interrupt_level_15_handler_tl0:
336 mov TT_INTERRUPT_LEVEL_15, %g2
337 clr %g5
338 PREEMPTIBLE_HANDLER exc_dispatch
339
340/* TT = 0x60, TL = 0, interrupt_vector_trap handler */
341.org trap_table + TT_INTERRUPT_VECTOR_TRAP*ENTRY_SIZE
342.global interrupt_vector_trap_handler_tl0
343interrupt_vector_trap_handler_tl0:
344 mov TT_INTERRUPT_VECTOR_TRAP, %g2
345 clr %g5
346 PREEMPTIBLE_HANDLER exc_dispatch
347
348/* TT = 0x64, TL = 0, fast_instruction_access_MMU_miss */
349.org trap_table + TT_FAST_INSTRUCTION_ACCESS_MMU_MISS*ENTRY_SIZE
350.global fast_instruction_access_mmu_miss_handler_tl0
351fast_instruction_access_mmu_miss_handler_tl0:
352 FAST_INSTRUCTION_ACCESS_MMU_MISS_HANDLER
353
354/* TT = 0x68, TL = 0, fast_data_access_MMU_miss */
355.org trap_table + TT_FAST_DATA_ACCESS_MMU_MISS*ENTRY_SIZE
356.global fast_data_access_mmu_miss_handler_tl0
357fast_data_access_mmu_miss_handler_tl0:
358 FAST_DATA_ACCESS_MMU_MISS_HANDLER 0
359
360/* TT = 0x6c, TL = 0, fast_data_access_protection */
361.org trap_table + TT_FAST_DATA_ACCESS_PROTECTION*ENTRY_SIZE
362.global fast_data_access_protection_handler_tl0
363fast_data_access_protection_handler_tl0:
364 FAST_DATA_ACCESS_PROTECTION_HANDLER 0
365
366/* TT = 0x80, TL = 0, spill_0_normal handler */
367.org trap_table + TT_SPILL_0_NORMAL*ENTRY_SIZE
368.global spill_0_normal_tl0
369spill_0_normal_tl0:
370 SPILL_NORMAL_HANDLER_KERNEL
371
372/* TT = 0x84, TL = 0, spill_1_normal handler */
373.org trap_table + TT_SPILL_1_NORMAL*ENTRY_SIZE
374.global spill_1_normal_tl0
375spill_1_normal_tl0:
376 SPILL_NORMAL_HANDLER_USERSPACE
377
378/* TT = 0x88, TL = 0, spill_2_normal handler */
379.org trap_table + TT_SPILL_2_NORMAL*ENTRY_SIZE
380.global spill_2_normal_tl0
381spill_2_normal_tl0:
382 SPILL_TO_USPACE_WINDOW_BUFFER
383
384/* TT = 0xa0, TL = 0, spill_0_other handler */
385.org trap_table + TT_SPILL_0_OTHER*ENTRY_SIZE
386.global spill_0_other_tl0
387spill_0_other_tl0:
388 SPILL_TO_USPACE_WINDOW_BUFFER
389
390/* TT = 0xc0, TL = 0, fill_0_normal handler */
391.org trap_table + TT_FILL_0_NORMAL*ENTRY_SIZE
392.global fill_0_normal_tl0
393fill_0_normal_tl0:
394 FILL_NORMAL_HANDLER_KERNEL
395
396/* TT = 0xc4, TL = 0, fill_1_normal handler */
397.org trap_table + TT_FILL_1_NORMAL*ENTRY_SIZE
398.global fill_1_normal_tl0
399fill_1_normal_tl0:
400 FILL_NORMAL_HANDLER_USERSPACE
401
402/* TT = 0x100 - 0x17f, TL = 0, trap_instruction_0 - trap_instruction_7f */
403.irp cur, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\
404 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\
405 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,\
406 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,\
407 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,\
408 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,\
409 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,\
410 127
411.org trap_table + (TT_TRAP_INSTRUCTION_0+\cur)*ENTRY_SIZE
412.global trap_instruction_\cur\()_tl0
413trap_instruction_\cur\()_tl0:
414 mov \cur, %g2
415 ba %xcc, trap_instruction_handler
416 clr %g5
417.endr
418
419/*
420 * Handlers for TL>0.
421 */
422
423/* TT = 0x08, TL > 0, instruction_access_exception */
424.org trap_table + (TT_INSTRUCTION_ACCESS_EXCEPTION+512)*ENTRY_SIZE
425.global instruction_access_exception_tl1
426instruction_access_exception_tl1:
427 wrpr %g0, 1, %tl
428 wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
429 mov TT_INSTRUCTION_ACCESS_EXCEPTION, %g2
430 clr %g5
431 PREEMPTIBLE_HANDLER exc_dispatch
432
433/* TT = 0x0a, TL > 0, instruction_access_error */
434.org trap_table + (TT_INSTRUCTION_ACCESS_ERROR+512)*ENTRY_SIZE
435.global instruction_access_error_tl1
436instruction_access_error_tl1:
437 wrpr %g0, 1, %tl
438 mov TT_INSTRUCTION_ACCESS_ERROR, %g2
439 clr %g5
440 PREEMPTIBLE_HANDLER exc_dispatch
441
442/* TT = 0x10, TL > 0, illegal_instruction */
443.org trap_table + (TT_ILLEGAL_INSTRUCTION+512)*ENTRY_SIZE
444.global illegal_instruction_tl1
445illegal_instruction_tl1:
446 wrpr %g0, 1, %tl
447 mov TT_ILLEGAL_INSTRUCTION, %g2
448 clr %g5
449 PREEMPTIBLE_HANDLER exc_dispatch
450
451/* TT = 0x24, TL > 0, clean_window handler */
452.org trap_table + (TT_CLEAN_WINDOW+512)*ENTRY_SIZE
453.global clean_window_tl1
454clean_window_tl1:
455 CLEAN_WINDOW_HANDLER
456
457/* TT = 0x28, TL > 0, division_by_zero */
458.org trap_table + (TT_DIVISION_BY_ZERO+512)*ENTRY_SIZE
459.global division_by_zero_tl1
460division_by_zero_tl1:
461 wrpr %g0, 1, %tl
462 mov TT_DIVISION_BY_ZERO, %g2
463 clr %g5
464 PREEMPTIBLE_HANDLER exc_dispatch
465
466/* TT = 0x30, TL > 0, data_access_exception */
467.org trap_table + (TT_DATA_ACCESS_EXCEPTION+512)*ENTRY_SIZE
468.global data_access_exception_tl1
469data_access_exception_tl1:
470 wrpr %g0, 1, %tl
471 wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
472 mov TT_DATA_ACCESS_EXCEPTION, %g2
473 clr %g5
474 PREEMPTIBLE_HANDLER exc_dispatch
475
476/* TT = 0x32, TL > 0, data_access_error */
477.org trap_table + (TT_DATA_ACCESS_ERROR+512)*ENTRY_SIZE
478.global data_access_error_tl1
479data_access_error_tl1:
480 wrpr %g0, 1, %tl
481 mov TT_DATA_ACCESS_ERROR, %g2
482 clr %g5
483 PREEMPTIBLE_HANDLER exc_dispatch
484
485/* TT = 0x34, TL > 0, mem_address_not_aligned */
486.org trap_table + (TT_MEM_ADDRESS_NOT_ALIGNED+512)*ENTRY_SIZE
487.global mem_address_not_aligned_tl1
488mem_address_not_aligned_tl1:
489 wrpr %g0, 1, %tl
490 mov TT_MEM_ADDRESS_NOT_ALIGNED, %g2
491 clr %g5
492 PREEMPTIBLE_HANDLER exc_dispatch
493
494/* TT = 0x68, TL > 0, fast_data_access_MMU_miss */
495.org trap_table + (TT_FAST_DATA_ACCESS_MMU_MISS+512)*ENTRY_SIZE
496.global fast_data_access_mmu_miss_handler_tl1
497fast_data_access_mmu_miss_handler_tl1:
498 FAST_DATA_ACCESS_MMU_MISS_HANDLER 1
499
500/* TT = 0x6c, TL > 0, fast_data_access_protection */
501.org trap_table + (TT_FAST_DATA_ACCESS_PROTECTION+512)*ENTRY_SIZE
502.global fast_data_access_protection_handler_tl1
503fast_data_access_protection_handler_tl1:
504 FAST_DATA_ACCESS_PROTECTION_HANDLER 1
505
506/* TT = 0x80, TL > 0, spill_0_normal handler */
507.org trap_table + (TT_SPILL_0_NORMAL+512)*ENTRY_SIZE
508.global spill_0_normal_tl1
509spill_0_normal_tl1:
510 SPILL_NORMAL_HANDLER_KERNEL
511
512/* TT = 0x88, TL > 0, spill_2_normal handler */
513.org trap_table + (TT_SPILL_2_NORMAL+512)*ENTRY_SIZE
514.global spill_2_normal_tl1
515spill_2_normal_tl1:
516 SPILL_TO_USPACE_WINDOW_BUFFER
517
518/* TT = 0xa0, TL > 0, spill_0_other handler */
519.org trap_table + (TT_SPILL_0_OTHER+512)*ENTRY_SIZE
520.global spill_0_other_tl1
521spill_0_other_tl1:
522 SPILL_TO_USPACE_WINDOW_BUFFER
523
524/* TT = 0xc0, TL > 0, fill_0_normal handler */
525.org trap_table + (TT_FILL_0_NORMAL+512)*ENTRY_SIZE
526.global fill_0_normal_tl1
527fill_0_normal_tl1:
528 FILL_NORMAL_HANDLER_KERNEL
529
530.align TABLE_SIZE
531
532
533#define NOT(x) ((x) == 0)
534
535/* Preemptible trap handler for TL=1.
536 *
537 * This trap handler makes arrangements to make calling of scheduler() from
538 * within a trap context possible. It is called from several other trap
539 * handlers.
540 *
541 * This function can be entered either with interrupt globals or alternate
542 * globals. Memory management trap handlers are obliged to switch to one of
543 * those global sets prior to calling this function. Register window management
544 * functions are not allowed to modify the alternate global registers.
545 *
546 * The kernel is designed to work on trap levels 0 - 4. For instance, the
547 * following can happen:
548 * TL0: kernel thread runs (CANSAVE=0, kernel stack not in DTLB)
549 * TL1: preemptible trap handler started after a tick interrupt
550 * TL2: preemptible trap handler did SAVE
551 * TL3: spill handler touched the kernel stack
552 * TL4: hardware or software failure
553 *
554 * Input registers:
555 * %g1 Address of function to call if this is not a syscall.
556 * %g2 First argument for the function.
557 * %g5 I/DTLB_TAG_ACCESS register if applicable.
558 * %g6 Pre-set as kernel stack base if trap from userspace.
559 * %g7 Pre-set as address of the userspace window buffer.
560 */
561.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
562.if NOT(\is_syscall)
563 rdpr %tstate, %g3
564
565 /*
566 * One of the ways this handler can be invoked is after a nested MMU trap from
567 * either spill_1_normal or fill_1_normal traps. Both of these traps manipulate
568 * the CWP register. We deal with the situation by simulating the MMU trap
569 * on TL=1 and restart the respective SAVE or RESTORE instruction once the MMU
570 * trap is resolved. However, because we are in the wrong window from the
571 * perspective of the MMU trap, we need to synchronize CWP with CWP from TL=0.
572 */
573 and %g3, TSTATE_CWP_MASK, %g4
574 wrpr %g4, 0, %cwp ! resynchronize CWP
575
576 andcc %g3, TSTATE_PRIV_BIT, %g0 ! if this trap came from the privileged mode...
577 bnz %xcc, 0f ! ...skip setting of kernel stack and primary context
578 nop
579.endif
580
581 /*
582 * Normal window spills will go to the userspace window buffer.
583 */
584 wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(2), %wstate
585
586 wrpr %g0, NWINDOWS - 1, %cleanwin ! prevent unnecessary clean_window exceptions
587
588 /*
589 * Switch to kernel stack. The old stack is
590 * automatically saved in the old window's %sp
591 * and the new window's %fp.
592 */
593 save %g6, -ISTATE_SIZE, %sp
594
595.if \is_syscall
596 /*
597 * Copy arguments for the syscall to the new window.
598 */
599 mov %i0, %o0
600 mov %i1, %o1
601 mov %i2, %o2
602 mov %i3, %o3
603 mov %i4, %o4
604 mov %i5, %o5
605.endif
606
607 /*
608 * Mark the CANRESTORE windows as OTHER windows.
609 */
610 rdpr %canrestore, %l0
611 wrpr %l0, %otherwin
612 wrpr %g0, %canrestore
613
614 /*
615 * Switch to primary context 0.
616 */
617 mov VA_PRIMARY_CONTEXT_REG, %l0
618 stxa %g0, [%l0] ASI_DMMU
619 rd %pc, %l0
620 flush %l0
621
622.if NOT(\is_syscall)
623 ba,a %xcc, 1f
6240:
625 save %sp, -ISTATE_SIZE, %sp
626
627 /*
628 * At this moment, we are using the kernel stack
629 * and have successfully allocated a register window.
630 */
6311:
632.endif
633 /*
634 * Other window spills will go to the userspace window buffer
635 * and normal spills will go to the kernel stack.
636 */
637 wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
638
639 /*
640 * Copy arguments.
641 */
642 mov %g1, %l0
643.if NOT(\is_syscall)
644 mov %g2, %o0
645.else
646 ! store the syscall number on the stack as 7th argument
647 stx %g2, [%sp + STACK_BIAS + ISTATE_OFFSET_ARG6]
648.endif
649
650 /*
651 * Save TSTATE, TPC, TNPC and I/DTLB_TAG_ACCESS aside.
652 */
653 rdpr %tstate, %g1
654 rdpr %tpc, %g2
655 rdpr %tnpc, %g3
656 rd %y, %g4
657
658 stx %g1, [%sp + STACK_BIAS + ISTATE_OFFSET_TSTATE]
659 stx %g2, [%sp + STACK_BIAS + ISTATE_OFFSET_TPC]
660 stx %g3, [%sp + STACK_BIAS + ISTATE_OFFSET_TNPC]
661 stx %g5, [%sp + STACK_BIAS + ISTATE_OFFSET_TLB_TAG_ACCESS]
662
663 /*
664 * Save the Y register.
665 */
666 stx %g4, [%sp + STACK_BIAS + ISTATE_OFFSET_Y]
667
668 wrpr %g0, 0, %tl
669 wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
670 SAVE_GLOBALS
671
672.if NOT(\is_syscall)
673 /*
674 * Call the higher-level handler and pass istate as second parameter.
675 */
676 call %l0
677 add %sp, STACK_BIAS, %o1
678.else
679 /*
680 * Call the higher-level syscall handler and enable interrupts.
681 */
682 call syscall_handler
683 wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT | PSTATE_IE_BIT, %pstate
684 mov %o0, %i0 ! copy the value returned by the syscall
685.endif
686
687 RESTORE_GLOBALS
688 rdpr %pstate, %l1 ! we must preserve the PEF bit
689 wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
690 wrpr %g0, 1, %tl
691
692 /*
693 * Read TSTATE, TPC and TNPC from saved copy.
694 */
695 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_TSTATE], %g1
696 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_TPC], %g2
697 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_TNPC], %g3
698
699 /*
700 * Copy PSTATE.PEF to the in-register copy of TSTATE.
701 */
702 and %l1, PSTATE_PEF_BIT, %l1
703 sllx %l1, TSTATE_PSTATE_SHIFT, %l1
704 sethi %hi(TSTATE_PEF_BIT), %g4
705 andn %g1, %g4, %g1
706 or %g1, %l1, %g1
707
708 /*
709 * Restore TSTATE, TPC and TNPC from saved copies.
710 */
711 wrpr %g1, 0, %tstate
712 wrpr %g2, 0, %tpc
713 wrpr %g3, 0, %tnpc
714
715 /*
716 * Restore Y.
717 */
718 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_Y], %g4
719 wr %g4, %y
720
721 /*
722 * If OTHERWIN is zero, then all the userspace windows have been
723 * spilled to kernel memory (i.e. register window buffer). Moreover,
724 * if the scheduler was called in the meantime, all valid windows
725 * belonging to other threads were spilled by context_save().
726 * If OTHERWIN is non-zero, then some userspace windows are still
727 * valid. Others might have been spilled. However, the CWP pointer
728 * needs no fixing because the scheduler had not been called.
729 */
730 rdpr %otherwin, %l0
731 brnz %l0, 0f
732 nop
733
734 /*
735 * OTHERWIN == 0
736 */
737
738 /*
739 * If TSTATE.CWP + 1 == CWP, then we still do not have to fix CWP.
740 */
741 and %g1, TSTATE_CWP_MASK, %l0
742 inc %l0
743 and %l0, NWINDOWS - 1, %l0 ! %l0 mod NWINDOWS
744 rdpr %cwp, %l1
745 cmp %l0, %l1
746 bz %xcc, 0f ! CWP is ok
747 nop
748
749 /*
750 * Fix CWP.
751 * In order to recapitulate, the input registers in the current
752 * window are the output registers of the window to which we want
753 * to restore. Because the fill trap fills only input and local
754 * registers of a window, we need to preserve those output
755 * registers manually.
756 */
757 mov %sp, %g2
758 stx %i0, [%sp + STACK_BIAS + ISTATE_OFFSET_O0]
759 stx %i1, [%sp + STACK_BIAS + ISTATE_OFFSET_O1]
760 stx %i2, [%sp + STACK_BIAS + ISTATE_OFFSET_O2]
761 stx %i3, [%sp + STACK_BIAS + ISTATE_OFFSET_O3]
762 stx %i4, [%sp + STACK_BIAS + ISTATE_OFFSET_O4]
763 stx %i5, [%sp + STACK_BIAS + ISTATE_OFFSET_O5]
764 stx %i6, [%sp + STACK_BIAS + ISTATE_OFFSET_O6]
765 stx %i7, [%sp + STACK_BIAS + ISTATE_OFFSET_O7]
766 wrpr %l0, 0, %cwp
767 mov %g2, %sp
768 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O0], %i0
769 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O1], %i1
770 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O2], %i2
771 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O3], %i3
772 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O4], %i4
773 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O5], %i5
774 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O6], %i6
775 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O7], %i7
776
777 /*
778 * OTHERWIN != 0 or fall-through from the OTHERWIN == 0 case.
779 * The CWP has already been restored to the value it had after the SAVE
780 * at the beginning of this function.
781 */
7820:
783.if NOT(\is_syscall)
784 rdpr %tstate, %g1
785 andcc %g1, TSTATE_PRIV_BIT, %g0 ! if we are not returning to userspace...,
786 bnz %xcc, 1f ! ...skip restoring userspace windows
787 nop
788.endif
789
790 /*
791 * Spills and fills will be processed by the {spill,fill}_1_normal
792 * handlers.
793 */
794 wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(1), %wstate
795
796 /*
797 * Set primary context according to secondary context.
798 */
799 wr %g0, ASI_DMMU, %asi
800 ldxa [VA_SECONDARY_CONTEXT_REG] %asi, %g1
801 stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi
802 rd %pc, %g1
803 flush %g1
804
805 rdpr %cwp, %g1
806 rdpr %otherwin, %g2
807
808 /*
809 * Skip all OTHERWIN windows and descend to the first window
810 * in the userspace window buffer.
811 */
812 sub %g1, %g2, %g3
813 dec %g3
814 and %g3, NWINDOWS - 1, %g3
815 wrpr %g3, 0, %cwp
816
817 /*
818 * CWP is now in the window last saved in the userspace window buffer.
819 * Fill all windows stored in the buffer.
820 */
821 clr %g4
8220: andcc %g7, UWB_ALIGNMENT - 1, %g0 ! alignment check
823 bz %xcc, 0f ! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill
824 nop
825
826 add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7
827 ldx [%g7 + L0_OFFSET], %l0
828 ldx [%g7 + L1_OFFSET], %l1
829 ldx [%g7 + L2_OFFSET], %l2
830 ldx [%g7 + L3_OFFSET], %l3
831 ldx [%g7 + L4_OFFSET], %l4
832 ldx [%g7 + L5_OFFSET], %l5
833 ldx [%g7 + L6_OFFSET], %l6
834 ldx [%g7 + L7_OFFSET], %l7
835 ldx [%g7 + I0_OFFSET], %i0
836 ldx [%g7 + I1_OFFSET], %i1
837 ldx [%g7 + I2_OFFSET], %i2
838 ldx [%g7 + I3_OFFSET], %i3
839 ldx [%g7 + I4_OFFSET], %i4
840 ldx [%g7 + I5_OFFSET], %i5
841 ldx [%g7 + I6_OFFSET], %i6
842 ldx [%g7 + I7_OFFSET], %i7
843
844 dec %g3
845 and %g3, NWINDOWS - 1, %g3
846 wrpr %g3, 0, %cwp ! switch to the preceeding window
847
848 ba %xcc, 0b
849 inc %g4
850
8510:
852 /*
853 * Switch back to the proper current window and adjust
854 * OTHERWIN, CANRESTORE, CANSAVE and CLEANWIN.
855 */
856 wrpr %g1, 0, %cwp
857 add %g4, %g2, %g2
858 cmp %g2, NWINDOWS - 2
859 bg %xcc, 2f ! fix the CANRESTORE=NWINDOWS-1 anomaly
860 mov NWINDOWS - 2, %g1 ! use dealy slot for both cases
861 sub %g1, %g2, %g1
862
863 wrpr %g0, 0, %otherwin
864 wrpr %g1, 0, %cansave ! NWINDOWS - 2 - CANRESTORE
865 wrpr %g2, 0, %canrestore ! OTHERWIN + windows in the buffer
866 wrpr %g2, 0, %cleanwin ! avoid information leak
867
8681:
869 restore
870
871.if \is_syscall
872 done
873.else
874 retry
875.endif
876
877 /*
878 * We got here in order to avoid inconsistency of the window state registers.
879 * If the:
880 *
881 * save %g6, -ISTATE_SIZE, %sp
882 *
883 * instruction trapped and spilled a register window into the userspace
884 * window buffer, we have just restored NWINDOWS - 1 register windows.
885 * However, CANRESTORE can be only NWINDOW - 2 at most.
886 *
887 * The solution is to manually switch to (CWP - 1) mod NWINDOWS
888 * and set the window state registers so that:
889 *
890 * CANRESTORE = NWINDOWS - 2
891 * CLEANWIN = NWINDOWS - 2
892 * CANSAVE = 0
893 * OTHERWIN = 0
894 *
895 * The RESTORE instruction is therfore to be skipped.
896 */
8972:
898 wrpr %g0, 0, %otherwin
899 wrpr %g0, 0, %cansave
900 wrpr %g1, 0, %canrestore
901 wrpr %g1, 0, %cleanwin
902
903 rdpr %cwp, %g1
904 dec %g1
905 and %g1, NWINDOWS - 1, %g1
906 wrpr %g1, 0, %cwp ! CWP--
907
908.if \is_syscall
909 done
910.else
911 retry
912.endif
913
914.endm
915
916.global preemptible_handler
917preemptible_handler:
918 PREEMPTIBLE_HANDLER_TEMPLATE 0
919
920.global trap_instruction_handler
921trap_instruction_handler:
922 PREEMPTIBLE_HANDLER_TEMPLATE 1
Note: See TracBrowser for help on using the repository browser.