Subversion Repositories HelenOS

Rev

Rev 4433 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3743 rimsky 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>
3993 rimsky 50
#include <arch/sun4v/arch.h>
51
#include <arch/sun4v/cpu.h>
3743 rimsky 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
61
trap_table:
62
 
63
/* TT = 0x08, TL = 0, instruction_access_exception */
4383 rimsky 64
/* TT = 0x08, TL = 0, IAE_privilege_violation on UltraSPARC T2 */
3743 rimsky 65
.org trap_table + TT_INSTRUCTION_ACCESS_EXCEPTION*ENTRY_SIZE
66
.global instruction_access_exception_tl0
67
instruction_access_exception_tl0:
4383 rimsky 68
	PREEMPTIBLE_HANDLER instruction_access_exception
3743 rimsky 69
 
4433 rimsky 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
 
3743 rimsky 76
/* TT = 0x0a, TL = 0, instruction_access_error */
77
.org trap_table + TT_INSTRUCTION_ACCESS_ERROR*ENTRY_SIZE
78
.global instruction_access_error_tl0
79
instruction_access_error_tl0:
80
	PREEMPTIBLE_HANDLER instruction_access_error
81
 
4383 rimsky 82
/* TT = 0x0b, TL = 0, IAE_unauth_access */
83
.org trap_table + TT_IAE_UNAUTH_ACCESS*ENTRY_SIZE
84
.global iae_unauth_access_tl0
85
iae_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
91
iae_nfo_page_tl0:
92
	PREEMPTIBLE_HANDLER instruction_access_exception
93
 
3743 rimsky 94
/* TT = 0x10, TL = 0, illegal_instruction */
95
.org trap_table + TT_ILLEGAL_INSTRUCTION*ENTRY_SIZE
96
.global illegal_instruction_tl0
97
illegal_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
103
privileged_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
109
unimplemented_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
115
unimplemented_STD_tl0:
116
	PREEMPTIBLE_HANDLER unimplemented_STD
117
 
4383 rimsky 118
/* TT = 0x14, TL = 0, DAE_invalid_asi */
119
.org trap_table + TT_DAE_INVALID_ASI*ENTRY_SIZE
120
.global dae_invalid_asi_tl0
121
dae_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
127
dae_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
133
dae_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
139
dae_nfo_page_tl0:
140
	PREEMPTIBLE_HANDLER data_access_exception
141
 
3743 rimsky 142
/* TT = 0x20, TL = 0, fb_disabled handler */
143
.org trap_table + TT_FP_DISABLED*ENTRY_SIZE
144
.global fb_disabled_tl0
145
fp_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
151
fp_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
157
fp_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
163
tag_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
169
clean_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
175
division_by_zero_tl0:
176
	PREEMPTIBLE_HANDLER division_by_zero
177
 
178
/* TT = 0x30, TL = 0, data_access_exception */
4383 rimsky 179
/* TT = 0x30, TL = 0, DAE_side_effect_page for UltraPSARC T2 */
3743 rimsky 180
.org trap_table + TT_DATA_ACCESS_EXCEPTION*ENTRY_SIZE
181
.global data_access_exception_tl0
182
data_access_exception_tl0:
4383 rimsky 183
	PREEMPTIBLE_HANDLER data_access_exception
3743 rimsky 184
 
4433 rimsky 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
188
data_access_mmu_miss_tl0:
189
	ba fast_data_access_mmu_miss_handler_tl0
190
	nop
191
 
3743 rimsky 192
/* TT = 0x32, TL = 0, data_access_error */
193
.org trap_table + TT_DATA_ACCESS_ERROR*ENTRY_SIZE
194
.global data_access_error_tl0
195
data_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
201
mem_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
207
LDDF_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
213
STDF_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
219
privileged_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
225
LDQF_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
231
STQF_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
237
interrupt_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
243
interrupt_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
249
interrupt_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
255
interrupt_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
261
interrupt_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
267
interrupt_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
273
interrupt_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
279
interrupt_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
285
interrupt_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
291
interrupt_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
297
interrupt_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
303
interrupt_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
309
interrupt_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
315
interrupt_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
321
interrupt_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
327
fast_instruction_access_mmu_miss_handler_tl0:
3863 rimsky 328
	FAST_INSTRUCTION_ACCESS_MMU_MISS_HANDLER
