Subversion Repositories HelenOS

Rev

Rev 4383 | 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 = 0x60, TL = 0, interrupt_vector_trap handler */
325
.org trap_table + TT_INTERRUPT_VECTOR_TRAP*ENTRY_SIZE
326
.global interrupt_vector_trap_handler_tl0
327
interrupt_vector_trap_handler_tl0:
328
	INTERRUPT_VECTOR_TRAP_HANDLER
329
 
330
/* TT = 0x64, TL = 0, fast_instruction_access_MMU_miss */
331
.org trap_table + TT_FAST_INSTRUCTION_ACCESS_MMU_MISS*ENTRY_SIZE
332
.global fast_instruction_access_mmu_miss_handler_tl0
333
fast_instruction_access_mmu_miss_handler_tl0:
3863 rimsky 334
	FAST_INSTRUCTION_ACCESS_MMU_MISS_HANDLER
3743 rimsky 335
 
336
/* TT = 0x68, TL = 0, fast_data_access_MMU_miss */
337
.org trap_table + TT_FAST_DATA_ACCESS_MMU_MISS*ENTRY_SIZE
338
.global fast_data_access_mmu_miss_handler_tl0
339
fast_data_access_mmu_miss_handler_tl0:
340
	FAST_DATA_ACCESS_MMU_MISS_HANDLER 0
341
 
342
/* TT = 0x6c, TL = 0, fast_data_access_protection */
343
.org trap_table + TT_FAST_DATA_ACCESS_PROTECTION*ENTRY_SIZE
344
.global fast_data_access_protection_handler_tl0
345
fast_data_access_protection_handler_tl0:
3993 rimsky 346
	FAST_DATA_ACCESS_PROTECTION_HANDLER 0
3743 rimsky 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
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
 
530
/* TT = 0x80, TL > 0, spill_0_normal handler */
531
.org trap_table + (TT_SPILL_0_NORMAL+512)*ENTRY_SIZE
532
.global spill_0_normal_tl1
533
spill_0_normal_tl1:
534
	SPILL_NORMAL_HANDLER_KERNEL
535
 
536
/* TT = 0x88, TL > 0, spill_2_normal handler */
537
.org trap_table + (TT_SPILL_2_NORMAL+512)*ENTRY_SIZE
538
.global spill_2_normal_tl1
539
spill_2_normal_tl1:
540
	SPILL_TO_USPACE_WINDOW_BUFFER
541
 
542
/* TT = 0xa0, TL > 0, spill_0_other handler */
543
.org trap_table + (TT_SPILL_0_OTHER+512)*ENTRY_SIZE
544
.global spill_0_other_tl1
545
spill_0_other_tl1:
546
	SPILL_TO_USPACE_WINDOW_BUFFER
547
 
548
/* TT = 0xc0, TL > 0, fill_0_normal handler */
549
.org trap_table + (TT_FILL_0_NORMAL+512)*ENTRY_SIZE
550
.global fill_0_normal_tl1
551
fill_0_normal_tl1:
552
	FILL_NORMAL_HANDLER_KERNEL
553
 
554
.align TABLE_SIZE
555
 
556
 
3798 rimsky 557
/*
558
 * Spills the window at CWP + 2 to the kernel stack. This macro is to be
559
 * used before doing SAVE when the spill trap is undesirable.
3801 rimsky 560
 * 
561
 * Parameters:
562
 * 	tmpreg1		global register to be used for scratching purposes
563
 * 	tmpreg2		global register to be used for scratching purposes
3798 rimsky 564
 */
3801 rimsky 565
.macro INLINE_SPILL tmpreg1, tmpreg2
3798 rimsky 566
	! CWP := CWP + 2
3801 rimsky 567
	rdpr %cwp, \tmpreg2
568
	add \tmpreg2, 2, \tmpreg1
569
	and \tmpreg1, NWINDOWS - 1, \tmpreg1		! modulo NWINDOWS
570
	wrpr \tmpreg1, %cwp
3798 rimsky 571
 
572
	! spill to kernel stack
573
	stx %l0, [%sp + STACK_BIAS + L0_OFFSET]	
574
	stx %l1, [%sp + STACK_BIAS + L1_OFFSET]
575
	stx %l2, [%sp + STACK_BIAS + L2_OFFSET]
576
	stx %l3, [%sp + STACK_BIAS + L3_OFFSET]
577
	stx %l4, [%sp + STACK_BIAS + L4_OFFSET]
