source: mainline/kernel/arch/sparc64/src/trap/trap_table.S@ 3b8fe85

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

Populate all sparc64 trap table slots belonging to trap_instruction_n.

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