Subversion Repositories HelenOS

Rev

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