3743 rimsky 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
333
fast_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
339
fast_data_access_protection_handler_tl0:
3993 rimsky 340
	FAST_DATA_ACCESS_PROTECTION_HANDLER 0
3743 rimsky 341
 
4638 rimsky 342
/* TT = 0x7c, TL = 0, cpu_mondo */
343
.org trap_table + TT_CPU_MONDO*ENTRY_SIZE
344
.global cpu_mondo_handler_tl0
345
cpu_mondo_handler_tl0:
346
PREEMPTIBLE_HANDLER cpu_mondo
347
 
3743 rimsky 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
351
spill_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
357
spill_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
363
spill_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
369
spill_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
375
fill_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
381
fill_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
395
trap_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 */
4383 rimsky 405
/* TT = 0x08, TL > 0, IAE_privilege_violation on UltraSPARC T2 */
3743 rimsky 406
.org trap_table + (TT_INSTRUCTION_ACCESS_EXCEPTION+512)*ENTRY_SIZE
407
.global instruction_access_exception_tl1
408
instruction_access_exception_tl1:
4383 rimsky 409
	wrpr %g0, 1, %tl
410
	PREEMPTIBLE_HANDLER instruction_access_exception
3743 rimsky 411
 
4433 rimsky 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
 
3743 rimsky 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
422
instruction_access_error_tl1:
423
	wrpr %g0, 1, %tl
424
	PREEMPTIBLE_HANDLER instruction_access_error
425
 
4383 rimsky 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
429
iae_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
436
iae_nfo_page_tl1:
437
	wrpr %g0, 1, %tl
438
	PREEMPTIBLE_HANDLER instruction_access_exception
439
 
3743 rimsky 440
/* TT = 0x10, TL > 0, illegal_instruction */
441
.org trap_table + (TT_ILLEGAL_INSTRUCTION+512)*ENTRY_SIZE
442
.global illegal_instruction_tl1
443
illegal_instruction_tl1:
444
	wrpr %g0, 1, %tl
445
	PREEMPTIBLE_HANDLER illegal_instruction
446
 
4383 rimsky 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
450
dae_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
457
dae_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
464
dae_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
471
dae_nfo_page_tl1:
472
	wrpr %g0, 1, %tl
473
	PREEMPTIBLE_HANDLER data_access_exception
474
 
3743 rimsky 475
/* TT = 0x24, TL > 0, clean_window handler */
476
.org trap_table + (TT_CLEAN_WINDOW+512)*ENTRY_SIZE
477
.global clean_window_tl1
478
clean_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
484
division_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
491
data_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
 
4433 rimsky 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
499
data_access_mmu_miss_tl1:
500
	ba fast_data_access_mmu_miss_handler_tl1
501
	nop
502
 
503
 
3743 rimsky 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
507
data_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
514
mem_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
521
fast_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
527
fast_data_access_protection_handler_tl1:
4068 rimsky 528
	FAST_DATA_ACCESS_PROTECTION_HANDLER 1
3743 rimsky 529
 
4638 rimsky 530
/* TT = 0x7c, TL > 0, cpu_mondo */
531
.org trap_table + (TT_CPU_MONDO+512)*ENTRY_SIZE
532
.global cpu_mondo_handler_tl1
533
cpu_mondo_handler_tl1:
534
	wrpr %g0, %tl
535
	PREEMPTIBLE_HANDLER cpu_mondo
536
 
3743 rimsky 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
540
spill_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
546
spill_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
552
spill_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
558
fill_0_normal_tl1:
559
	FILL_NORMAL_HANDLER_KERNEL
560
 
561
.align TABLE_SIZE
562
 
563
 
3798 rimsky 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.
3801 rimsky 567
 * 
