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

Last change on this file was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

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