578
	stx %l5, [%sp + STACK_BIAS + L5_OFFSET]
579
	stx %l6, [%sp + STACK_BIAS + L6_OFFSET]
580
	stx %l7, [%sp + STACK_BIAS + L7_OFFSET]
581
	stx %i0, [%sp + STACK_BIAS + I0_OFFSET]
582
	stx %i1, [%sp + STACK_BIAS + I1_OFFSET]
583
	stx %i2, [%sp + STACK_BIAS + I2_OFFSET]
584
	stx %i3, [%sp + STACK_BIAS + I3_OFFSET]
585
	stx %i4, [%sp + STACK_BIAS + I4_OFFSET]
586
	stx %i5, [%sp + STACK_BIAS + I5_OFFSET]
587
	stx %i6, [%sp + STACK_BIAS + I6_OFFSET]
588
	stx %i7, [%sp + STACK_BIAS + I7_OFFSET]
3743 rimsky 589
 
3798 rimsky 590
	! CWP := CWP - 2
3801 rimsky 591
	wrpr \tmpreg2, %cwp
3798 rimsky 592
 
593
	saved
594
.endm
595
 
596
/*
597
 * Fill the window at CWP - 1 from the kernel stack. This macro is to be
598
 * used before doing RESTORE when the fill trap is undesirable.
3801 rimsky 599
 * 
600
 * Parameters:
601
 * 	tmpreg1		global register to be used for scratching purposes
602
 * 	tmpreg2		global register to be used for scratching purposes
3743 rimsky 603
 */
3801 rimsky 604
.macro INLINE_FILL tmpreg1, tmpreg2
3798 rimsky 605
	! CWP := CWP - 1
3801 rimsky 606
	rdpr %cwp, \tmpreg2
607
	add \tmpreg2, NWINDOWS - 1, \tmpreg1
608
	and \tmpreg1, NWINDOWS - 1, \tmpreg1
609
	wrpr \tmpreg1, %cwp
3798 rimsky 610
 
3801 rimsky 611
	! fill from kernel stack
3798 rimsky 612
	ldx [%sp + STACK_BIAS + L0_OFFSET], %l0
613
	ldx [%sp + STACK_BIAS + L1_OFFSET], %l1
614
	ldx [%sp + STACK_BIAS + L2_OFFSET], %l2
615
	ldx [%sp + STACK_BIAS + L3_OFFSET], %l3
616
	ldx [%sp + STACK_BIAS + L4_OFFSET], %l4
617
	ldx [%sp + STACK_BIAS + L5_OFFSET], %l5
618
	ldx [%sp + STACK_BIAS + L6_OFFSET], %l6
619
	ldx [%sp + STACK_BIAS + L7_OFFSET], %l7
620
	ldx [%sp + STACK_BIAS + I0_OFFSET], %i0
621
	ldx [%sp + STACK_BIAS + I1_OFFSET], %i1
622
	ldx [%sp + STACK_BIAS + I2_OFFSET], %i2
623
	ldx [%sp + STACK_BIAS + I3_OFFSET], %i3
624
	ldx [%sp + STACK_BIAS + I4_OFFSET], %i4
625
	ldx [%sp + STACK_BIAS + I5_OFFSET], %i5
626
	ldx [%sp + STACK_BIAS + I6_OFFSET], %i6
627
	ldx [%sp + STACK_BIAS + I7_OFFSET], %i7
628
 
629
	! CWP := CWP + 1
3801 rimsky 630
	wrpr \tmpreg2, %cwp
3798 rimsky 631
 
632
	restored
633
.endm
634
 
3993 rimsky 635
#define NOT(x)	((x) == 0)
636
 
3798 rimsky 637
/*
3993 rimsky 638
 * Perform all the actions of the preemptible trap handler which are common
639
 * for trapping from kernel and trapping from userspace, including call of the
640
 * higher level service routine.
641
 *
642
 * Important note:
643
 * 	This macro must be inserted between the "2:" and "4:" labels. The
644
 *	inserting code must be aware of the usage of all the registers
645
 *	contained in this macro.
3798 rimsky 646
 */
3993 rimsky 647
.macro MIDDLE_PART is_syscall
3798 rimsky 648
	/* copy higher level routine's address and its argument */
3743 rimsky 649
	mov %g1, %l0
3993 rimsky 650
.if NOT(\is_syscall)
3743 rimsky 651
	mov %g2, %o0