568
 * Parameters:
569
 * 	tmpreg1		global register to be used for scratching purposes
570
 * 	tmpreg2		global register to be used for scratching purposes
3798 rimsky 571
 */
3801 rimsky 572
.macro INLINE_SPILL tmpreg1, tmpreg2
3798 rimsky 573
	! CWP := CWP + 2
3801 rimsky 574
	rdpr %cwp, \tmpreg2
575
	add \tmpreg2, 2, \tmpreg1
576
	and \tmpreg1, NWINDOWS - 1, \tmpreg1		! modulo NWINDOWS
577
	wrpr \tmpreg1, %cwp
3798 rimsky 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]
3743 rimsky 596
 
3798 rimsky 597
	! CWP := CWP - 2
3801 rimsky 598
	wrpr \tmpreg2, %cwp
3798 rimsky 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.
3801 rimsky 606
 * 
607
 * Parameters:
608
 * 	tmpreg1		global register to be used for scratching purposes
609
 * 	tmpreg2		global register to be used for scratching purposes
3743 rimsky 610
 */
3801 rimsky 611
.macro INLINE_FILL tmpreg1, tmpreg2
3798 rimsky 612
	! CWP := CWP - 1
3801 rimsky 613
	rdpr %cwp, \tmpreg2
614
	add \tmpreg2, NWINDOWS - 1, \tmpreg1
615
	and \tmpreg1, NWINDOWS - 1, \tmpreg1
616
	wrpr \tmpreg1, %cwp
3798 rimsky 617
 
3801 rimsky 618
	! fill from kernel stack
3798 rimsky 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
3801 rimsky 637
	wrpr \tmpreg2, %cwp
3798 rimsky 638
 
639
	restored
640
.endm
641
 
3993 rimsky 642
#define NOT(x)	((x) == 0)
643
 
3798 rimsky 644
/*
3993 rimsky 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.
3798 rimsky 653
 */
3993 rimsky 654
.macro MIDDLE_PART is_syscall
3798 rimsky 655
	/* copy higher level routine's address and its argument */
3743 rimsky 656
	mov %g1, %l0
3993 rimsky 657
.if NOT(\is_syscall)
3743 rimsky 658
	mov %g2, %o0
3993 rimsky 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
3743 rimsky 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
	 */
3798 rimsky 682
	rd %y, %g4
3743 rimsky 683
	stx %g4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y]
3798 rimsky 684
 
685
	/* switch to TL = 0, explicitly enable FPU */
3743 rimsky 686
	wrpr %g0, 0, %tl
3801 rimsky 687
	wrpr %g0, 0, %gl
3743 rimsky 688
	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
3798 rimsky 689
 
690
	/* g1 -> l1, ..., g7 -> l7 */
3743 rimsky 691
	SAVE_GLOBALS
3798 rimsky 692
 
3993 rimsky 693
.if NOT(\is_syscall)
3798 rimsky 694
	/* call higher-level service routine, pass istate as its 2nd parameter */
3743 rimsky 695
	call %l0
696
	add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
3993 rimsky 697
.else
698
	/* Call the higher-level syscall handler. */
4064 rimsky 699
	!wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT | PSTATE_IE_BIT, %pstate
3993 rimsky 700
	call syscall_handler
701
	nop
702
	/* copy the value returned by the syscall */
703
	mov %o0, %i0
704
.endif
3743 rimsky 705
 
3798 rimsky 706
	/* l1 -> g1, ..., l7 -> g7 */
3743 rimsky 707
	RESTORE_GLOBALS
3798 rimsky 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
3743 rimsky 714
	wrpr %g0, 1, %tl
3798 rimsky 715
	wrpr %g0, 1, %gl
716
 
717
	/* Read TSTATE, TPC and TNPC from saved copy. */
3743 rimsky 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
 
3798 rimsky 722
	/* Copy PSTATE.PEF to the in-register copy of TSTATE. */
3743 rimsky 723
	and %l1, PSTATE_PEF_BIT, %l1
