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

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

Fix one more use of an obsolete branch instruction.

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