3993 rimsky 652
.else
653
	! store the syscall number on the stack as 7th argument
654
	stx %g2, [%sp + STACK_WINDOW_SAVE_AREA_SIZE + STACK_BIAS + STACK_ARG6] 
655
.endif
3743 rimsky 656
 
657
	/*
658
	 * Save TSTATE, TPC and TNPC aside.
659
	 */
660
	rdpr %tstate, %g1
661
	rdpr %tpc, %g2
662
	rdpr %tnpc, %g3
663
 
664
	stx %g1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE]
665
	stx %g2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC]
666
	stx %g3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC]
667
 
668
	/*
669
	 * Save the Y register.
670
	 * This register is deprecated according to SPARC V9 specification
671
	 * and is only present for backward compatibility with previous
672
	 * versions of the SPARC architecture.
673
	 * Surprisingly, gcc makes use of this register without a notice.
674
	 */
3798 rimsky 675
	rd %y, %g4
3743 rimsky 676
	stx %g4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y]
3798 rimsky 677
 
678
	/* switch to TL = 0, explicitly enable FPU */
3743 rimsky 679
	wrpr %g0, 0, %tl
3801 rimsky 680
	wrpr %g0, 0, %gl
3743 rimsky 681
	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
3798 rimsky 682
 
683
	/* g1 -> l1, ..., g7 -> l7 */
3743 rimsky 684
	SAVE_GLOBALS
3798 rimsky 685
 
3993 rimsky 686
.if NOT(\is_syscall)
3798 rimsky 687
	/* call higher-level service routine, pass istate as its 2nd parameter */
3743 rimsky 688
	call %l0
689
	add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
3993 rimsky 690
.else
691
	/* Call the higher-level syscall handler. */
4064 rimsky 692
	!wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT | PSTATE_IE_BIT, %pstate
3993 rimsky 693
	call syscall_handler
694
	nop
695
	/* copy the value returned by the syscall */
696
	mov %o0, %i0
697
.endif
3743 rimsky 698
 
3798 rimsky 699
	/* l1 -> g1, ..., l7 -> g7 */
3743 rimsky 700
	RESTORE_GLOBALS
3798 rimsky 701
 
702
	/* we must prserve the PEF bit */
703
	rdpr %pstate, %l1
704
 
705
	/* TL := 1, GL := 1 */
706
	wrpr %g0, PSTATE_PRIV_BIT, %pstate
3743 rimsky 707
	wrpr %g0, 1, %tl
3798 rimsky 708
	wrpr %g0, 1, %gl
709
 
710
	/* Read TSTATE, TPC and TNPC from saved copy. */
3743 rimsky 711
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE], %g1
712
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC], %g2
713
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC], %g3
714
 
3798 rimsky 715
	/* Copy PSTATE.PEF to the in-register copy of TSTATE. */
3743 rimsky 716
	and %l1, PSTATE_PEF_BIT, %l1
717
	sllx %l1, TSTATE_PSTATE_SHIFT, %l1
3798 rimsky 718
	sethi %hi(TSTATE_PEF_BIT), %g4		! reset the PEF bit to 0 ...
3743 rimsky 719
	andn %g1, %g4, %g1
3798 rimsky 720
	or %g1, %l1, %g1			! ... "or" it with saved PEF
3743 rimsky 721
 
3798 rimsky 722
	/* Restore TSTATE, TPC and TNPC from saved copies. */
3743 rimsky 723
	wrpr %g1, 0, %tstate
724
	wrpr %g2, 0, %tpc
725
	wrpr %g3, 0, %tnpc
726
 
3798 rimsky 727
	/* Restore Y. */
3743 rimsky 728
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y], %g4
729
	wr %g4, %y
3798 rimsky 730
 
731
	/* If TSTATE.CWP + 1 == CWP, then we do not have to fix CWP. */
3743 rimsky 732
	and %g1, TSTATE_CWP_MASK, %l0
733
	inc %l0
734
	and %l0, NWINDOWS - 1, %l0	! %l0 mod NWINDOWS
735
	rdpr %cwp, %l1
736
	cmp %l0, %l1
3798 rimsky 737
	bz 4f				! CWP is ok
3743 rimsky 738
	nop
739
 