724
	sllx %l1, TSTATE_PSTATE_SHIFT, %l1
3798 rimsky 725
	sethi %hi(TSTATE_PEF_BIT), %g4		! reset the PEF bit to 0 ...
3743 rimsky 726
	andn %g1, %g4, %g1
3798 rimsky 727
	or %g1, %l1, %g1			! ... "or" it with saved PEF
3743 rimsky 728
 
3798 rimsky 729
	/* Restore TSTATE, TPC and TNPC from saved copies. */
3743 rimsky 730
	wrpr %g1, 0, %tstate
731
	wrpr %g2, 0, %tpc
732
	wrpr %g3, 0, %tnpc
733
 
3798 rimsky 734
	/* Restore Y. */
3743 rimsky 735
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y], %g4
736
	wr %g4, %y
3798 rimsky 737
 
738
	/* If TSTATE.CWP + 1 == CWP, then we do not have to fix CWP. */
3743 rimsky 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
3798 rimsky 744
	bz 4f				! CWP is ok
3743 rimsky 745
	nop
746
 
3798 rimsky 747
3:
3743 rimsky 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
3993 rimsky 775
.endm
3743 rimsky 776
 
3993 rimsky 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
789
0:	ba 0b					! this is for debugging, if we ever get here
790
	nop					! it will be easy to find
791
 
792
1:
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
 
807
2:
808
	/* ask for new register window */
809
	save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
810
 
811
	MIDDLE_PART 0
812
 
3798 rimsky 813
4:
3743 rimsky 814
	/*
3801 rimsky 815
	 * Prevent RESTORE instruction from causing a fill exception. If the
816
	 * CANRESTORE register is zero, explicitly fill register window
817
	 * at CWP - 1.
3743 rimsky 818
	 */
3798 rimsky 819
	rdpr %canrestore, %g1
820
	brnz %g1, 5f
3743 rimsky 821
	nop
3801 rimsky 822
	INLINE_FILL %g3, %g4
3743 rimsky 823
 
3798 rimsky 824
5:
3743 rimsky 825
	restore
826
	retry
3798 rimsky 827
.endm
3743 rimsky 828
 
3993 rimsky 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
3743 rimsky 847
 
3993 rimsky 848
	! CWP := CWP - 2
849
	wrpr \tmpreg2, %cwp
3743 rimsky 850
 
3993 rimsky 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
 
885
2:
4369 rimsky 886
	set SCRATCHPAD_KSTACK, %g4
887
	ldxa [%g4] ASI_SCRATCHPAD, %g6
3993 rimsky 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
 
918
4:
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. */
4369 rimsky 938
	set SCRATCHPAD_WBUF, %g5
939
	ldxa [%g5] ASI_SCRATCHPAD, %g7
3993 rimsky 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
958
5:	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
 
987
6:
988
	/* Save changes of the address of the userspace window buffer. */
4369 rimsky 989
	stxa %g7, [%g5] ASI_SCRATCHPAD
3993 rimsky 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
 
1007
7:
1008
	restore
1009
 
1010
.if \is_syscall
1011
	done
1012
.else
1013
	retry
1014
.endif
1015
 
1016
8:
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
 
3798 rimsky 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
3993 rimsky 1062
	rdpr %tstate, %g3
1063
	and %g3, TSTATE_PRIV_BIT, %g3
1064
	brz %g3, 100f			! trapping from userspace
1065
	nop
1066
 
3798 rimsky 1067
	PREEMPTIBLE_HANDLER_KERNEL
3993 rimsky 1068
	ba 101f
1069
	nop
1070
 
1071
	100:
1072
	PREEMPTIBLE_HANDLER_USPACE \is_syscall
1073
 
1074
	101:
3743 rimsky 1075
.endm
1076
 
1077
.global preemptible_handler
1078
preemptible_handler:
1079
	PREEMPTIBLE_HANDLER_TEMPLATE 0
1080
 
1081
.global trap_instruction_handler
1082
trap_instruction_handler:
1083
	PREEMPTIBLE_HANDLER_TEMPLATE 1