source: mainline/kernel/arch/sparc64/src/trap/sun4v/trap_table.S@ 3349e7d

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

Call exc_dispatch() also for TT_CPU_MONDO.

  • Property mode set to 100644
File size: 33.1 KB
Line 
1#
2# Copyright (c) 2005 Jakub Jermar
3# Copyright (c) 2008 Pavel Rimsky
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9#
10# - Redistributions of source code must retain the above copyright
11# notice, this list of conditions and the following disclaimer.
12# - Redistributions in binary form must reproduce the above copyright
13# notice, this list of conditions and the following disclaimer in the
14# documentation and/or other materials provided with the distribution.
15# - The name of the author may not be used to endorse or promote products
16# derived from this software without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28#
29
30/**
31 * @file
32 * @brief This file contains kernel trap table.
33 */
34
35.register %g2, #scratch
36.register %g3, #scratch
37
38.text
39
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/sun4v/mmu.h>
46#include <arch/mm/sun4v/mmu.h>
47#include <arch/mm/page.h>
48#include <arch/stack.h>
49#include <arch/sun4v/regdef.h>
50#include <arch/sun4v/arch.h>
51#include <arch/sun4v/cpu.h>
52
53#define TABLE_SIZE TRAP_TABLE_SIZE
54#define ENTRY_SIZE TRAP_TABLE_ENTRY_SIZE
55
56/*
57 * Kernel trap table.
58 */
59.align TABLE_SIZE
60.global trap_table
61trap_table:
62
63/* TT = 0x08, TL = 0, instruction_access_exception */
64/* TT = 0x08, TL = 0, IAE_privilege_violation on UltraSPARC T2 */
65.org trap_table + TT_INSTRUCTION_ACCESS_EXCEPTION*ENTRY_SIZE
66.global instruction_access_exception_tl0
67instruction_access_exception_tl0:
68 mov TT_INSTRUCTION_ACCESS_EXCEPTION, %g2
69 clr %g5
70 PREEMPTIBLE_HANDLER exc_dispatch
71
72/* TT = 0x09, TL = 0, instruction_access_mmu_miss */
73.org trap_table + TT_INSTRUCTION_ACCESS_MMU_MISS*ENTRY_SIZE
74.global instruction_access_mmu_miss_handler_tl0
75 ba,a %xcc, fast_instruction_access_mmu_miss_handler_tl0
76
77/* TT = 0x0a, TL = 0, instruction_access_error */
78.org trap_table + TT_INSTRUCTION_ACCESS_ERROR*ENTRY_SIZE
79.global instruction_access_error_tl0
80instruction_access_error_tl0:
81 mov TT_INSTRUCTION_ACCESS_ERROR, %g2
82 clr %g5
83 PREEMPTIBLE_HANDLER exc_dispatch
84
85/* TT = 0x0b, TL = 0, IAE_unauth_access */
86.org trap_table + TT_IAE_UNAUTH_ACCESS*ENTRY_SIZE
87.global iae_unauth_access_tl0
88iae_unauth_access_tl0:
89 mov TT_IAE_UNAUTH_ACCESS, %g2
90 clr %g5
91 PREEMPTIBLE_HANDLER exc_dispatch
92
93/* TT = 0x0c, TL = 0, IAE_nfo_page */
94.org trap_table + TT_IAE_NFO_PAGE*ENTRY_SIZE
95.global iae_nfo_page_tl0
96iae_nfo_page_tl0:
97 mov TT_IAE_NFO_PAGE, %g2
98 clr %g5
99 PREEMPTIBLE_HANDLER exc_dispatch
100
101/* TT = 0x10, TL = 0, illegal_instruction */
102.org trap_table + TT_ILLEGAL_INSTRUCTION*ENTRY_SIZE
103.global illegal_instruction_tl0
104illegal_instruction_tl0:
105 mov TT_ILLEGAL_INSTRUCTION, %g2
106 clr %g5
107 PREEMPTIBLE_HANDLER exc_dispatch
108
109/* TT = 0x11, TL = 0, privileged_opcode */
110.org trap_table + TT_PRIVILEGED_OPCODE*ENTRY_SIZE
111.global privileged_opcode_tl0
112privileged_opcode_tl0:
113 mov TT_PRIVILEGED_OPCODE, %g2
114 clr %g5
115 PREEMPTIBLE_HANDLER exc_dispatch
116
117/* TT = 0x12, TL = 0, unimplemented_LDD */
118.org trap_table + TT_UNIMPLEMENTED_LDD*ENTRY_SIZE
119.global unimplemented_LDD_tl0
120unimplemented_LDD_tl0:
121 mov TT_UNIMPLEMENTED_LDD, %g2
122 clr %g5
123 PREEMPTIBLE_HANDLER exc_dispatch
124
125/* TT = 0x13, TL = 0, unimplemented_STD */
126.org trap_table + TT_UNIMPLEMENTED_STD*ENTRY_SIZE
127.global unimplemented_STD_tl0
128unimplemented_STD_tl0:
129 mov TT_UNIMPLEMENTED_STD, %g2
130 clr %g5
131 PREEMPTIBLE_HANDLER exc_dispatch
132
133/* TT = 0x14, TL = 0, DAE_invalid_asi */
134.org trap_table + TT_DAE_INVALID_ASI*ENTRY_SIZE
135.global dae_invalid_asi_tl0
136dae_invalid_asi_tl0:
137 mov TT_DAE_INVALID_ASI, %g2
138 clr %g5
139 PREEMPTIBLE_HANDLER exc_dispatch
140
141/* TT = 0x15, TL = 0, DAE_privilege_violation */
142.org trap_table + TT_DAE_PRIVILEGE_VIOLATION*ENTRY_SIZE
143.global dae_privilege_violation_tl0
144dae_privilege_violation_tl0:
145 mov TT_DAE_PRIVILEGE_VIOLATION, %g2
146 clr %g5
147 PREEMPTIBLE_HANDLER exc_dispatch
148
149/* TT = 0x16, TL = 0, DAE_nc_page */
150.org trap_table + TT_DAE_NC_PAGE*ENTRY_SIZE
151.global dae_nc_page_tl0
152dae_nc_page_tl0:
153 mov TT_DAE_NC_PAGE, %g2
154 clr %g5
155 PREEMPTIBLE_HANDLER exc_dispatch
156
157/* TT = 0x17, TL = 0, DAE_nfo_page */
158.org trap_table + TT_DAE_NFO_PAGE*ENTRY_SIZE
159.global dae_nfo_page_tl0
160dae_nfo_page_tl0:
161 mov TT_DAE_NFO_PAGE, %g2
162 clr %g5
163 PREEMPTIBLE_HANDLER exc_dispatch
164
165/* TT = 0x20, TL = 0, fb_disabled handler */
166.org trap_table + TT_FP_DISABLED*ENTRY_SIZE
167.global fb_disabled_tl0
168fp_disabled_tl0:
169 mov TT_FP_DISABLED, %g2
170 clr %g5
171 PREEMPTIBLE_HANDLER exc_dispatch
172
173/* TT = 0x21, TL = 0, fb_exception_ieee_754 handler */
174.org trap_table + TT_FP_EXCEPTION_IEEE_754*ENTRY_SIZE
175.global fb_exception_ieee_754_tl0
176fp_exception_ieee_754_tl0:
177 mov TT_FP_EXCEPTION_IEEE_754, %g2
178 clr %g5
179 PREEMPTIBLE_HANDLER exc_dispatch
180
181/* TT = 0x22, TL = 0, fb_exception_other handler */
182.org trap_table + TT_FP_EXCEPTION_OTHER*ENTRY_SIZE
183.global fb_exception_other_tl0
184fp_exception_other_tl0:
185 mov TT_FP_EXCEPTION_OTHER, %g2
186 clr %g5
187 PREEMPTIBLE_HANDLER exc_dispatch
188
189/* TT = 0x23, TL = 0, tag_overflow */
190.org trap_table + TT_TAG_OVERFLOW*ENTRY_SIZE
191.global tag_overflow_tl0
192tag_overflow_tl0:
193 mov TT_TAG_OVERFLOW, %g2
194 clr %g5
195 PREEMPTIBLE_HANDLER exc_dispatch
196
197/* TT = 0x24, TL = 0, clean_window handler */
198.org trap_table + TT_CLEAN_WINDOW*ENTRY_SIZE
199.global clean_window_tl0
200clean_window_tl0:
201 CLEAN_WINDOW_HANDLER
202
203/* TT = 0x28, TL = 0, division_by_zero */
204.org trap_table + TT_DIVISION_BY_ZERO*ENTRY_SIZE
205.global division_by_zero_tl0
206division_by_zero_tl0:
207 mov TT_DIVISION_BY_ZERO, %g2
208 clr %g5
209 PREEMPTIBLE_HANDLER exc_dispatch
210
211/* TT = 0x30, TL = 0, data_access_exception */
212/* TT = 0x30, TL = 0, DAE_side_effect_page for UltraPSARC T2 */
213.org trap_table + TT_DATA_ACCESS_EXCEPTION*ENTRY_SIZE
214.global data_access_exception_tl0
215data_access_exception_tl0:
216 mov TT_DATA_ACCESS_EXCEPTION, %g2
217 clr %g5
218 PREEMPTIBLE_HANDLER exc_dispatch
219
220/* TT = 0x31, TL = 0, data_access_mmu_miss */
221.org trap_table + TT_DATA_ACCESS_MMU_MISS*ENTRY_SIZE
222.global data_access_mmu_miss_tl0
223data_access_mmu_miss_tl0:
224 ba,a %xcc, fast_data_access_mmu_miss_handler_tl0
225
226/* TT = 0x32, TL = 0, data_access_error */
227.org trap_table + TT_DATA_ACCESS_ERROR*ENTRY_SIZE
228.global data_access_error_tl0
229data_access_error_tl0:
230 mov TT_DATA_ACCESS_ERROR, %g2
231 clr %g5
232 PREEMPTIBLE_HANDLER exc_dispatch
233
234/* TT = 0x34, TL = 0, mem_address_not_aligned */
235.org trap_table + TT_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
236.global mem_address_not_aligned_tl0
237mem_address_not_aligned_tl0:
238 mov TT_MEM_ADDRESS_NOT_ALIGNED, %g2
239 clr %g5
240 PREEMPTIBLE_HANDLER exc_dispatch
241
242/* TT = 0x35, TL = 0, LDDF_mem_address_not_aligned */
243.org trap_table + TT_LDDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
244.global LDDF_mem_address_not_aligned_tl0
245LDDF_mem_address_not_aligned_tl0:
246 mov TT_LDDF_MEM_ADDRESS_NOT_ALIGNED, %g2
247 clr %g5
248 PREEMPTIBLE_HANDLER exc_dispatch
249
250/* TT = 0x36, TL = 0, STDF_mem_address_not_aligned */
251.org trap_table + TT_STDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
252.global STDF_mem_address_not_aligned_tl0
253STDF_mem_address_not_aligned_tl0:
254 mov TT_STDF_MEM_ADDRESS_NOT_ALIGNED, %g2
255 clr %g5
256 PREEMPTIBLE_HANDLER exc_dispatch
257
258/* TT = 0x37, TL = 0, privileged_action */
259.org trap_table + TT_PRIVILEGED_ACTION*ENTRY_SIZE
260.global privileged_action_tl0
261privileged_action_tl0:
262 mov TT_PRIVILEGED_ACTION, %g2
263 clr %g5
264 PREEMPTIBLE_HANDLER exc_dispatch
265
266/* TT = 0x38, TL = 0, LDQF_mem_address_not_aligned */
267.org trap_table + TT_LDQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
268.global LDQF_mem_address_not_aligned_tl0
269LDQF_mem_address_not_aligned_tl0:
270 mov TT_LDQF_MEM_ADDRESS_NOT_ALIGNED, %g2
271 clr %g5
272 PREEMPTIBLE_HANDLER exc_dispatch
273
274/* TT = 0x39, TL = 0, STQF_mem_address_not_aligned */
275.org trap_table + TT_STQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
276.global STQF_mem_address_not_aligned_tl0
277STQF_mem_address_not_aligned_tl0:
278 mov TT_STQF_MEM_ADDRESS_NOT_ALIGNED, %g2
279 clr %g5
280 PREEMPTIBLE_HANDLER exc_dispatch
281
282/* TT = 0x41, TL = 0, interrupt_level_1 handler */
283.org trap_table + TT_INTERRUPT_LEVEL_1*ENTRY_SIZE
284.global interrupt_level_1_handler_tl0
285interrupt_level_1_handler_tl0:
286 mov TT_INTERRUPT_LEVEL_1, %g2
287 clr %g5
288 PREEMPTIBLE_HANDLER exc_dispatch
289
290/* TT = 0x42, TL = 0, interrupt_level_2 handler */
291.org trap_table + TT_INTERRUPT_LEVEL_2*ENTRY_SIZE
292.global interrupt_level_2_handler_tl0
293interrupt_level_2_handler_tl0:
294 mov TT_INTERRUPT_LEVEL_2, %g2
295 clr %g5
296 PREEMPTIBLE_HANDLER exc_dispatch
297
298/* TT = 0x43, TL = 0, interrupt_level_3 handler */
299.org trap_table + TT_INTERRUPT_LEVEL_3*ENTRY_SIZE
300.global interrupt_level_3_handler_tl0
301interrupt_level_3_handler_tl0:
302 mov TT_INTERRUPT_LEVEL_3, %g2
303 clr %g5
304 PREEMPTIBLE_HANDLER exc_dispatch
305
306/* TT = 0x44, TL = 0, interrupt_level_4 handler */
307.org trap_table + TT_INTERRUPT_LEVEL_4*ENTRY_SIZE
308.global interrupt_level_4_handler_tl0
309interrupt_level_4_handler_tl0:
310 mov TT_INTERRUPT_LEVEL_4, %g2
311 clr %g5
312 PREEMPTIBLE_HANDLER exc_dispatch
313
314/* TT = 0x45, TL = 0, interrupt_level_5 handler */
315.org trap_table + TT_INTERRUPT_LEVEL_5*ENTRY_SIZE
316.global interrupt_level_5_handler_tl0
317interrupt_level_5_handler_tl0:
318 mov TT_INTERRUPT_LEVEL_5, %g2
319 clr %g5
320 PREEMPTIBLE_HANDLER exc_dispatch
321
322/* TT = 0x46, TL = 0, interrupt_level_6 handler */
323.org trap_table + TT_INTERRUPT_LEVEL_6*ENTRY_SIZE
324.global interrupt_level_6_handler_tl0
325interrupt_level_6_handler_tl0:
326 mov TT_INTERRUPT_LEVEL_6, %g2
327 clr %g5
328 PREEMPTIBLE_HANDLER exc_dispatch
329
330/* TT = 0x47, TL = 0, interrupt_level_7 handler */
331.org trap_table + TT_INTERRUPT_LEVEL_7*ENTRY_SIZE
332.global interrupt_level_7_handler_tl0
333interrupt_level_7_handler_tl0:
334 mov TT_INTERRUPT_LEVEL_7, %g2
335 clr %g5
336 PREEMPTIBLE_HANDLER exc_dispatch
337
338/* TT = 0x48, TL = 0, interrupt_level_8 handler */
339.org trap_table + TT_INTERRUPT_LEVEL_8*ENTRY_SIZE
340.global interrupt_level_8_handler_tl0
341interrupt_level_8_handler_tl0:
342 mov TT_INTERRUPT_LEVEL_8, %g2
343 clr %g5
344 PREEMPTIBLE_HANDLER exc_dispatch
345
346/* TT = 0x49, TL = 0, interrupt_level_9 handler */
347.org trap_table + TT_INTERRUPT_LEVEL_9*ENTRY_SIZE
348.global interrupt_level_9_handler_tl0
349interrupt_level_9_handler_tl0:
350 mov TT_INTERRUPT_LEVEL_9, %g2
351 clr %g5
352 PREEMPTIBLE_HANDLER exc_dispatch
353
354/* TT = 0x4a, TL = 0, interrupt_level_10 handler */
355.org trap_table + TT_INTERRUPT_LEVEL_10*ENTRY_SIZE
356.global interrupt_level_10_handler_tl0
357interrupt_level_10_handler_tl0:
358 mov TT_INTERRUPT_LEVEL_10, %g2
359 clr %g5
360 PREEMPTIBLE_HANDLER exc_dispatch
361
362/* TT = 0x4b, TL = 0, interrupt_level_11 handler */
363.org trap_table + TT_INTERRUPT_LEVEL_11*ENTRY_SIZE
364.global interrupt_level_11_handler_tl0
365interrupt_level_11_handler_tl0:
366 mov TT_INTERRUPT_LEVEL_11, %g2
367 clr %g5
368 PREEMPTIBLE_HANDLER exc_dispatch
369
370/* TT = 0x4c, TL = 0, interrupt_level_12 handler */
371.org trap_table + TT_INTERRUPT_LEVEL_12*ENTRY_SIZE
372.global interrupt_level_12_handler_tl0
373interrupt_level_12_handler_tl0:
374 mov TT_INTERRUPT_LEVEL_12, %g2
375 clr %g5
376 PREEMPTIBLE_HANDLER exc_dispatch
377
378/* TT = 0x4d, TL = 0, interrupt_level_13 handler */
379.org trap_table + TT_INTERRUPT_LEVEL_13*ENTRY_SIZE
380.global interrupt_level_13_handler_tl0
381interrupt_level_13_handler_tl0:
382 mov TT_INTERRUPT_LEVEL_13, %g2
383 clr %g5
384 PREEMPTIBLE_HANDLER exc_dispatch
385
386/* TT = 0x4e, TL = 0, interrupt_level_14 handler */
387.org trap_table + TT_INTERRUPT_LEVEL_14*ENTRY_SIZE
388.global interrupt_level_14_handler_tl0
389interrupt_level_14_handler_tl0:
390 mov TT_INTERRUPT_LEVEL_14, %g2
391 clr %g5
392 PREEMPTIBLE_HANDLER exc_dispatch
393
394/* TT = 0x4f, TL = 0, interrupt_level_15 handler */
395.org trap_table + TT_INTERRUPT_LEVEL_15*ENTRY_SIZE
396.global interrupt_level_15_handler_tl0
397interrupt_level_15_handler_tl0:
398 mov TT_INTERRUPT_LEVEL_15, %g2
399 clr %g5
400 PREEMPTIBLE_HANDLER exc_dispatch
401
402/* TT = 0x64, TL = 0, fast_instruction_access_MMU_miss */
403.org trap_table + TT_FAST_INSTRUCTION_ACCESS_MMU_MISS*ENTRY_SIZE
404.global fast_instruction_access_mmu_miss_handler_tl0
405fast_instruction_access_mmu_miss_handler_tl0:
406 FAST_INSTRUCTION_ACCESS_MMU_MISS_HANDLER
407
408/* TT = 0x68, TL = 0, fast_data_access_MMU_miss */
409.org trap_table + TT_FAST_DATA_ACCESS_MMU_MISS*ENTRY_SIZE
410.global fast_data_access_mmu_miss_handler_tl0
411fast_data_access_mmu_miss_handler_tl0:
412 FAST_DATA_ACCESS_MMU_MISS_HANDLER 0
413
414/* TT = 0x6c, TL = 0, fast_data_access_protection */
415.org trap_table + TT_FAST_DATA_ACCESS_PROTECTION*ENTRY_SIZE
416.global fast_data_access_protection_handler_tl0
417fast_data_access_protection_handler_tl0:
418 FAST_DATA_ACCESS_PROTECTION_HANDLER 0
419
420/* TT = 0x7c, TL = 0, cpu_mondo */
421.org trap_table + TT_CPU_MONDO*ENTRY_SIZE
422.global cpu_mondo_handler_tl0
423cpu_mondo_handler_tl0:
424 mov TT_CPU_MONDO, %g2
425 clr %g5
426 PREEMPTIBLE_HANDLER exc_dispatch
427
428/* TT = 0x80, TL = 0, spill_0_normal handler */
429.org trap_table + TT_SPILL_0_NORMAL*ENTRY_SIZE
430.global spill_0_normal_tl0
431spill_0_normal_tl0:
432 SPILL_NORMAL_HANDLER_KERNEL
433
434/* TT = 0x84, TL = 0, spill_1_normal handler */
435.org trap_table + TT_SPILL_1_NORMAL*ENTRY_SIZE
436.global spill_1_normal_tl0
437spill_1_normal_tl0:
438 SPILL_NORMAL_HANDLER_USERSPACE
439
440/* TT = 0x88, TL = 0, spill_2_normal handler */
441.org trap_table + TT_SPILL_2_NORMAL*ENTRY_SIZE
442.global spill_2_normal_tl0
443spill_2_normal_tl0:
444 SPILL_TO_USPACE_WINDOW_BUFFER
445
446/* TT = 0xa0, TL = 0, spill_0_other handler */
447.org trap_table + TT_SPILL_0_OTHER*ENTRY_SIZE
448.global spill_0_other_tl0
449spill_0_other_tl0:
450 SPILL_TO_USPACE_WINDOW_BUFFER
451
452/* TT = 0xc0, TL = 0, fill_0_normal handler */
453.org trap_table + TT_FILL_0_NORMAL*ENTRY_SIZE
454.global fill_0_normal_tl0
455fill_0_normal_tl0:
456 FILL_NORMAL_HANDLER_KERNEL
457
458/* TT = 0xc4, TL = 0, fill_1_normal handler */
459.org trap_table + TT_FILL_1_NORMAL*ENTRY_SIZE
460.global fill_1_normal_tl0
461fill_1_normal_tl0:
462 FILL_NORMAL_HANDLER_USERSPACE
463
464/* TT = 0x100 - 0x17f, TL = 0, trap_instruction_0 - trap_instruction_7f */
465.irp cur, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\
466 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\
467 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,\
468 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,\
469 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,\
470 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,\
471 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,\
472 127
473.org trap_table + (TT_TRAP_INSTRUCTION_0+\cur)*ENTRY_SIZE
474.global trap_instruction_\cur\()_tl0
475trap_instruction_\cur\()_tl0:
476 mov \cur, %g2
477 ba %xcc, trap_instruction_handler
478 clr %g5
479.endr
480
481/*
482 * Handlers for TL>0.
483 */
484
485/* TT = 0x08, TL > 0, instruction_access_exception */
486/* TT = 0x08, TL > 0, IAE_privilege_violation on UltraSPARC T2 */
487.org trap_table + (TT_INSTRUCTION_ACCESS_EXCEPTION+512)*ENTRY_SIZE
488.global instruction_access_exception_tl1
489instruction_access_exception_tl1:
490 wrpr %g0, 1, %tl
491 mov TT_INSTRUCTION_ACCESS_EXCEPTION, %g2
492 clr %g5
493 PREEMPTIBLE_HANDLER exc_dispatch
494
495/* TT = 0x09, TL > 0, instruction_access_mmu_miss */
496.org trap_table + (TT_INSTRUCTION_ACCESS_MMU_MISS+512)*ENTRY_SIZE
497.global instruction_access_mmu_miss_handler_tl1
498 wrpr %g0, 1, %tl
499 ba,a %xcc, fast_instruction_access_mmu_miss_handler_tl0
500
501/* TT = 0x0a, TL > 0, instruction_access_error */
502.org trap_table + (TT_INSTRUCTION_ACCESS_ERROR+512)*ENTRY_SIZE
503.global instruction_access_error_tl1
504instruction_access_error_tl1:
505 wrpr %g0, 1, %tl
506 mov TT_INSTRUCTION_ACCESS_ERROR, %g2
507 clr %g5
508 PREEMPTIBLE_HANDLER exc_dispatch
509
510/* TT = 0x0b, TL > 0, IAE_unauth_access */
511.org trap_table + (TT_IAE_UNAUTH_ACCESS+512)*ENTRY_SIZE
512.global iae_unauth_access_tl1
513iae_unauth_access_tl1:
514 wrpr %g0, 1, %tl
515 mov TT_IAE_UNAUTH_ACCESS, %g2
516 clr %g5
517 PREEMPTIBLE_HANDLER exc_dispatch
518
519/* TT = 0x0c, TL > 0, IAE_nfo_page */
520.org trap_table + (TT_IAE_NFO_PAGE+512)*ENTRY_SIZE
521.global iae_nfo_page_tl1
522iae_nfo_page_tl1:
523 wrpr %g0, 1, %tl
524 mov TT_IAE_NFO_PAGE, %g2
525 clr %g5
526 PREEMPTIBLE_HANDLER exc_dispatch
527
528/* TT = 0x10, TL > 0, illegal_instruction */
529.org trap_table + (TT_ILLEGAL_INSTRUCTION+512)*ENTRY_SIZE
530.global illegal_instruction_tl1
531illegal_instruction_tl1:
532 wrpr %g0, 1, %tl
533 mov TT_ILLEGAL_INSTRUCTION, %g2
534 clr %g5
535 PREEMPTIBLE_HANDLER exc_dispatch
536
537/* TT = 0x14, TL > 0, DAE_invalid_asi */
538.org trap_table + (TT_DAE_INVALID_ASI+512)*ENTRY_SIZE
539.global dae_invalid_asi_tl1
540dae_invalid_asi_tl1:
541 wrpr %g0, 1, %tl
542 mov TT_DAE_INVALID_ASI, %g2
543 clr %g5
544 PREEMPTIBLE_HANDLER exc_dispatch
545
546/* TT = 0x15, TL > 0, DAE_privilege_violation */
547.org trap_table + (TT_DAE_PRIVILEGE_VIOLATION+512)*ENTRY_SIZE
548.global dae_privilege_violation_tl1
549dae_privilege_violation_tl1:
550 wrpr %g0, 1, %tl
551 mov TT_DAE_PRIVILEGE_VIOLATION, %g2
552 clr %g5
553 PREEMPTIBLE_HANDLER exc_dispatch
554
555/* TT = 0x16, TL > 0, DAE_nc_page */
556.org trap_table + (TT_DAE_NC_PAGE+512)*ENTRY_SIZE
557.global dae_nc_page_tl1
558dae_nc_page_tl1:
559 wrpr %g0, 1, %tl
560 mov TT_DAE_NC_PAGE, %g2
561 clr %g5
562 PREEMPTIBLE_HANDLER exc_dispatch
563
564/* TT = 0x17, TL > 0, DAE_nfo_page */
565.org trap_table + (TT_DAE_NFO_PAGE+512)*ENTRY_SIZE
566.global dae_nfo_page_tl1
567dae_nfo_page_tl1:
568 wrpr %g0, 1, %tl
569 mov TT_DAE_NFO_PAGE, %g2
570 clr %g5
571 PREEMPTIBLE_HANDLER exc_dispatch
572
573/* TT = 0x24, TL > 0, clean_window handler */
574.org trap_table + (TT_CLEAN_WINDOW+512)*ENTRY_SIZE
575.global clean_window_tl1
576clean_window_tl1:
577 CLEAN_WINDOW_HANDLER
578
579/* TT = 0x28, TL > 0, division_by_zero */
580.org trap_table + (TT_DIVISION_BY_ZERO+512)*ENTRY_SIZE
581.global division_by_zero_tl1
582division_by_zero_tl1:
583 wrpr %g0, 1, %tl
584 mov TT_DIVISION_BY_ZERO, %g2
585 clr %g5
586 PREEMPTIBLE_HANDLER exc_dispatch
587
588/* TT = 0x30, TL > 0, data_access_exception */
589.org trap_table + (TT_DATA_ACCESS_EXCEPTION+512)*ENTRY_SIZE
590.global data_access_exception_tl1
591data_access_exception_tl1:
592 wrpr %g0, 1, %tl
593 mov TT_DATA_ACCESS_EXCEPTION, %g2
594 clr %g5
595 PREEMPTIBLE_HANDLER exc_dispatch
596
597/* TT = 0x31, TL > 0, data_access_mmu_miss */
598.org trap_table + (TT_DATA_ACCESS_MMU_MISS+512)*ENTRY_SIZE
599.global data_access_mmu_miss_tl1
600data_access_mmu_miss_tl1:
601 ba,a %xcc, fast_data_access_mmu_miss_handler_tl1
602
603/* TT = 0x32, TL > 0, data_access_error */
604.org trap_table + (TT_DATA_ACCESS_ERROR+512)*ENTRY_SIZE
605.global data_access_error_tl1
606data_access_error_tl1:
607 wrpr %g0, 1, %tl
608 mov TT_DATA_ACCESS_ERROR, %g2
609 clr %g5
610 PREEMPTIBLE_HANDLER exc_dispatch
611
612/* TT = 0x34, TL > 0, mem_address_not_aligned */
613.org trap_table + (TT_MEM_ADDRESS_NOT_ALIGNED+512)*ENTRY_SIZE
614.global mem_address_not_aligned_tl1
615mem_address_not_aligned_tl1:
616 wrpr %g0, 1, %tl
617 mov TT_MEM_ADDRESS_NOT_ALIGNED, %g2
618 clr %g5
619 PREEMPTIBLE_HANDLER exc_dispatch
620
621/* TT = 0x68, TL > 0, fast_data_access_MMU_miss */
622.org trap_table + (TT_FAST_DATA_ACCESS_MMU_MISS+512)*ENTRY_SIZE
623.global fast_data_access_mmu_miss_handler_tl1
624fast_data_access_mmu_miss_handler_tl1:
625 FAST_DATA_ACCESS_MMU_MISS_HANDLER 1
626
627/* TT = 0x6c, TL > 0, fast_data_access_protection */
628.org trap_table + (TT_FAST_DATA_ACCESS_PROTECTION+512)*ENTRY_SIZE
629.global fast_data_access_protection_handler_tl1
630fast_data_access_protection_handler_tl1:
631 FAST_DATA_ACCESS_PROTECTION_HANDLER 1
632
633/* TT = 0x7c, TL > 0, cpu_mondo */
634.org trap_table + (TT_CPU_MONDO+512)*ENTRY_SIZE
635.global cpu_mondo_handler_tl1
636cpu_mondo_handler_tl1:
637 wrpr %g0, %tl
638 mov TT_CPU_MONDO, %g2
639 clr %g5
640 PREEMPTIBLE_HANDLER exc_dispatch
641
642/* TT = 0x80, TL > 0, spill_0_normal handler */
643.org trap_table + (TT_SPILL_0_NORMAL+512)*ENTRY_SIZE
644.global spill_0_normal_tl1
645spill_0_normal_tl1:
646 SPILL_NORMAL_HANDLER_KERNEL
647
648/* TT = 0x88, TL > 0, spill_2_normal handler */
649.org trap_table + (TT_SPILL_2_NORMAL+512)*ENTRY_SIZE
650.global spill_2_normal_tl1
651spill_2_normal_tl1:
652 SPILL_TO_USPACE_WINDOW_BUFFER
653
654/* TT = 0xa0, TL > 0, spill_0_other handler */
655.org trap_table + (TT_SPILL_0_OTHER+512)*ENTRY_SIZE
656.global spill_0_other_tl1
657spill_0_other_tl1:
658 SPILL_TO_USPACE_WINDOW_BUFFER
659
660/* TT = 0xc0, TL > 0, fill_0_normal handler */
661.org trap_table + (TT_FILL_0_NORMAL+512)*ENTRY_SIZE
662.global fill_0_normal_tl1
663fill_0_normal_tl1:
664 FILL_NORMAL_HANDLER_KERNEL
665
666.align TABLE_SIZE
667
668
669/*
670 * Spills the window at CWP + 2 to the kernel stack. This macro is to be
671 * used before doing SAVE when the spill trap is undesirable.
672 *
673 * Parameters:
674 * tmpreg1 global register to be used for scratching purposes
675 * tmpreg2 global register to be used for scratching purposes
676 */
677.macro INLINE_SPILL tmpreg1, tmpreg2
678 ! CWP := CWP + 2
679 rdpr %cwp, \tmpreg2
680 add \tmpreg2, 2, \tmpreg1
681 and \tmpreg1, NWINDOWS - 1, \tmpreg1 ! modulo NWINDOWS
682 wrpr \tmpreg1, %cwp
683
684 ! spill to kernel stack
685 stx %l0, [%sp + STACK_BIAS + L0_OFFSET]
686 stx %l1, [%sp + STACK_BIAS + L1_OFFSET]
687 stx %l2, [%sp + STACK_BIAS + L2_OFFSET]
688 stx %l3, [%sp + STACK_BIAS + L3_OFFSET]
689 stx %l4, [%sp + STACK_BIAS + L4_OFFSET]
690 stx %l5, [%sp + STACK_BIAS + L5_OFFSET]
691 stx %l6, [%sp + STACK_BIAS + L6_OFFSET]
692 stx %l7, [%sp + STACK_BIAS + L7_OFFSET]
693 stx %i0, [%sp + STACK_BIAS + I0_OFFSET]
694 stx %i1, [%sp + STACK_BIAS + I1_OFFSET]
695 stx %i2, [%sp + STACK_BIAS + I2_OFFSET]
696 stx %i3, [%sp + STACK_BIAS + I3_OFFSET]
697 stx %i4, [%sp + STACK_BIAS + I4_OFFSET]
698 stx %i5, [%sp + STACK_BIAS + I5_OFFSET]
699 stx %i6, [%sp + STACK_BIAS + I6_OFFSET]
700 stx %i7, [%sp + STACK_BIAS + I7_OFFSET]
701
702 ! CWP := CWP - 2
703 wrpr \tmpreg2, %cwp
704
705 saved
706.endm
707
708/*
709 * Fill the window at CWP - 1 from the kernel stack. This macro is to be
710 * used before doing RESTORE when the fill trap is undesirable.
711 *
712 * Parameters:
713 * tmpreg1 global register to be used for scratching purposes
714 * tmpreg2 global register to be used for scratching purposes
715 */
716.macro INLINE_FILL tmpreg1, tmpreg2
717 ! CWP := CWP - 1
718 rdpr %cwp, \tmpreg2
719 add \tmpreg2, NWINDOWS - 1, \tmpreg1
720 and \tmpreg1, NWINDOWS - 1, \tmpreg1
721 wrpr \tmpreg1, %cwp
722
723 ! fill from kernel stack
724 ldx [%sp + STACK_BIAS + L0_OFFSET], %l0
725 ldx [%sp + STACK_BIAS + L1_OFFSET], %l1
726 ldx [%sp + STACK_BIAS + L2_OFFSET], %l2
727 ldx [%sp + STACK_BIAS + L3_OFFSET], %l3
728 ldx [%sp + STACK_BIAS + L4_OFFSET], %l4
729 ldx [%sp + STACK_BIAS + L5_OFFSET], %l5
730 ldx [%sp + STACK_BIAS + L6_OFFSET], %l6
731 ldx [%sp + STACK_BIAS + L7_OFFSET], %l7
732 ldx [%sp + STACK_BIAS + I0_OFFSET], %i0
733 ldx [%sp + STACK_BIAS + I1_OFFSET], %i1
734 ldx [%sp + STACK_BIAS + I2_OFFSET], %i2
735 ldx [%sp + STACK_BIAS + I3_OFFSET], %i3
736 ldx [%sp + STACK_BIAS + I4_OFFSET], %i4
737 ldx [%sp + STACK_BIAS + I5_OFFSET], %i5
738 ldx [%sp + STACK_BIAS + I6_OFFSET], %i6
739 ldx [%sp + STACK_BIAS + I7_OFFSET], %i7
740
741 ! CWP := CWP + 1
742 wrpr \tmpreg2, %cwp
743
744 restored
745.endm
746
747#define NOT(x) ((x) == 0)
748
749/*
750 * Perform all the actions of the preemptible trap handler which are common
751 * for trapping from kernel and trapping from userspace, including call of the
752 * higher level service routine.
753 *
754 * Important note:
755 * This macro must be inserted between the "2:" and "4:" labels. The
756 * inserting code must be aware of the usage of all the registers
757 * contained in this macro.
758 */
759.macro MIDDLE_PART is_syscall
760 /* copy higher level routine's address and its argument */
761 mov %g1, %l0
762.if NOT(\is_syscall)
763 mov %g2, %o0
764.else
765 ! store the syscall number on the stack as 7th argument
766 stx %g2, [%sp + STACK_BIAS + ISTATE_OFFSET_ARG6]
767.endif
768
769 /*
770 * Save TSTATE, TPC and TNPC aside.
771 */
772 rdpr %tstate, %g1
773 rdpr %tpc, %g2
774 rdpr %tnpc, %g3
775
776 stx %g1, [%sp + STACK_BIAS + ISTATE_OFFSET_TSTATE]
777 stx %g2, [%sp + STACK_BIAS + ISTATE_OFFSET_TPC]
778 stx %g3, [%sp + STACK_BIAS + ISTATE_OFFSET_TNPC]
779
780 /*
781 * Save the Y register.
782 */
783 rd %y, %g4
784 stx %g4, [%sp + STACK_BIAS + ISTATE_OFFSET_Y]
785
786 /*
787 * Save the faulting page and context.
788 */
789 stx %g5, [%sp + STACK_BIAS + ISTATE_OFFSET_TLB_TAG_ACCESS]
790
791 /* switch to TL = 0, explicitly enable FPU */
792 wrpr %g0, 0, %tl
793 wrpr %g0, 0, %gl
794 wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
795
796 /* g1 -> l1, ..., g7 -> l7 */
797 SAVE_GLOBALS
798
799.if NOT(\is_syscall)
800 /* call higher-level service routine, pass istate as its 2nd parameter */
801 call %l0
802 add %sp, STACK_BIAS, %o1
803.else
804 /* Call the higher-level syscall handler. */
805 !wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT | PSTATE_IE_BIT, %pstate
806 call syscall_handler
807 nop
808 /* copy the value returned by the syscall */
809 mov %o0, %i0
810.endif
811
812 /* l1 -> g1, ..., l7 -> g7 */
813 RESTORE_GLOBALS
814
815 /* we must prserve the PEF bit */
816 rdpr %pstate, %l1
817
818 /* TL := 1, GL := 1 */
819 wrpr %g0, PSTATE_PRIV_BIT, %pstate
820 wrpr %g0, 1, %tl
821 wrpr %g0, 1, %gl
822
823 /* Read TSTATE, TPC and TNPC from saved copy. */
824 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_TSTATE], %g1
825 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_TPC], %g2
826 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_TNPC], %g3
827
828 /* Copy PSTATE.PEF to the in-register copy of TSTATE. */
829 and %l1, PSTATE_PEF_BIT, %l1
830 sllx %l1, TSTATE_PSTATE_SHIFT, %l1
831 sethi %hi(TSTATE_PEF_BIT), %g4 ! reset the PEF bit to 0 ...
832 andn %g1, %g4, %g1
833 or %g1, %l1, %g1 ! ... "or" it with saved PEF
834
835 /* Restore TSTATE, TPC and TNPC from saved copies. */
836 wrpr %g1, 0, %tstate
837 wrpr %g2, 0, %tpc
838 wrpr %g3, 0, %tnpc
839
840 /* Restore Y. */
841 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_Y], %g4
842 wr %g4, %y
843
844 /* If TSTATE.CWP + 1 == CWP, then we do not have to fix CWP. */
845 and %g1, TSTATE_CWP_MASK, %l0
846 inc %l0
847 and %l0, NWINDOWS - 1, %l0 ! %l0 mod NWINDOWS
848 rdpr %cwp, %l1
849 cmp %l0, %l1
850 bz %xcc, 4f ! CWP is ok
851 nop
852
8533:
854 /*
855 * Fix CWP.
856 * In order to recapitulate, the input registers in the current
857 * window are the output registers of the window to which we want
858 * to restore. Because the fill trap fills only input and local
859 * registers of a window, we need to preserve those output
860 * registers manually.
861 */
862 mov %sp, %g2
863 stx %i0, [%sp + STACK_BIAS + ISTATE_OFFSET_O0]
864 stx %i1, [%sp + STACK_BIAS + ISTATE_OFFSET_O1]
865 stx %i2, [%sp + STACK_BIAS + ISTATE_OFFSET_O2]
866 stx %i3, [%sp + STACK_BIAS + ISTATE_OFFSET_O3]
867 stx %i4, [%sp + STACK_BIAS + ISTATE_OFFSET_O4]
868 stx %i5, [%sp + STACK_BIAS + ISTATE_OFFSET_O5]
869 stx %i6, [%sp + STACK_BIAS + ISTATE_OFFSET_O6]
870 stx %i7, [%sp + STACK_BIAS + ISTATE_OFFSET_O7]
871 wrpr %l0, 0, %cwp
872 mov %g2, %sp
873 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O0], %i0
874 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O1], %i1
875 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O2], %i2
876 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O3], %i3
877 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O4], %i4
878 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O5], %i5
879 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O6], %i6
880 ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O7], %i7
881.endm
882
883/*
884 * Preemptible trap handler for handling traps from kernel.
885 */
886.macro PREEMPTIBLE_HANDLER_KERNEL
887 /* prevent unnecessary CLEANWIN exceptions */
888 wrpr %g0, NWINDOWS - 1, %cleanwin
889
890 /*
891 * Prevent SAVE instruction from causing a spill exception. If the
892 * CANSAVE register is zero, explicitly spill register window
893 * at CWP + 2.
894 */
895
896 rdpr %cansave, %g3
897 brnz %g3, 2f
898 nop
899 INLINE_SPILL %g3, %g4
900
9012:
902 /* ask for new register window */
903 save %sp, -ISTATE_SIZE, %sp
904
905 MIDDLE_PART 0
906
9074:
908 /*
909 * Prevent RESTORE instruction from causing a fill exception. If the
910 * CANRESTORE register is zero, explicitly fill register window
911 * at CWP - 1.
912 */
913 rdpr %canrestore, %g1
914 brnz %g1, 5f
915 nop
916 INLINE_FILL %g3, %g4
917
9185:
919 restore
920 retry
921.endm
922
923/*
924 * Spills the window at CWP + 2 to the userspace window buffer. This macro
925 * is to be used before doing SAVE when the spill trap is undesirable.
926 *
927 * Parameters:
928 * tmpreg1 global register to be used for scratching purposes
929 * tmpreg2 global register to be used for scratching purposes
930 * tmpreg3 global register to be used for scratching purposes
931 */
932.macro INLINE_SPILL_TO_WBUF tmpreg1, tmpreg2, tmpreg3
933 ! CWP := CWP + 2
934 rdpr %cwp, \tmpreg2
935 add \tmpreg2, 2, \tmpreg1
936 and \tmpreg1, NWINDOWS - 1, \tmpreg1 ! modulo NWINDOWS
937 wrpr \tmpreg1, %cwp
938
939 ! spill to userspace window buffer
940 SAVE_TO_USPACE_WBUF \tmpreg3, \tmpreg1
941
942 ! CWP := CWP - 2
943 wrpr \tmpreg2, %cwp
944
945 saved
946.endm
947
948/*
949 * Preemptible handler for handling traps from userspace.
950 */
951.macro PREEMPTIBLE_HANDLER_USPACE is_syscall
952 /*
953 * One of the ways this handler can be invoked is after a nested MMU trap from
954 * either spill_1_normal or fill_1_normal traps. Both of these traps manipulate
955 * the CWP register. We deal with the situation by simulating the MMU trap
956 * on TL=1 and restart the respective SAVE or RESTORE instruction once the MMU
957 * trap is resolved. However, because we are in the wrong window from the
958 * perspective of the MMU trap, we need to synchronize CWP with CWP from TL=0.
959 */
960.if NOT(\is_syscall)
961 rdpr %tstate, %g3
962 and %g3, TSTATE_CWP_MASK, %g4
963 wrpr %g4, 0, %cwp ! resynchronize CWP
964.endif
965
966 /* prevent unnecessary CLEANWIN exceptions */
967 wrpr %g0, NWINDOWS - 1, %cleanwin
968
969 /*
970 * Prevent SAVE instruction from causing a spill exception. If the
971 * CANSAVE register is zero, explicitly spill register window
972 * at CWP + 2.
973 */
974 rdpr %cansave, %g3
975 brnz %g3, 2f
976 nop
977 INLINE_SPILL_TO_WBUF %g3, %g4, %g7
978
9792:
980 set SCRATCHPAD_KSTACK, %g4
981 ldxa [%g4] ASI_SCRATCHPAD, %g6
982 save %g6, -ISTATE_SIZE, %sp
983
984.if \is_syscall
985 /* Copy arguments for the syscall to the new window. */
986 mov %i0, %o0
987 mov %i1, %o1
988 mov %i2, %o2
989 mov %i3, %o3
990 mov %i4, %o4
991 mov %i5, %o5
992.endif
993
994 mov VA_PRIMARY_CONTEXT_REG, %l0
995 stxa %g0, [%l0] ASI_PRIMARY_CONTEXT_REG
996 rd %pc, %l0
997 flush %l0
998
999 /* Mark the CANRESTORE windows as OTHER windows. */
1000 rdpr %canrestore, %l0
1001 wrpr %l0, %otherwin
1002 wrpr %g0, %canrestore
1003
1004 /*
1005 * Other window spills will go to the userspace window buffer
1006 * and normal spills will go to the kernel stack.
1007 */
1008 wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
1009
1010 MIDDLE_PART \is_syscall
1011
10124:
1013 /*
1014 * Spills and fills will be processed by the {spill,fill}_1_normal
1015 * handlers.
1016 */
1017 wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(1), %wstate
1018
1019 /*
1020 * Set primary context according to secondary context.
1021 */
1022 wr %g0, ASI_SECONDARY_CONTEXT_REG, %asi
1023 ldxa [VA_SECONDARY_CONTEXT_REG] %asi, %g1
1024 wr %g0, ASI_PRIMARY_CONTEXT_REG, %asi
1025 stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi
1026 rd %pc, %g1
1027 flush %g1
1028
1029 /* Restoring userspace windows: */
1030
1031 /* Save address of the userspace window buffer to the %g7 register. */
1032 set SCRATCHPAD_WBUF, %g5
1033 ldxa [%g5] ASI_SCRATCHPAD, %g7
1034
1035 rdpr %cwp, %g1
1036 rdpr %otherwin, %g2
1037
1038 /*
1039 * Skip all OTHERWIN windows and descend to the first window
1040 * in the userspace window buffer.
1041 */
1042 sub %g1, %g2, %g3
1043 dec %g3
1044 and %g3, NWINDOWS - 1, %g3
1045 wrpr %g3, 0, %cwp
1046
1047 /*
1048 * CWP is now in the window last saved in the userspace window buffer.
1049 * Fill all windows stored in the buffer.
1050 */
1051 clr %g4
10525: andcc %g7, UWB_ALIGNMENT - 1, %g0 ! alignment check
1053 bz %xcc, 6f ! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill
1054 nop
1055
1056 add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7
1057 ldx [%g7 + L0_OFFSET], %l0
1058 ldx [%g7 + L1_OFFSET], %l1
1059 ldx [%g7 + L2_OFFSET], %l2
1060 ldx [%g7 + L3_OFFSET], %l3
1061 ldx [%g7 + L4_OFFSET], %l4
1062 ldx [%g7 + L5_OFFSET], %l5
1063 ldx [%g7 + L6_OFFSET], %l6
1064 ldx [%g7 + L7_OFFSET], %l7
1065 ldx [%g7 + I0_OFFSET], %i0
1066 ldx [%g7 + I1_OFFSET], %i1
1067 ldx [%g7 + I2_OFFSET], %i2
1068 ldx [%g7 + I3_OFFSET], %i3
1069 ldx [%g7 + I4_OFFSET], %i4
1070 ldx [%g7 + I5_OFFSET], %i5
1071 ldx [%g7 + I6_OFFSET], %i6
1072 ldx [%g7 + I7_OFFSET], %i7
1073
1074 dec %g3
1075 and %g3, NWINDOWS - 1, %g3
1076 wrpr %g3, 0, %cwp ! switch to the preceeding window
1077
1078 ba %xcc, 5b
1079 inc %g4
1080
10816:
1082 /* Save changes of the address of the userspace window buffer. */
1083 stxa %g7, [%g5] ASI_SCRATCHPAD
1084
1085 /*
1086 * Switch back to the proper current window and adjust
1087 * OTHERWIN, CANRESTORE, CANSAVE and CLEANWIN.
1088 */
1089 wrpr %g1, 0, %cwp
1090 add %g4, %g2, %g2
1091 cmp %g2, NWINDOWS - 2
1092 bg %xcc, 8f ! fix the CANRESTORE=NWINDOWS-1 anomaly
1093 mov NWINDOWS - 2, %g1 ! use dealy slot for both cases
1094 sub %g1, %g2, %g1
1095
1096 wrpr %g0, 0, %otherwin
1097 wrpr %g1, 0, %cansave ! NWINDOWS - 2 - CANRESTORE
1098 wrpr %g2, 0, %canrestore ! OTHERWIN + windows in the buffer
1099 wrpr %g2, 0, %cleanwin ! avoid information leak
1100
11017:
1102 restore
1103
1104.if \is_syscall
1105 done
1106.else
1107 retry
1108.endif
1109
11108:
1111 /*
1112 * We got here in order to avoid inconsistency of the window state registers.
1113 * If the:
1114 *
1115 * save %g6, -ISTATE_SIZE, %sp
1116 *
1117 * instruction trapped and spilled a register window into the userspace
1118 * window buffer, we have just restored NWINDOWS - 1 register windows.
1119 * However, CANRESTORE can be only NWINDOW - 2 at most.
1120 *
1121 * The solution is to manually switch to (CWP - 1) mod NWINDOWS
1122 * and set the window state registers so that:
1123 *
1124 * CANRESTORE = NWINDOWS - 2
1125 * CLEANWIN = NWINDOWS - 2
1126 * CANSAVE = 0
1127 * OTHERWIN = 0
1128 *
1129 * The RESTORE instruction is therfore to be skipped.
1130 */
1131 wrpr %g0, 0, %otherwin
1132 wrpr %g0, 0, %cansave
1133 wrpr %g1, 0, %canrestore
1134 wrpr %g1, 0, %cleanwin
1135
1136 rdpr %cwp, %g1
1137 dec %g1
1138 and %g1, NWINDOWS - 1, %g1
1139 wrpr %g1, 0, %cwp ! CWP--
1140
1141.if \is_syscall
1142 done
1143.else
1144 retry
1145.endif
1146
1147.endm
1148
1149/* Preemptible trap handler for TL=1.
1150 *
1151 * This trap handler makes arrangements to make calling of scheduler() from
1152 * within a trap context possible. It is called from several other trap
1153 * handlers.
1154 */
1155.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
1156 rdpr %tstate, %g3
1157 and %g3, TSTATE_PRIV_BIT, %g3
1158 brz %g3, 100f ! trapping from userspace
1159 nop
1160
1161 PREEMPTIBLE_HANDLER_KERNEL
1162 ba,a %xcc, 101f
1163
1164 100:
1165 PREEMPTIBLE_HANDLER_USPACE \is_syscall
1166
1167 101:
1168.endm
1169
1170.global preemptible_handler
1171preemptible_handler:
1172 PREEMPTIBLE_HANDLER_TEMPLATE 0
1173
1174.global trap_instruction_handler
1175trap_instruction_handler:
1176 PREEMPTIBLE_HANDLER_TEMPLATE 1
Note: See TracBrowser for help on using the repository browser.