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

Last change on this file was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

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