3798 rimsky 740
3:
3743 rimsky 741
	/*
742
	 * Fix CWP.
743
	 * In order to recapitulate, the input registers in the current
744
	 * window are the output registers of the window to which we want
745
	 * to restore. Because the fill trap fills only input and local
746
	 * registers of a window, we need to preserve those output
747
	 * registers manually.
748
	 */
749
	mov %sp, %g2
750
	stx %i0, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0]
751
	stx %i1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1]
752
	stx %i2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2]
753
	stx %i3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3]
754
	stx %i4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4]
755
	stx %i5, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5]
756
	stx %i6, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6]
757
	stx %i7, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7]
758
	wrpr %l0, 0, %cwp
759
	mov %g2, %sp
760
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0], %i0
761
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1], %i1
762
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2], %i2
763
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3], %i3
764
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4], %i4
765
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5], %i5
766
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6], %i6
767
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7], %i7
3993 rimsky 768
.endm
3743 rimsky 769
 
3993 rimsky 770
/*
771
 * Preemptible trap handler for handling traps from kernel.
772
 */
773
.macro PREEMPTIBLE_HANDLER_KERNEL
774
 
775
	/*
776
	 * ASSERT(%tl == 1)
777
	 */
778
	rdpr %tl, %g3
779
	cmp %g3, 1
780
	be 1f
781
	nop
782
0:	ba 0b					! this is for debugging, if we ever get here
783
	nop					! it will be easy to find
784
 
785
1:
786
	/* prevent unnecessary CLEANWIN exceptions */
787
	wrpr %g0, NWINDOWS - 1, %cleanwin
788
 
789
	/*
790
	 * Prevent SAVE instruction from causing a spill exception. If the
791
	 * CANSAVE register is zero, explicitly spill register window
792
	 * at CWP + 2.
793
	 */
794
 
795
	rdpr %cansave, %g3
796
	brnz %g3, 2f
797
	nop
798
	INLINE_SPILL %g3, %g4
799
 
800
2:
801
	/* ask for new register window */
802
	save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
803
 
804
	MIDDLE_PART 0
805
 
3798 rimsky 806
4:
3743 rimsky 807
	/*
3801 rimsky 808
	 * Prevent RESTORE instruction from causing a fill exception. If the
809
	 * CANRESTORE register is zero, explicitly fill register window
810
	 * at CWP - 1.
3743 rimsky 811
	 */
3798 rimsky 812
	rdpr %canrestore, %g1
813
	brnz %g1, 5f
3743 rimsky 814
	nop
3801 rimsky 815
	INLINE_FILL %g3, %g4
3743 rimsky 816
 
3798 rimsky 817
5:
3743 rimsky 818
	restore
819
 
820
	retry
3798 rimsky 821
.endm
3743 rimsky 822
 
3993 rimsky 823
/*
824
 * Spills the window at CWP + 2 to the userspace window buffer. This macro
825
 * is to be used before doing SAVE when the spill trap is undesirable.
826
 * 
827
 * Parameters:
828
 * 	tmpreg1		global register to be used for scratching purposes
829
 * 	tmpreg2		global register to be used for scratching purposes
830
 * 	tmpreg3		global register to be used for scratching purposes
831
 */
832
.macro INLINE_SPILL_TO_WBUF tmpreg1, tmpreg2, tmpreg3
833
	! CWP := CWP + 2
834
	rdpr %cwp, \tmpreg2
835
	add \tmpreg2, 2, \tmpreg1
836
	and \tmpreg1, NWINDOWS - 1, \tmpreg1		! modulo NWINDOWS
837
	wrpr \tmpreg1, %cwp
838
 
839
	! spill to userspace window buffer
840
	SAVE_TO_USPACE_WBUF \tmpreg3, \tmpreg1
3743 rimsky 841
 
3993 rimsky 842
	! CWP := CWP - 2
843
	wrpr \tmpreg2, %cwp
3743 rimsky 844
 
3993 rimsky 845
	saved
846
.endm
847
 
848
/*
849
 * Preemptible handler for handling traps from userspace.
850
 */
851
.macro PREEMPTIBLE_HANDLER_USPACE is_syscall
852
	/*
853
	 * One of the ways this handler can be invoked is after a nested MMU trap from
854
	 * either spill_1_normal or fill_1_normal traps. Both of these traps manipulate
855
	 * the CWP register. We deal with the situation by simulating the MMU trap
856
	 * on TL=1 and restart the respective SAVE or RESTORE instruction once the MMU
857
	 * trap is resolved. However, because we are in the wrong window from the
858
	 * perspective of the MMU trap, we need to synchronize CWP with CWP from TL=0.
859
	 */ 
