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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since b97b348 was f8f7dba, checked in by Pavel Rimsky <pavel@…>, 15 years ago

Fixed a stupid bug which prevented booting sun4v on SMP. Now HelenOS seems to work on a Simics machine with 2 CPUs.

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