source: mainline/kernel/arch/sparc64/src/trap/trap_table.S@ 7ba7c6d

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

A quote from from SPARC V9 specification:

The Y register is deprecated; it is provided only for compatibility with previous versions
of the architecture. It should not be used in new SPARC-V9 software. It is
recommended that all instructions that reference the Y register (i.e., SMUL,
SMULcc, UMUL, UMULcc, MULScc, SDIV, SDIVcc, UDIV, UDIVcc, RDY, and
WRY) be avoided. See the appropriate pages in Appendix A, “Instruction Definitions,”
for suitable substitute instructions.

Still gcc is generating code which uses Y and some of the instructions above.
This change modifies the preemptible_handler() to preserve the Y register
across preemption.

  • Property mode set to 100644
File size: 30.1 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, TL = 0, trap_instruction_0 */
333.org trap_table + TT_TRAP_INSTRUCTION(0)*ENTRY_SIZE
334.global trap_instruction_0_tl0
335trap_instruction_0_tl0:
336 TRAP_INSTRUCTION 0
337
338/* TT = 0x101, TL = 0, trap_instruction_1 */
339.org trap_table + TT_TRAP_INSTRUCTION(1)*ENTRY_SIZE
340.global trap_instruction_1_tl0
341trap_instruction_1_tl0:
342 TRAP_INSTRUCTION 1
343
344/* TT = 0x102, TL = 0, trap_instruction_2 */
345.org trap_table + TT_TRAP_INSTRUCTION(2)*ENTRY_SIZE
346.global trap_instruction_2_tl0
347trap_instruction_2_tl0:
348 TRAP_INSTRUCTION 2
349
350/* TT = 0x103, TL = 0, trap_instruction_3 */
351.org trap_table + TT_TRAP_INSTRUCTION(3)*ENTRY_SIZE
352.global trap_instruction_3_tl0
353trap_instruction_3_tl0:
354 TRAP_INSTRUCTION 3
355
356/* TT = 0x104, TL = 0, trap_instruction_4 */
357.org trap_table + TT_TRAP_INSTRUCTION(4)*ENTRY_SIZE
358.global trap_instruction_4_tl0
359trap_instruction_4_tl0:
360 TRAP_INSTRUCTION 4
361
362/* TT = 0x105, TL = 0, trap_instruction_5 */
363.org trap_table + TT_TRAP_INSTRUCTION(5)*ENTRY_SIZE
364.global trap_instruction_5_tl0
365trap_instruction_5_tl0:
366 TRAP_INSTRUCTION 5
367
368/* TT = 0x106, TL = 0, trap_instruction_6 */
369.org trap_table + TT_TRAP_INSTRUCTION(6)*ENTRY_SIZE
370.global trap_instruction_6_tl0
371trap_instruction_6_tl0:
372 TRAP_INSTRUCTION 6
373
374/* TT = 0x107, TL = 0, trap_instruction_7 */
375.org trap_table + TT_TRAP_INSTRUCTION(7)*ENTRY_SIZE
376.global trap_instruction_7_tl0
377trap_instruction_7_tl0:
378 TRAP_INSTRUCTION 7
379
380/* TT = 0x108, TL = 0, trap_instruction_8 */
381.org trap_table + TT_TRAP_INSTRUCTION(8)*ENTRY_SIZE
382.global trap_instruction_8_tl0
383trap_instruction_8_tl0:
384 TRAP_INSTRUCTION 8
385
386/* TT = 0x109, TL = 0, trap_instruction_9 */
387.org trap_table + TT_TRAP_INSTRUCTION(9)*ENTRY_SIZE
388.global trap_instruction_9_tl0
389trap_instruction_9_tl0:
390 TRAP_INSTRUCTION 9
391
392/* TT = 0x10a, TL = 0, trap_instruction_10 */
393.org trap_table + TT_TRAP_INSTRUCTION(10)*ENTRY_SIZE
394.global trap_instruction_10_tl0
395trap_instruction_10_tl0:
396 TRAP_INSTRUCTION 10
397
398/* TT = 0x10b, TL = 0, trap_instruction_11 */
399.org trap_table + TT_TRAP_INSTRUCTION(11)*ENTRY_SIZE
400.global trap_instruction_11_tl0
401trap_instruction_11_tl0:
402 TRAP_INSTRUCTION 11
403
404/* TT = 0x10c, TL = 0, trap_instruction_12 */
405.org trap_table + TT_TRAP_INSTRUCTION(12)*ENTRY_SIZE
406.global trap_instruction_12_tl0
407trap_instruction_12_tl0:
408 TRAP_INSTRUCTION 12
409
410/* TT = 0x10d, TL = 0, trap_instruction_13 */
411.org trap_table + TT_TRAP_INSTRUCTION(13)*ENTRY_SIZE
412.global trap_instruction_13_tl0
413trap_instruction_13_tl0:
414 TRAP_INSTRUCTION 13
415
416/* TT = 0x10e, TL = 0, trap_instruction_14 */
417.org trap_table + TT_TRAP_INSTRUCTION(14)*ENTRY_SIZE
418.global trap_instruction_14_tl0
419trap_instruction_14_tl0:
420 TRAP_INSTRUCTION 14
421
422/* TT = 0x10f, TL = 0, trap_instruction_15 */
423.org trap_table + TT_TRAP_INSTRUCTION(15)*ENTRY_SIZE
424.global trap_instruction_15_tl0
425trap_instruction_15_tl0:
426 TRAP_INSTRUCTION 15
427
428/* TT = 0x110, TL = 0, trap_instruction_16 */
429.org trap_table + TT_TRAP_INSTRUCTION(16)*ENTRY_SIZE
430.global trap_instruction_16_tl0
431trap_instruction_16_tl0:
432 TRAP_INSTRUCTION 16
433
434/* TT = 0x111, TL = 0, trap_instruction_17 */
435.org trap_table + TT_TRAP_INSTRUCTION(17)*ENTRY_SIZE
436.global trap_instruction_17_tl0
437trap_instruction_17_tl0:
438 TRAP_INSTRUCTION 17
439
440/* TT = 0x112, TL = 0, trap_instruction_18 */
441.org trap_table + TT_TRAP_INSTRUCTION(18)*ENTRY_SIZE
442.global trap_instruction_18_tl0
443trap_instruction_18_tl0:
444 TRAP_INSTRUCTION 18
445
446/* TT = 0x113, TL = 0, trap_instruction_19 */
447.org trap_table + TT_TRAP_INSTRUCTION(19)*ENTRY_SIZE
448.global trap_instruction_19_tl0
449trap_instruction_19_tl0:
450 TRAP_INSTRUCTION 19
451
452/* TT = 0x114, TL = 0, trap_instruction_20 */
453.org trap_table + TT_TRAP_INSTRUCTION(20)*ENTRY_SIZE
454.global trap_instruction_20_tl0
455trap_instruction_20_tl0:
456 TRAP_INSTRUCTION 20
457
458/* TT = 0x115, TL = 0, trap_instruction_21 */
459.org trap_table + TT_TRAP_INSTRUCTION(21)*ENTRY_SIZE
460.global trap_instruction_21_tl0
461trap_instruction_21_tl0:
462 TRAP_INSTRUCTION 21
463
464/* TT = 0x116, TL = 0, trap_instruction_22 */
465.org trap_table + TT_TRAP_INSTRUCTION(22)*ENTRY_SIZE
466.global trap_instruction_22_tl0
467trap_instruction_22_tl0:
468 TRAP_INSTRUCTION 22
469
470/* TT = 0x117, TL = 0, trap_instruction_23 */
471.org trap_table + TT_TRAP_INSTRUCTION(23)*ENTRY_SIZE
472.global trap_instruction_23_tl0
473trap_instruction_23_tl0:
474 TRAP_INSTRUCTION 23
475
476/* TT = 0x118, TL = 0, trap_instruction_24 */
477.org trap_table + TT_TRAP_INSTRUCTION(24)*ENTRY_SIZE
478.global trap_instruction_24_tl0
479trap_instruction_24_tl0:
480 TRAP_INSTRUCTION 24
481
482/* TT = 0x119, TL = 0, trap_instruction_25 */
483.org trap_table + TT_TRAP_INSTRUCTION(25)*ENTRY_SIZE
484.global trap_instruction_25_tl0
485trap_instruction_25_tl0:
486 TRAP_INSTRUCTION 25
487
488/* TT = 0x11a, TL = 0, trap_instruction_26 */
489.org trap_table + TT_TRAP_INSTRUCTION(26)*ENTRY_SIZE
490.global trap_instruction_26_tl0
491trap_instruction_26_tl0:
492 TRAP_INSTRUCTION 26
493
494/* TT = 0x11b, TL = 0, trap_instruction_27 */
495.org trap_table + TT_TRAP_INSTRUCTION(27)*ENTRY_SIZE
496.global trap_instruction_27_tl0
497trap_instruction_27_tl0:
498 TRAP_INSTRUCTION 27
499
500/* TT = 0x11c, TL = 0, trap_instruction_28 */
501.org trap_table + TT_TRAP_INSTRUCTION(28)*ENTRY_SIZE
502.global trap_instruction_28_tl0
503trap_instruction_28_tl0:
504 TRAP_INSTRUCTION 28
505
506/* TT = 0x11d, TL = 0, trap_instruction_29 */
507.org trap_table + TT_TRAP_INSTRUCTION(29)*ENTRY_SIZE
508.global trap_instruction_29_tl0
509trap_instruction_29_tl0:
510 TRAP_INSTRUCTION 29
511
512/* TT = 0x11e, TL = 0, trap_instruction_30 */
513.org trap_table + TT_TRAP_INSTRUCTION(30)*ENTRY_SIZE
514.global trap_instruction_30_tl0
515trap_instruction_30_tl0:
516 TRAP_INSTRUCTION 30
517
518/* TT = 0x11f, TL = 0, trap_instruction_31 */
519.org trap_table + TT_TRAP_INSTRUCTION(31)*ENTRY_SIZE
520.global trap_instruction_31_tl0
521trap_instruction_31_tl0:
522 TRAP_INSTRUCTION 31
523
524/*
525 * Handlers for TL>0.
526 */
527
528/* TT = 0x08, TL > 0, instruction_access_exception */
529.org trap_table + (TT_INSTRUCTION_ACCESS_EXCEPTION+512)*ENTRY_SIZE
530.global instruction_access_exception_tl1
531instruction_access_exception_tl1:
532 wrpr %g0, 1, %tl
533 wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
534 PREEMPTIBLE_HANDLER instruction_access_exception
535
536/* TT = 0x0a, TL > 0, instruction_access_error */
537.org trap_table + (TT_INSTRUCTION_ACCESS_ERROR+512)*ENTRY_SIZE
538.global instruction_access_error_tl1
539instruction_access_error_tl1:
540 wrpr %g0, 1, %tl
541 PREEMPTIBLE_HANDLER instruction_access_error
542
543/* TT = 0x10, TL > 0, illegal_instruction */
544.org trap_table + (TT_ILLEGAL_INSTRUCTION+512)*ENTRY_SIZE
545.global illegal_instruction_tl1
546illegal_instruction_tl1:
547 wrpr %g0, 1, %tl
548 PREEMPTIBLE_HANDLER illegal_instruction
549
550/* TT = 0x24, TL > 0, clean_window handler */
551.org trap_table + (TT_CLEAN_WINDOW+512)*ENTRY_SIZE
552.global clean_window_tl1
553clean_window_tl1:
554 CLEAN_WINDOW_HANDLER
555
556/* TT = 0x28, TL > 0, division_by_zero */
557.org trap_table + (TT_DIVISION_BY_ZERO+512)*ENTRY_SIZE
558.global division_by_zero_tl1
559division_by_zero_tl1:
560 wrpr %g0, 1, %tl
561 PREEMPTIBLE_HANDLER division_by_zero
562
563/* TT = 0x30, TL > 0, data_access_exception */
564.org trap_table + (TT_DATA_ACCESS_EXCEPTION+512)*ENTRY_SIZE
565.global data_access_exception_tl1
566data_access_exception_tl1:
567 wrpr %g0, 1, %tl
568 wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
569 PREEMPTIBLE_HANDLER data_access_exception
570
571/* TT = 0x32, TL > 0, data_access_error */
572.org trap_table + (TT_DATA_ACCESS_ERROR+512)*ENTRY_SIZE
573.global data_access_error_tl1
574data_access_error_tl1:
575 wrpr %g0, 1, %tl
576 PREEMPTIBLE_HANDLER data_access_error
577
578/* TT = 0x34, TL > 0, mem_address_not_aligned */
579.org trap_table + (TT_MEM_ADDRESS_NOT_ALIGNED+512)*ENTRY_SIZE
580.global mem_address_not_aligned_tl1
581mem_address_not_aligned_tl1:
582 wrpr %g0, 1, %tl
583 PREEMPTIBLE_HANDLER mem_address_not_aligned
584
585/* TT = 0x68, TL > 0, fast_data_access_MMU_miss */
586.org trap_table + (TT_FAST_DATA_ACCESS_MMU_MISS+512)*ENTRY_SIZE
587.global fast_data_access_mmu_miss_handler_tl1
588fast_data_access_mmu_miss_handler_tl1:
589 FAST_DATA_ACCESS_MMU_MISS_HANDLER 1
590
591/* TT = 0x6c, TL > 0, fast_data_access_protection */
592.org trap_table + (TT_FAST_DATA_ACCESS_PROTECTION+512)*ENTRY_SIZE
593.global fast_data_access_protection_handler_tl1
594fast_data_access_protection_handler_tl1:
595 FAST_DATA_ACCESS_PROTECTION_HANDLER 1
596
597/* TT = 0x80, TL > 0, spill_0_normal handler */
598.org trap_table + (TT_SPILL_0_NORMAL+512)*ENTRY_SIZE
599.global spill_0_normal_tl1
600spill_0_normal_tl1:
601 SPILL_NORMAL_HANDLER_KERNEL
602
603/* TT = 0x88, TL > 0, spill_2_normal handler */
604.org trap_table + (TT_SPILL_2_NORMAL+512)*ENTRY_SIZE
605.global spill_2_normal_tl1
606spill_2_normal_tl1:
607 SPILL_TO_USPACE_WINDOW_BUFFER
608
609/* TT = 0xa0, TL > 0, spill_0_other handler */
610.org trap_table + (TT_SPILL_0_OTHER+512)*ENTRY_SIZE
611.global spill_0_other_tl1
612spill_0_other_tl1:
613 SPILL_TO_USPACE_WINDOW_BUFFER
614
615/* TT = 0xc0, TL > 0, fill_0_normal handler */
616.org trap_table + (TT_FILL_0_NORMAL+512)*ENTRY_SIZE
617.global fill_0_normal_tl1
618fill_0_normal_tl1:
619 FILL_NORMAL_HANDLER_KERNEL
620
621#define NOT(x) ((x) == 0)
622
623/* Preemptible trap handler for TL=1.
624 *
625 * This trap handler makes arrangements to make calling of scheduler() from
626 * within a trap context possible. It is called from several other trap
627 * handlers.
628 *
629 * This function can be entered either with interrupt globals or alternate globals.
630 * Memory management trap handlers are obliged to switch to one of those global sets
631 * prior to calling this function. Register window management functions are not
632 * allowed to modify the alternate global registers.
633 *
634 * Input registers:
635 * %g1 Address of function to call.
636 * %g2 First argument for the function.
637 * %g6 Pre-set as kernel stack base if trap from userspace.
638 * %g7 Pre-set as address of the userspace window buffer.
639 */
640.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
641 /*
642 * ASSERT(%tl == 1)
643 */
644 rdpr %tl, %g3
645 cmp %g3, 1
646 be 1f
647 nop
6480: ba 0b ! this is for debugging, if we ever get here
649 nop ! it will be easy to find
650
6511:
652.if NOT(\is_syscall)
653 rdpr %tstate, %g3
654
655 /*
656 * One of the ways this handler can be invoked is after a nested MMU trap from
657 * either spill_1_normal or fill_1_normal traps. Both of these traps manipulate
658 * the CWP register. We deal with the situation by simulating the MMU trap
659 * on TL=1 and restart the respective SAVE or RESTORE instruction once the MMU
660 * trap is resolved. However, because we are in the wrong window from the
661 * perspective of the MMU trap, we need to synchronize CWP with CWP from TL=0.
662 */
663 and %g3, TSTATE_CWP_MASK, %g4
664 wrpr %g4, 0, %cwp ! resynchronize CWP
665
666 andcc %g3, TSTATE_PRIV_BIT, %g0 ! if this trap came from the privileged mode...
667 bnz 0f ! ...skip setting of kernel stack and primary context
668 nop
669
670.endif
671 /*
672 * Normal window spills will go to the userspace window buffer.
673 */
674 wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(2), %wstate
675
676 wrpr %g0, NWINDOW - 1, %cleanwin ! prevent unnecessary clean_window exceptions
677
678 /*
679 * Switch to kernel stack. The old stack is
680 * automatically saved in the old window's %sp
681 * and the new window's %fp.
682 */
683 save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
684
685.if \is_syscall
686 /*
687 * Copy arguments for the syscall to the new window.
688 */
689 mov %i0, %o2
690 mov %i1, %o3
691 mov %i2, %o4
692 mov %i3, %o5
693.endif
694
695 /*
696 * Mark the CANRESTORE windows as OTHER windows.
697 */
698 rdpr %canrestore, %l0
699 wrpr %l0, %otherwin
700 wrpr %g0, %canrestore
701
702 /*
703 * Switch to primary context 0.
704 */
705 mov VA_PRIMARY_CONTEXT_REG, %l0
706 stxa %g0, [%l0] ASI_DMMU
707 rd %pc, %l0
708 flush %l0
709
710.if NOT(\is_syscall)
711 ba 1f
712 nop
7130:
714 save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
715
716 /*
717 * At this moment, we are using the kernel stack
718 * and have successfully allocated a register window.
719 */
7201:
721.endif
722 /*
723 * Other window spills will go to the userspace window buffer
724 * and normal spills will go to the kernel stack.
725 */
726 wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
727
728 /*
729 * Copy arguments.
730 */
731 mov %g1, %l0
732 mov %g2, %o0
733
734 /*
735 * Save TSTATE, TPC and TNPC aside.
736 */
737 rdpr %tstate, %g1
738 rdpr %tpc, %g2
739 rdpr %tnpc, %g3
740
741 /*
742 * The following memory accesses will not fault
743 * because special provisions are made to have
744 * the kernel stack of THREAD locked in DTLB.
745 */
746 stx %g1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE]
747 stx %g2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC]
748 stx %g3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC]
749
750 /*
751 * Save the Y register.
752 * This register is deprecated according to SPARC V9 specification
753 * and is only present for backward compatibility with previous
754 * versions of the SPARC architecture.
755 * Surprisingly, gcc makes use of this register without a notice.
756 */
757 rd %y, %g4
758 stx %g4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y]
759
760 wrpr %g0, 0, %tl
761 wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
762 SAVE_GLOBALS
763
764 /*
765 * Call the higher-level handler and pass istate as second parameter.
766 */
767 call %l0
768 add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
769
770.if \is_syscall
771 /*
772 * Copy the value returned by the syscall.
773 */
774 mov %o0, %i0
775.endif
776
777 RESTORE_GLOBALS
778 rdpr %pstate, %l1 ! we must preserve the PEF bit
779 wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
780 wrpr %g0, 1, %tl
781
782 /*
783 * Read TSTATE, TPC and TNPC from saved copy.
784 */
785 ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE], %g1
786 ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC], %g2
787 ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC], %g3
788
789 /*
790 * Restore Y.
791 */
792 ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y], %g4
793 wr %g4, %y
794
795 /*
796 * Copy PSTATE.PEF to the in-register copy of TSTATE.
797 */
798 and %l1, PSTATE_PEF_BIT, %l1
799 sllx %l1, TSTATE_PSTATE_SHIFT, %l1
800 sethi %hi(TSTATE_PEF_BIT), %g4
801 andn %g1, %g4, %g1
802 or %g1, %l1, %g1
803
804 /*
805 * Restore TSTATE, TPC and TNPC from saved copies.
806 */
807 wrpr %g1, 0, %tstate
808 wrpr %g2, 0, %tpc
809 wrpr %g3, 0, %tnpc
810
811
812 /*
813 * If OTHERWIN is zero, then all the userspace windows have been
814 * spilled to kernel memory (i.e. register window buffer). Moreover,
815 * if the scheduler was called in the meantime, all valid windows
816 * belonging to other threads were spilled by context_restore().
817 * If OTHERWIN is non-zero, then some userspace windows are still
818 * valid. Others might have been spilled. However, the CWP pointer
819 * needs no fixing because the scheduler had not been called.
820 */
821 rdpr %otherwin, %l0
822 brnz %l0, 0f
823 nop
824
825 /*
826 * OTHERWIN == 0
827 */
828
829 /*
830 * If TSTATE.CWP + 1 == CWP, then we still do not have to fix CWP.
831 */
832 and %g1, TSTATE_CWP_MASK, %l0
833 inc %l0
834 and %l0, NWINDOW - 1, %l0 ! %l0 mod NWINDOW
835 rdpr %cwp, %l1
836 cmp %l0, %l1
837 bz 0f ! CWP is ok
838 nop
839
840 /*
841 * Fix CWP.
842 * In order to recapitulate, the input registers in the current
843 * window are the output registers of the window to which we want
844 * to restore. Because the fill trap fills only input and local
845 * registers of a window, we need to preserve those output
846 * registers manually.
847 */
848 mov %sp, %g2
849 stx %i0, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0]
850 stx %i1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1]
851 stx %i2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2]
852 stx %i3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3]
853 stx %i4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4]
854 stx %i5, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5]
855 stx %i6, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6]
856 stx %i7, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7]
857 wrpr %l0, 0, %cwp
858 mov %g2, %sp
859 ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0], %i0
860 ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1], %i1
861 ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2], %i2
862 ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3], %i3
863 ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4], %i4
864 ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5], %i5
865 ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6], %i6
866 ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7], %i7
867
868 /*
869 * OTHERWIN != 0 or fall-through from the OTHERWIN == 0 case.
870 * The CWP has already been restored to the value it had after the SAVE
871 * at the beginning of this function.
872 */
8730:
874.if NOT(\is_syscall)
875 rdpr %tstate, %g1
876 andcc %g1, TSTATE_PRIV_BIT, %g0 ! if we are not returning to userspace...,
877 bnz 1f ! ...skip restoring userspace windows
878 nop
879.endif
880
881 /*
882 * Spills and fills will be processed by the {spill,fill}_1_normal
883 * handlers.
884 */
885 wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(1), %wstate
886
887 /*
888 * Set primary context according to secondary context.
889 */
890 wr %g0, ASI_DMMU, %asi
891 ldxa [VA_SECONDARY_CONTEXT_REG] %asi, %g1
892 stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi
893 rd %pc, %g1
894 flush %g1
895
896 rdpr %cwp, %g1
897 rdpr %otherwin, %g2
898
899 /*
900 * Skip all OTHERWIN windows and descend to the first window
901 * in the userspace window buffer.
902 */
903 sub %g1, %g2, %g3
904 dec %g3
905 and %g3, NWINDOW - 1, %g3
906 wrpr %g3, 0, %cwp
907
908 /*
909 * CWP is now in the window last saved in the userspace window buffer.
910 * Fill all windows stored in the buffer.
911 */
912 clr %g4
913 set PAGE_SIZE - 1, %g5
9140: andcc %g7, %g5, %g0 ! PAGE_SIZE alignment check
915 bz 0f ! %g7 is page-aligned, no more windows to refill
916 nop
917
918 add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7
919 ldx [%g7 + L0_OFFSET], %l0
920 ldx [%g7 + L1_OFFSET], %l1
921 ldx [%g7 + L2_OFFSET], %l2
922 ldx [%g7 + L3_OFFSET], %l3
923 ldx [%g7 + L4_OFFSET], %l4
924 ldx [%g7 + L5_OFFSET], %l5
925 ldx [%g7 + L6_OFFSET], %l6
926 ldx [%g7 + L7_OFFSET], %l7
927 ldx [%g7 + I0_OFFSET], %i0
928 ldx [%g7 + I1_OFFSET], %i1
929 ldx [%g7 + I2_OFFSET], %i2
930 ldx [%g7 + I3_OFFSET], %i3
931 ldx [%g7 + I4_OFFSET], %i4
932 ldx [%g7 + I5_OFFSET], %i5
933 ldx [%g7 + I6_OFFSET], %i6
934 ldx [%g7 + I7_OFFSET], %i7
935
936 dec %g3
937 and %g3, NWINDOW - 1, %g3
938 wrpr %g3, 0, %cwp ! switch to the preceeding window
939
940 ba 0b
941 inc %g4
942
9430:
944 /*
945 * Switch back to the proper current window and adjust
946 * OTHERWIN, CANRESTORE, CANSAVE and CLEANWIN.
947 */
948 wrpr %g1, 0, %cwp
949 add %g4, %g2, %g2
950 cmp %g2, NWINDOW - 2
951 bg 2f ! fix the CANRESTORE=NWINDOW-1 anomaly
952 mov NWINDOW - 2, %g1 ! use dealy slot for both cases
953 sub %g1, %g2, %g1
954
955 wrpr %g0, 0, %otherwin
956 wrpr %g1, 0, %cansave ! NWINDOW - 2 - CANRESTORE
957 wrpr %g2, 0, %canrestore ! OTHERWIN + windows in the buffer
958 wrpr %g2, 0, %cleanwin ! avoid information leak
959
9601:
961 restore
962
963.if \is_syscall
964 done
965.else
966 retry
967.endif
968
969 /*
970 * We got here in order to avoid inconsistency of the window state registers.
971 * If the:
972 *
973 * save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
974 *
975 * instruction trapped and spilled a register window into the userspace
976 * window buffer, we have just restored NWINDOW - 1 register windows.
977 * However, CANRESTORE can be only NWINDOW - 2 at most.
978 *
979 * The solution is to manually switch to (CWP - 1) mod NWINDOW
980 * and set the window state registers so that:
981 *
982 * CANRESTORE = NWINDOW - 2
983 * CLEANWIN = NWINDOW - 2
984 * CANSAVE = 0
985 * OTHERWIN = 0
986 *
987 * The RESTORE instruction is therfore to be skipped.
988 */
9892:
990 wrpr %g0, 0, %otherwin
991 wrpr %g0, 0, %cansave
992 wrpr %g1, 0, %canrestore
993 wrpr %g1, 0, %cleanwin
994
995 rdpr %cwp, %g1
996 dec %g1
997 and %g1, NWINDOW - 1, %g1
998 wrpr %g1, 0, %cwp ! CWP--
999
1000.if \is_syscall
1001 done
1002.else
1003 retry
1004.endif
1005
1006.endm
1007
1008.global preemptible_handler
1009preemptible_handler:
1010 PREEMPTIBLE_HANDLER_TEMPLATE 0
1011
1012.global trap_instruction_handler
1013trap_instruction_handler:
1014 PREEMPTIBLE_HANDLER_TEMPLATE 1
Note: See TracBrowser for help on using the repository browser.