860
.if NOT(\is_syscall)
861
	rdpr %tstate, %g3
862
	and %g3, TSTATE_CWP_MASK, %g4
863
	wrpr %g4, 0, %cwp			! resynchronize CWP
864
.endif
865
 
866
	/* prevent unnecessary CLEANWIN exceptions */
867
	wrpr %g0, NWINDOWS - 1, %cleanwin
868
 
869
	/*
870
	 * Prevent SAVE instruction from causing a spill exception. If the
871
	 * CANSAVE register is zero, explicitly spill register window
872
	 * at CWP + 2.
873
	 */
874
	rdpr %cansave, %g3
875
	brnz %g3, 2f
876
	nop
877
	INLINE_SPILL_TO_WBUF %g3, %g4, %g7
878
 
879
2:
4369 rimsky 880
	set SCRATCHPAD_KSTACK, %g4
881
	ldxa [%g4] ASI_SCRATCHPAD, %g6
3993 rimsky 882
	save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
883
 
884
.if \is_syscall
885
	/* Copy arguments for the syscall to the new window. */
886
	mov %i0, %o0
887
	mov %i1, %o1
888
	mov %i2, %o2
889
	mov %i3, %o3
890
	mov %i4, %o4
891
	mov %i5, %o5
892
.endif
893
 
894
	mov VA_PRIMARY_CONTEXT_REG, %l0 
895
	stxa %g0, [%l0] ASI_PRIMARY_CONTEXT_REG
896
	rd %pc, %l0
897
	flush %l0
898
 
899
	/* Mark the CANRESTORE windows as OTHER windows. */
900
	rdpr %canrestore, %l0
901
	wrpr %l0, %otherwin
902
	wrpr %g0, %canrestore
903
 
904
	/*
905
	 * Other window spills will go to the userspace window buffer
906
	 * and normal spills will go to the kernel stack.
907
	 */
908
	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
909
 
910
	MIDDLE_PART \is_syscall
911
 
912
4:
913
	/*
914
	 * Spills and fills will be processed by the {spill,fill}_1_normal
915
	 * handlers.
916
	 */
917
	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(1), %wstate
918
 
919
	/*
920
	 * Set primary context according to secondary context.
921
	 */
922
	wr %g0, ASI_SECONDARY_CONTEXT_REG, %asi
923
	ldxa [VA_SECONDARY_CONTEXT_REG] %asi, %g1
924
	wr %g0, ASI_PRIMARY_CONTEXT_REG, %asi
925
	stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi
926
	rd %pc, %g1
927
	flush %g1
928
 
929
	/* Restoring userspace windows: */
930
 
931
	/* Save address of the userspace window buffer to the %g7 register. */
4369 rimsky 932
	set SCRATCHPAD_WBUF, %g5
933
	ldxa [%g5] ASI_SCRATCHPAD, %g7
3993 rimsky 934
 
935
	rdpr %cwp, %g1
936
	rdpr %otherwin, %g2
937
 
938
	/*
939
	 * Skip all OTHERWIN windows and descend to the first window
940
	 * in the userspace window buffer.
941
	 */
942
	sub %g1, %g2, %g3
943
	dec %g3
944
	and %g3, NWINDOWS - 1, %g3
945
	wrpr %g3, 0, %cwp
946
 
947
	/*
948
	 * CWP is now in the window last saved in the userspace window buffer.
949
	 * Fill all windows stored in the buffer.
950
	 */
951
	clr %g4
952
5:	andcc %g7, UWB_ALIGNMENT - 1, %g0	! alignment check
953
	bz 6f					! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill
954
	nop
955
 
956
	add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7
957
	ldx [%g7 + L0_OFFSET], %l0
958
	ldx [%g7 + L1_OFFSET], %l1
959
	ldx [%g7 + L2_OFFSET], %l2
960
	ldx [%g7 + L3_OFFSET], %l3
961
	ldx [%g7 + L4_OFFSET], %l4
962
	ldx [%g7 + L5_OFFSET], %l5
963
	ldx [%g7 + L6_OFFSET], %l6
964
	ldx [%g7 + L7_OFFSET], %l7
965
	ldx [%g7 + I0_OFFSET], %i0
966
	ldx [%g7 + I1_OFFSET], %i1
967
	ldx [%g7 + I2_OFFSET], %i2
968
	ldx [%g7 + I3_OFFSET], %i3
969
	ldx [%g7 + I4_OFFSET], %i4
970
	ldx [%g7 + I5_OFFSET], %i5
971
	ldx [%g7 + I6_OFFSET], %i6
972
	ldx [%g7 + I7_OFFSET], %i7
973
 
974
	dec %g3
975
	and %g3, NWINDOWS - 1, %g3
976
	wrpr %g3, 0, %cwp			! switch to the preceeding window
977
 
978
	ba 5b
979
	inc %g4
980
 
981
6:
982
	/* Save changes of the address of the userspace window buffer. */
4369 rimsky 983
	stxa %g7, [%g5] ASI_SCRATCHPAD
3993 rimsky 984
 
985
	/*
986
	 * Switch back to the proper current window and adjust
987
	 * OTHERWIN, CANRESTORE, CANSAVE and CLEANWIN.
988
	 */
989
	wrpr %g1, 0, %cwp
990
	add %g4, %g2, %g2
991
	cmp %g2, NWINDOWS - 2
992
	bg 8f					! fix the CANRESTORE=NWINDOWS-1 anomaly
993
	mov NWINDOWS - 2, %g1			! use dealy slot for both cases
994
	sub %g1, %g2, %g1
995
 
996
	wrpr %g0, 0, %otherwin
997
	wrpr %g1, 0, %cansave			! NWINDOWS - 2 - CANRESTORE
998
	wrpr %g2, 0, %canrestore		! OTHERWIN + windows in the buffer
999
	wrpr %g2, 0, %cleanwin			! avoid information leak
1000
 
1001
7:
1002
	restore
1003
 
1004
.if \is_syscall
1005
	done
1006
.else
1007
	retry
1008
.endif
1009
 
1010
8:
1011
	/*
1012
	 * We got here in order to avoid inconsistency of the window state registers.
1013
	 * If the:
1014
	 *
1015
	 * 	save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
1016
	 *
1017
	 * instruction trapped and spilled a register window into the userspace
1018
	 * window buffer, we have just restored NWINDOWS - 1 register windows.
1019
	 * However, CANRESTORE can be only NWINDOW - 2 at most.
1020
	 *
1021
	 * The solution is to manually switch to (CWP - 1) mod NWINDOWS
1022
	 * and set the window state registers so that:
1023
	 *
1024
	 * 	CANRESTORE 	= NWINDOWS - 2
1025
	 *	CLEANWIN	= NWINDOWS - 2
1026
	 *	CANSAVE 	= 0
1027
	 *	OTHERWIN	= 0
1028
	 *
1029
	 * The RESTORE instruction is therfore to be skipped.
1030
	 */
1031
	wrpr %g0, 0, %otherwin
1032
	wrpr %g0, 0, %cansave
1033
	wrpr %g1, 0, %canrestore
1034
	wrpr %g1, 0, %cleanwin
1035
 
1036
	rdpr %cwp, %g1
1037
	dec %g1
1038
	and %g1, NWINDOWS - 1, %g1
1039
	wrpr %g1, 0, %cwp			! CWP--
1040
 
1041
.if \is_syscall
1042
	done
1043
.else
1044
	retry
1045
.endif
1046
 
1047
.endm
1048
 
3798 rimsky 1049
/* Preemptible trap handler for TL=1.
1050
 *
1051
 * This trap handler makes arrangements to make calling of scheduler() from
1052
 * within a trap context possible. It is called from several other trap
1053
 * handlers.
1054
 */
1055
.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
3993 rimsky 1056
	rdpr %tstate, %g3
1057
	and %g3, TSTATE_PRIV_BIT, %g3
1058
	brz %g3, 100f			! trapping from userspace
1059
	nop
1060
 
3798 rimsky 1061
	PREEMPTIBLE_HANDLER_KERNEL
3993 rimsky 1062
	ba 101f
1063
	nop
1064
 
1065
	100:
1066
	PREEMPTIBLE_HANDLER_USPACE \is_syscall
1067
 
1068
	101:
3743 rimsky 1069
.endm
1070
 
1071
.global preemptible_handler
1072
preemptible_handler:
1073
	PREEMPTIBLE_HANDLER_TEMPLATE 0
1074
 
1075
.global trap_instruction_handler
1076
trap_instruction_handler:
1077
	PREEMPTIBLE_HANDLER_TEMPLATE 1