Subversion Repositories HelenOS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3743 rimsky 1
#
2
# Copyright (c) 2005 Jakub Jermar
3
# All rights reserved.
4
#
5
# Redistribution and use in source and binary forms, with or without
6
# modification, are permitted provided that the following conditions
7
# are met:
8
#
9
# - Redistributions of source code must retain the above copyright
10
#   notice, this list of conditions and the following disclaimer.
11
# - Redistributions in binary form must reproduce the above copyright
12
#   notice, this list of conditions and the following disclaimer in the
13
#   documentation and/or other materials provided with the distribution.
14
# - The name of the author may not be used to endorse or promote products
15
#   derived from this software without specific prior written permission.
16
#
17
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
#
28
 
29
/**
30
 * @file
31
 * @brief This file contains kernel trap table.
32
 */
33
 
34
.register %g2, #scratch
35
.register %g3, #scratch
36
 
37
.text
38
 
39
#include <arch/trap/trap_table.h>
40
#include <arch/trap/regwin.h>
41
#include <arch/trap/interrupt.h>
42
#include <arch/trap/exception.h>
43
#include <arch/trap/syscall.h>
44
#include <arch/trap/sun4u/mmu.h>
45
#include <arch/mm/sun4u/mmu.h>
46
#include <arch/mm/page.h>
47
#include <arch/stack.h>
48
#include <arch/sun4u/regdef.h>
49
 
50
#define TABLE_SIZE	TRAP_TABLE_SIZE
51
#define ENTRY_SIZE	TRAP_TABLE_ENTRY_SIZE
52
 
53
/*
54
 * Kernel trap table.
55
 */
56
.align TABLE_SIZE
57
.global trap_table
58
trap_table:
59
 
60
/* TT = 0x08, TL = 0, instruction_access_exception */
61
.org trap_table + TT_INSTRUCTION_ACCESS_EXCEPTION*ENTRY_SIZE
62
.global instruction_access_exception_tl0
63
instruction_access_exception_tl0:
64
	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
65
	PREEMPTIBLE_HANDLER instruction_access_exception
66
 
67
/* TT = 0x0a, TL = 0, instruction_access_error */
68
.org trap_table + TT_INSTRUCTION_ACCESS_ERROR*ENTRY_SIZE
69
.global instruction_access_error_tl0
70
instruction_access_error_tl0:
71
	PREEMPTIBLE_HANDLER instruction_access_error
72
 
73
/* TT = 0x10, TL = 0, illegal_instruction */
74
.org trap_table + TT_ILLEGAL_INSTRUCTION*ENTRY_SIZE
75
.global illegal_instruction_tl0
76
illegal_instruction_tl0:
77
	PREEMPTIBLE_HANDLER illegal_instruction
78
 
79
/* TT = 0x11, TL = 0, privileged_opcode */
80
.org trap_table + TT_PRIVILEGED_OPCODE*ENTRY_SIZE
81
.global privileged_opcode_tl0
82
privileged_opcode_tl0:
83
	PREEMPTIBLE_HANDLER privileged_opcode
84
 
85
/* TT = 0x12, TL = 0, unimplemented_LDD */
86
.org trap_table + TT_UNIMPLEMENTED_LDD*ENTRY_SIZE
87
.global unimplemented_LDD_tl0
88
unimplemented_LDD_tl0:
89
	PREEMPTIBLE_HANDLER unimplemented_LDD
90
 
91
/* TT = 0x13, TL = 0, unimplemented_STD */
92
.org trap_table + TT_UNIMPLEMENTED_STD*ENTRY_SIZE
93
.global unimplemented_STD_tl0
94
unimplemented_STD_tl0:
95
	PREEMPTIBLE_HANDLER unimplemented_STD
96
 
97
/* TT = 0x20, TL = 0, fb_disabled handler */
98
.org trap_table + TT_FP_DISABLED*ENTRY_SIZE
99
.global fb_disabled_tl0
100
fp_disabled_tl0:
101
	PREEMPTIBLE_HANDLER fp_disabled
102
 
103
/* TT = 0x21, TL = 0, fb_exception_ieee_754 handler */
104
.org trap_table + TT_FP_EXCEPTION_IEEE_754*ENTRY_SIZE
105
.global fb_exception_ieee_754_tl0
106
fp_exception_ieee_754_tl0:
107
	PREEMPTIBLE_HANDLER fp_exception_ieee_754
108
 
109
/* TT = 0x22, TL = 0, fb_exception_other handler */
110
.org trap_table + TT_FP_EXCEPTION_OTHER*ENTRY_SIZE
111
.global fb_exception_other_tl0
112
fp_exception_other_tl0:
113
	PREEMPTIBLE_HANDLER fp_exception_other
114
 
115
/* TT = 0x23, TL = 0, tag_overflow */
116
.org trap_table + TT_TAG_OVERFLOW*ENTRY_SIZE
117
.global tag_overflow_tl0
118
tag_overflow_tl0:
119
	PREEMPTIBLE_HANDLER tag_overflow
120
 
121
/* TT = 0x24, TL = 0, clean_window handler */
122
.org trap_table + TT_CLEAN_WINDOW*ENTRY_SIZE
123
.global clean_window_tl0
124
clean_window_tl0:
125
	CLEAN_WINDOW_HANDLER
126
 
127
/* TT = 0x28, TL = 0, division_by_zero */
128
.org trap_table + TT_DIVISION_BY_ZERO*ENTRY_SIZE
129
.global division_by_zero_tl0
130
division_by_zero_tl0:
131
	PREEMPTIBLE_HANDLER division_by_zero
132
 
133
/* TT = 0x30, TL = 0, data_access_exception */
134
.org trap_table + TT_DATA_ACCESS_EXCEPTION*ENTRY_SIZE
135
.global data_access_exception_tl0
136
data_access_exception_tl0:
137
	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
138
	PREEMPTIBLE_HANDLER data_access_exception
139
 
140
/* TT = 0x32, TL = 0, data_access_error */
141
.org trap_table + TT_DATA_ACCESS_ERROR*ENTRY_SIZE
142
.global data_access_error_tl0
143
data_access_error_tl0:
144
	PREEMPTIBLE_HANDLER data_access_error
145
 
146
/* TT = 0x34, TL = 0, mem_address_not_aligned */
147
.org trap_table + TT_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
148
.global mem_address_not_aligned_tl0
149
mem_address_not_aligned_tl0:
150
	PREEMPTIBLE_HANDLER mem_address_not_aligned
151
 
152
/* TT = 0x35, TL = 0, LDDF_mem_address_not_aligned */
153
.org trap_table + TT_LDDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
154
.global LDDF_mem_address_not_aligned_tl0
155
LDDF_mem_address_not_aligned_tl0:
156
	PREEMPTIBLE_HANDLER LDDF_mem_address_not_aligned
157
 
158
/* TT = 0x36, TL = 0, STDF_mem_address_not_aligned */
159
.org trap_table + TT_STDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
160
.global STDF_mem_address_not_aligned_tl0
161
STDF_mem_address_not_aligned_tl0:
162
	PREEMPTIBLE_HANDLER STDF_mem_address_not_aligned
163
 
164
/* TT = 0x37, TL = 0, privileged_action */
165
.org trap_table + TT_PRIVILEGED_ACTION*ENTRY_SIZE
166
.global privileged_action_tl0
167
privileged_action_tl0:
168
	PREEMPTIBLE_HANDLER privileged_action
169
 
170
/* TT = 0x38, TL = 0, LDQF_mem_address_not_aligned */
171
.org trap_table + TT_LDQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
172
.global LDQF_mem_address_not_aligned_tl0
173
LDQF_mem_address_not_aligned_tl0:
174
	PREEMPTIBLE_HANDLER LDQF_mem_address_not_aligned
175
 
176
/* TT = 0x39, TL = 0, STQF_mem_address_not_aligned */
177
.org trap_table + TT_STQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
178
.global STQF_mem_address_not_aligned_tl0
179
STQF_mem_address_not_aligned_tl0:
180
	PREEMPTIBLE_HANDLER STQF_mem_address_not_aligned
181
 
182
/* TT = 0x41, TL = 0, interrupt_level_1 handler */
183
.org trap_table + TT_INTERRUPT_LEVEL_1*ENTRY_SIZE
184
.global interrupt_level_1_handler_tl0
185
interrupt_level_1_handler_tl0:
186
	INTERRUPT_LEVEL_N_HANDLER 1
187
 
188
/* TT = 0x42, TL = 0, interrupt_level_2 handler */
189
.org trap_table + TT_INTERRUPT_LEVEL_2*ENTRY_SIZE
190
.global interrupt_level_2_handler_tl0
191
interrupt_level_2_handler_tl0:
192
	INTERRUPT_LEVEL_N_HANDLER 2
193
 
194
/* TT = 0x43, TL = 0, interrupt_level_3 handler */
195
.org trap_table + TT_INTERRUPT_LEVEL_3*ENTRY_SIZE
196
.global interrupt_level_3_handler_tl0
197
interrupt_level_3_handler_tl0:
198
	INTERRUPT_LEVEL_N_HANDLER 3
199
 
200
/* TT = 0x44, TL = 0, interrupt_level_4 handler */
201
.org trap_table + TT_INTERRUPT_LEVEL_4*ENTRY_SIZE
202
.global interrupt_level_4_handler_tl0
203
interrupt_level_4_handler_tl0:
204
	INTERRUPT_LEVEL_N_HANDLER 4
205
 
206
/* TT = 0x45, TL = 0, interrupt_level_5 handler */
207
.org trap_table + TT_INTERRUPT_LEVEL_5*ENTRY_SIZE
208
.global interrupt_level_5_handler_tl0
209
interrupt_level_5_handler_tl0:
210
	INTERRUPT_LEVEL_N_HANDLER 5
211
 
212
/* TT = 0x46, TL = 0, interrupt_level_6 handler */
213
.org trap_table + TT_INTERRUPT_LEVEL_6*ENTRY_SIZE
214
.global interrupt_level_6_handler_tl0
215
interrupt_level_6_handler_tl0:
216
	INTERRUPT_LEVEL_N_HANDLER 6
217
 
218
/* TT = 0x47, TL = 0, interrupt_level_7 handler */
219
.org trap_table + TT_INTERRUPT_LEVEL_7*ENTRY_SIZE
220
.global interrupt_level_7_handler_tl0
221
interrupt_level_7_handler_tl0:
222
	INTERRUPT_LEVEL_N_HANDLER 7
223
 
224
/* TT = 0x48, TL = 0, interrupt_level_8 handler */
225
.org trap_table + TT_INTERRUPT_LEVEL_8*ENTRY_SIZE
226
.global interrupt_level_8_handler_tl0
227
interrupt_level_8_handler_tl0:
228
	INTERRUPT_LEVEL_N_HANDLER 8
229
 
230
/* TT = 0x49, TL = 0, interrupt_level_9 handler */
231
.org trap_table + TT_INTERRUPT_LEVEL_9*ENTRY_SIZE
232
.global interrupt_level_9_handler_tl0
233
interrupt_level_9_handler_tl0:
234
	INTERRUPT_LEVEL_N_HANDLER 9
235
 
236
/* TT = 0x4a, TL = 0, interrupt_level_10 handler */
237
.org trap_table + TT_INTERRUPT_LEVEL_10*ENTRY_SIZE
238
.global interrupt_level_10_handler_tl0
239
interrupt_level_10_handler_tl0:
240
	INTERRUPT_LEVEL_N_HANDLER 10
241
 
242
/* TT = 0x4b, TL = 0, interrupt_level_11 handler */
243
.org trap_table + TT_INTERRUPT_LEVEL_11*ENTRY_SIZE
244
.global interrupt_level_11_handler_tl0
245
interrupt_level_11_handler_tl0:
246
	INTERRUPT_LEVEL_N_HANDLER 11
247
 
248
/* TT = 0x4c, TL = 0, interrupt_level_12 handler */
249
.org trap_table + TT_INTERRUPT_LEVEL_12*ENTRY_SIZE
250
.global interrupt_level_12_handler_tl0
251
interrupt_level_12_handler_tl0:
252
	INTERRUPT_LEVEL_N_HANDLER 12
253
 
254
/* TT = 0x4d, TL = 0, interrupt_level_13 handler */
255
.org trap_table + TT_INTERRUPT_LEVEL_13*ENTRY_SIZE
256
.global interrupt_level_13_handler_tl0
257
interrupt_level_13_handler_tl0:
258
	INTERRUPT_LEVEL_N_HANDLER 13
259
 
260
/* TT = 0x4e, TL = 0, interrupt_level_14 handler */
261
.org trap_table + TT_INTERRUPT_LEVEL_14*ENTRY_SIZE
262
.global interrupt_level_14_handler_tl0
263
interrupt_level_14_handler_tl0:
264
	INTERRUPT_LEVEL_N_HANDLER 14
265
 
266
/* TT = 0x4f, TL = 0, interrupt_level_15 handler */
267
.org trap_table + TT_INTERRUPT_LEVEL_15*ENTRY_SIZE
268
.global interrupt_level_15_handler_tl0
269
interrupt_level_15_handler_tl0:
270
	INTERRUPT_LEVEL_N_HANDLER 15
271
 
272
/* TT = 0x60, TL = 0, interrupt_vector_trap handler */
273
.org trap_table + TT_INTERRUPT_VECTOR_TRAP*ENTRY_SIZE
274
.global interrupt_vector_trap_handler_tl0
275
interrupt_vector_trap_handler_tl0:
276
	INTERRUPT_VECTOR_TRAP_HANDLER
277
 
278
/* TT = 0x64, TL = 0, fast_instruction_access_MMU_miss */
279
.org trap_table + TT_FAST_INSTRUCTION_ACCESS_MMU_MISS*ENTRY_SIZE
280
.global fast_instruction_access_mmu_miss_handler_tl0
281
fast_instruction_access_mmu_miss_handler_tl0:
282
	FAST_INSTRUCTION_ACCESS_MMU_MISS_HANDLER
283
 
284
/* TT = 0x68, TL = 0, fast_data_access_MMU_miss */
285
.org trap_table + TT_FAST_DATA_ACCESS_MMU_MISS*ENTRY_SIZE
286
.global fast_data_access_mmu_miss_handler_tl0
287
fast_data_access_mmu_miss_handler_tl0:
288
	FAST_DATA_ACCESS_MMU_MISS_HANDLER 0
289
 
290
/* TT = 0x6c, TL = 0, fast_data_access_protection */
291
.org trap_table + TT_FAST_DATA_ACCESS_PROTECTION*ENTRY_SIZE
292
.global fast_data_access_protection_handler_tl0
293
fast_data_access_protection_handler_tl0:
294
	FAST_DATA_ACCESS_PROTECTION_HANDLER 0
295
 
296
/* TT = 0x80, TL = 0, spill_0_normal handler */
297
.org trap_table + TT_SPILL_0_NORMAL*ENTRY_SIZE
298
.global spill_0_normal_tl0
299
spill_0_normal_tl0:
300
	SPILL_NORMAL_HANDLER_KERNEL
301
 
302
/* TT = 0x84, TL = 0, spill_1_normal handler */
303
.org trap_table + TT_SPILL_1_NORMAL*ENTRY_SIZE
304
.global spill_1_normal_tl0
305
spill_1_normal_tl0:
306
	SPILL_NORMAL_HANDLER_USERSPACE
307
 
308
/* TT = 0x88, TL = 0, spill_2_normal handler */
309
.org trap_table + TT_SPILL_2_NORMAL*ENTRY_SIZE
310
.global spill_2_normal_tl0
311
spill_2_normal_tl0:
312
	SPILL_TO_USPACE_WINDOW_BUFFER
313
 
314
/* TT = 0xa0, TL = 0, spill_0_other handler */
315
.org trap_table + TT_SPILL_0_OTHER*ENTRY_SIZE
316
.global spill_0_other_tl0
317
spill_0_other_tl0:
318
	SPILL_TO_USPACE_WINDOW_BUFFER
319
 
320
/* TT = 0xc0, TL = 0, fill_0_normal handler */
321
.org trap_table + TT_FILL_0_NORMAL*ENTRY_SIZE
322
.global fill_0_normal_tl0
323
fill_0_normal_tl0:
324
	FILL_NORMAL_HANDLER_KERNEL
325
 
326
/* TT = 0xc4, TL = 0, fill_1_normal handler */
327
.org trap_table + TT_FILL_1_NORMAL*ENTRY_SIZE
328
.global fill_1_normal_tl0
329
fill_1_normal_tl0:
330
	FILL_NORMAL_HANDLER_USERSPACE
331
 
332
/* TT = 0x100 - 0x17f, TL = 0, trap_instruction_0 - trap_instruction_7f */
333
.irp cur, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\
334
    20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\
335
    39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,\
336
    58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,\
337
    77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,\
338
    96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,\
339
    112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,\
340
    127
341
.org trap_table + (TT_TRAP_INSTRUCTION_0+\cur)*ENTRY_SIZE
342
.global trap_instruction_\cur\()_tl0
343
trap_instruction_\cur\()_tl0:
344
	ba trap_instruction_handler
345
	mov \cur, %g2
346
.endr
347
 
348
/*
349
 * Handlers for TL>0.
350
 */
351
 
352
/* TT = 0x08, TL > 0, instruction_access_exception */
353
.org trap_table + (TT_INSTRUCTION_ACCESS_EXCEPTION+512)*ENTRY_SIZE
354
.global instruction_access_exception_tl1
355
instruction_access_exception_tl1:
356
	wrpr %g0, 1, %tl
357
	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
358
	PREEMPTIBLE_HANDLER instruction_access_exception
359
 
360
/* TT = 0x0a, TL > 0, instruction_access_error */
361
.org trap_table + (TT_INSTRUCTION_ACCESS_ERROR+512)*ENTRY_SIZE
362
.global instruction_access_error_tl1
363
instruction_access_error_tl1:
364
	wrpr %g0, 1, %tl
365
	PREEMPTIBLE_HANDLER instruction_access_error
366
 
367
/* TT = 0x10, TL > 0, illegal_instruction */
368
.org trap_table + (TT_ILLEGAL_INSTRUCTION+512)*ENTRY_SIZE
369
.global illegal_instruction_tl1
370
illegal_instruction_tl1:
371
	wrpr %g0, 1, %tl
372
	PREEMPTIBLE_HANDLER illegal_instruction
373
 
374
/* TT = 0x24, TL > 0, clean_window handler */
375
.org trap_table + (TT_CLEAN_WINDOW+512)*ENTRY_SIZE
376
.global clean_window_tl1
377
clean_window_tl1:
378
	CLEAN_WINDOW_HANDLER
379
 
380
/* TT = 0x28, TL > 0, division_by_zero */
381
.org trap_table + (TT_DIVISION_BY_ZERO+512)*ENTRY_SIZE
382
.global division_by_zero_tl1
383
division_by_zero_tl1:
384
	wrpr %g0, 1, %tl
385
	PREEMPTIBLE_HANDLER division_by_zero
386
 
387
/* TT = 0x30, TL > 0, data_access_exception */
388
.org trap_table + (TT_DATA_ACCESS_EXCEPTION+512)*ENTRY_SIZE
389
.global data_access_exception_tl1
390
data_access_exception_tl1:
391
	wrpr %g0, 1, %tl
392
	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
393
	PREEMPTIBLE_HANDLER data_access_exception
394
 
395
/* TT = 0x32, TL > 0, data_access_error */
396
.org trap_table + (TT_DATA_ACCESS_ERROR+512)*ENTRY_SIZE
397
.global data_access_error_tl1
398
data_access_error_tl1:
399
	wrpr %g0, 1, %tl
400
	PREEMPTIBLE_HANDLER data_access_error
401
 
402
/* TT = 0x34, TL > 0, mem_address_not_aligned */
403
.org trap_table + (TT_MEM_ADDRESS_NOT_ALIGNED+512)*ENTRY_SIZE
404
.global mem_address_not_aligned_tl1
405
mem_address_not_aligned_tl1:
406
	wrpr %g0, 1, %tl
407
	PREEMPTIBLE_HANDLER mem_address_not_aligned
408
 
409
/* TT = 0x68, TL > 0, fast_data_access_MMU_miss */
410
.org trap_table + (TT_FAST_DATA_ACCESS_MMU_MISS+512)*ENTRY_SIZE
411
.global fast_data_access_mmu_miss_handler_tl1
412
fast_data_access_mmu_miss_handler_tl1:
413
	FAST_DATA_ACCESS_MMU_MISS_HANDLER 1
414
 
415
/* TT = 0x6c, TL > 0, fast_data_access_protection */
416
.org trap_table + (TT_FAST_DATA_ACCESS_PROTECTION+512)*ENTRY_SIZE
417
.global fast_data_access_protection_handler_tl1
418
fast_data_access_protection_handler_tl1:
419
	FAST_DATA_ACCESS_PROTECTION_HANDLER 1
420
 
421
/* TT = 0x80, TL > 0, spill_0_normal handler */
422
.org trap_table + (TT_SPILL_0_NORMAL+512)*ENTRY_SIZE
423
.global spill_0_normal_tl1
424
spill_0_normal_tl1:
425
	SPILL_NORMAL_HANDLER_KERNEL
426
 
427
/* TT = 0x88, TL > 0, spill_2_normal handler */
428
.org trap_table + (TT_SPILL_2_NORMAL+512)*ENTRY_SIZE
429
.global spill_2_normal_tl1
430
spill_2_normal_tl1:
431
	SPILL_TO_USPACE_WINDOW_BUFFER
432
 
433
/* TT = 0xa0, TL > 0, spill_0_other handler */
434
.org trap_table + (TT_SPILL_0_OTHER+512)*ENTRY_SIZE
435
.global spill_0_other_tl1
436
spill_0_other_tl1:
437
	SPILL_TO_USPACE_WINDOW_BUFFER
438
 
439
/* TT = 0xc0, TL > 0, fill_0_normal handler */
440
.org trap_table + (TT_FILL_0_NORMAL+512)*ENTRY_SIZE
441
.global fill_0_normal_tl1
442
fill_0_normal_tl1:
443
	FILL_NORMAL_HANDLER_KERNEL
444
 
445
.align TABLE_SIZE
446
 
447
 
448
#define NOT(x)	((x) == 0)
449
 
450
/* Preemptible trap handler for TL=1.
451
 *
452
 * This trap handler makes arrangements to make calling of scheduler() from
453
 * within a trap context possible. It is called from several other trap
454
 * handlers.
455
 *
456
 * This function can be entered either with interrupt globals or alternate
457
 * globals. Memory management trap handlers are obliged to switch to one of
458
 * those global sets prior to calling this function. Register window management
459
 * functions are not allowed to modify the alternate global registers.
460
 *
461
 * The kernel is designed to work on trap levels 0 - 4. For instance, the
462
 * following can happen:
463
 * TL0: kernel thread runs (CANSAVE=0, kernel stack not in DTLB)
464
 * TL1: preemptible trap handler started after a tick interrupt
465
 * TL2: preemptible trap handler did SAVE
466
 * TL3: spill handler touched the kernel stack  
467
 * TL4: hardware or software failure
468
 *
469
 * Input registers:
470
 *	%g1		Address of function to call if this is not a syscall.
471
 * 	%g2	 	First argument for the function.
472
 *	%g6		Pre-set as kernel stack base if trap from userspace.
473
 *	%g7		Pre-set as address of the userspace window buffer.
474
 */
475
.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
476
	/*
477
	 * ASSERT(%tl == 1)
478
	 */
479
	rdpr %tl, %g3
480
	cmp %g3, 1
481
	be 1f
482
	nop
483
0:	ba 0b					! this is for debugging, if we ever get here
484
	nop					! it will be easy to find
485
 
486
1:
487
.if NOT(\is_syscall)
488
	rdpr %tstate, %g3
489
 
490
	/*
491
	 * One of the ways this handler can be invoked is after a nested MMU trap from
492
	 * either spill_1_normal or fill_1_normal traps. Both of these traps manipulate
493
	 * the CWP register. We deal with the situation by simulating the MMU trap
494
	 * on TL=1 and restart the respective SAVE or RESTORE instruction once the MMU
495
	 * trap is resolved. However, because we are in the wrong window from the
496
	 * perspective of the MMU trap, we need to synchronize CWP with CWP from TL=0.
497
	 */ 
498
	and %g3, TSTATE_CWP_MASK, %g4
499
	wrpr %g4, 0, %cwp			! resynchronize CWP
500
 
501
	andcc %g3, TSTATE_PRIV_BIT, %g0		! if this trap came from the privileged mode...
502
	bnz 0f					! ...skip setting of kernel stack and primary context
503
	nop
504
 
505
.endif
506
	/*
507
	 * Normal window spills will go to the userspace window buffer.
508
	 */
509
	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(2), %wstate
510
 
511
	wrpr %g0, NWINDOWS - 1, %cleanwin	! prevent unnecessary clean_window exceptions
512
 
513
	/*
514
	 * Switch to kernel stack. The old stack is
515
	 * automatically saved in the old window's %sp
516
	 * and the new window's %fp.
517
	 */
518
	save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
519
 
520
.if \is_syscall
521
	/*
522
	 * Copy arguments for the syscall to the new window.
523
	 */
524
	mov %i0, %o0
525
	mov %i1, %o1
526
	mov %i2, %o2
527
	mov %i3, %o3
528
	mov %i4, %o4
529
	mov %i5, %o5
530
.endif
531
 
532
	/*
533
	 * Mark the CANRESTORE windows as OTHER windows.
534
	 */
535
	rdpr %canrestore, %l0
536
	wrpr %l0, %otherwin
537
	wrpr %g0, %canrestore
538
 
539
	/*
540
	 * Switch to primary context 0.
541
	 */
542
	mov VA_PRIMARY_CONTEXT_REG, %l0
543
	stxa %g0, [%l0] ASI_DMMU
544
	rd %pc, %l0
545
	flush %l0
546
 
547
.if NOT(\is_syscall)
548
	ba 1f
549
	nop
550
0:
551
	save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
552
 
553
	/*
554
	 * At this moment, we are using the kernel stack 
555
	 * and have successfully allocated a register window.
556
	 */
557
1:
558
.endif
559
	/*
560
	 * Other window spills will go to the userspace window buffer
561
	 * and normal spills will go to the kernel stack.
562
	 */
563
	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
564
 
565
	/*
566
	 * Copy arguments.
567
	 */
568
	mov %g1, %l0
569
.if NOT(\is_syscall)
570
	mov %g2, %o0
571
.else
572
	! store the syscall number on the stack as 7th argument
573
	stx %g2, [%sp + STACK_WINDOW_SAVE_AREA_SIZE + STACK_BIAS + STACK_ARG6] 
574
.endif
575
 
576
	/*
577
	 * Save TSTATE, TPC and TNPC aside.
578
	 */
579
	rdpr %tstate, %g1
580
	rdpr %tpc, %g2
581
	rdpr %tnpc, %g3
582
	rd %y, %g4
583
 
584
	stx %g1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE]
585
	stx %g2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC]
586
	stx %g3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC]
587
 
588
	/*
589
	 * Save the Y register.
590
	 * This register is deprecated according to SPARC V9 specification
591
	 * and is only present for backward compatibility with previous
592
	 * versions of the SPARC architecture.
593
	 * Surprisingly, gcc makes use of this register without a notice.
594
	 */
595
	stx %g4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y]
596
 
597
	wrpr %g0, 0, %tl
598
	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
599
	SAVE_GLOBALS
600
 
601
.if NOT(\is_syscall)
602
	/*
603
	 * Call the higher-level handler and pass istate as second parameter.
604
	 */
605
	call %l0
606
	add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
607
.else
608
	/*
609
	 * Call the higher-level syscall handler.
610
	 */
611
	call syscall_handler
612
	nop
613
	mov %o0, %i0				! copy the value returned by the syscall
614
.endif
615
 
616
	RESTORE_GLOBALS
617
	rdpr %pstate, %l1			! we must preserve the PEF bit
618
	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
619
	wrpr %g0, 1, %tl
620
 
621
	/*
622
	 * Read TSTATE, TPC and TNPC from saved copy.
623
	 */
624
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE], %g1
625
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC], %g2
626
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC], %g3
627
 
628
	/*
629
	 * Copy PSTATE.PEF to the in-register copy of TSTATE.
630
	 */
631
	and %l1, PSTATE_PEF_BIT, %l1
632
	sllx %l1, TSTATE_PSTATE_SHIFT, %l1
633
	sethi %hi(TSTATE_PEF_BIT), %g4
634
	andn %g1, %g4, %g1
635
	or %g1, %l1, %g1
636
 
637
	/*
638
	 * Restore TSTATE, TPC and TNPC from saved copies.
639
	 */
640
	wrpr %g1, 0, %tstate
641
	wrpr %g2, 0, %tpc
642
	wrpr %g3, 0, %tnpc
643
 
644
	/*
645
	 * Restore Y.
646
	 */
647
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y], %g4
648
	wr %g4, %y
649
 
650
	/*
651
	 * If OTHERWIN is zero, then all the userspace windows have been
652
	 * spilled to kernel memory (i.e. register window buffer). Moreover,
653
	 * if the scheduler was called in the meantime, all valid windows
654
	 * belonging to other threads were spilled by context_restore().
655
	 * If OTHERWIN is non-zero, then some userspace windows are still
656
	 * valid. Others might have been spilled. However, the CWP pointer
657
	 * needs no fixing because the scheduler had not been called.
658
	 */
659
	rdpr %otherwin, %l0
660
	brnz %l0, 0f
661
	nop
662
 
663
	/*
664
	 * OTHERWIN == 0
665
	 */
666
 
667
	/*
668
	 * If TSTATE.CWP + 1 == CWP, then we still do not have to fix CWP.
669
	 */
670
	and %g1, TSTATE_CWP_MASK, %l0
671
	inc %l0
672
	and %l0, NWINDOWS - 1, %l0	! %l0 mod NWINDOWS
673
	rdpr %cwp, %l1
674
	cmp %l0, %l1
675
	bz 0f				! CWP is ok
676
	nop
677
 
678
	/*
679
	 * Fix CWP.
680
	 * In order to recapitulate, the input registers in the current
681
	 * window are the output registers of the window to which we want
682
	 * to restore. Because the fill trap fills only input and local
683
	 * registers of a window, we need to preserve those output
684
	 * registers manually.
685
	 */
686
	mov %sp, %g2
687
	stx %i0, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0]
688
	stx %i1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1]
689
	stx %i2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2]
690
	stx %i3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3]
691
	stx %i4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4]
692
	stx %i5, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5]
693
	stx %i6, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6]
694
	stx %i7, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7]
695
	wrpr %l0, 0, %cwp
696
	mov %g2, %sp
697
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0], %i0
698
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1], %i1
699
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2], %i2
700
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3], %i3
701
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4], %i4
702
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5], %i5
703
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6], %i6
704
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7], %i7
705
 
706
	/*
707
	 * OTHERWIN != 0 or fall-through from the OTHERWIN == 0 case.
708
	 * The CWP has already been restored to the value it had after the SAVE
709
	 * at the beginning of this function.
710
	 */
711
0:
712
.if NOT(\is_syscall)
713
	rdpr %tstate, %g1
714
	andcc %g1, TSTATE_PRIV_BIT, %g0		! if we are not returning to userspace...,
715
	bnz 1f					! ...skip restoring userspace windows
716
	nop
717
.endif
718
 
719
	/*
720
	 * Spills and fills will be processed by the {spill,fill}_1_normal
721
	 * handlers.
722
	 */
723
	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(1), %wstate
724
 
725
	/*
726
	 * Set primary context according to secondary context.
727
	 */
728
	wr %g0, ASI_DMMU, %asi
729
	ldxa [VA_SECONDARY_CONTEXT_REG] %asi, %g1
730
	stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi
731
	rd %pc, %g1
732
	flush %g1
733
 
734
	rdpr %cwp, %g1
735
	rdpr %otherwin, %g2
736
 
737
	/*
738
	 * Skip all OTHERWIN windows and descend to the first window
739
	 * in the userspace window buffer.
740
	 */
741
	sub %g1, %g2, %g3
742
	dec %g3
743
	and %g3, NWINDOWS - 1, %g3
744
	wrpr %g3, 0, %cwp
745
 
746
	/*
747
	 * CWP is now in the window last saved in the userspace window buffer.
748
	 * Fill all windows stored in the buffer.
749
	 */
750
	clr %g4
751
0:	andcc %g7, UWB_ALIGNMENT - 1, %g0	! alignment check
752
	bz 0f					! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill
753
	nop
754
 
755
	add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7
756
	ldx [%g7 + L0_OFFSET], %l0
757
	ldx [%g7 + L1_OFFSET], %l1
758
	ldx [%g7 + L2_OFFSET], %l2
759
	ldx [%g7 + L3_OFFSET], %l3
760
	ldx [%g7 + L4_OFFSET], %l4
761
	ldx [%g7 + L5_OFFSET], %l5
762
	ldx [%g7 + L6_OFFSET], %l6
763
	ldx [%g7 + L7_OFFSET], %l7
764
	ldx [%g7 + I0_OFFSET], %i0
765
	ldx [%g7 + I1_OFFSET], %i1
766
	ldx [%g7 + I2_OFFSET], %i2
767
	ldx [%g7 + I3_OFFSET], %i3
768
	ldx [%g7 + I4_OFFSET], %i4
769
	ldx [%g7 + I5_OFFSET], %i5
770
	ldx [%g7 + I6_OFFSET], %i6
771
	ldx [%g7 + I7_OFFSET], %i7
772
 
773
	dec %g3
774
	and %g3, NWINDOWS - 1, %g3
775
	wrpr %g3, 0, %cwp			! switch to the preceeding window
776
 
777
	ba 0b
778
	inc %g4
779
 
780
0:
781
	/*
782
	 * Switch back to the proper current window and adjust
783
	 * OTHERWIN, CANRESTORE, CANSAVE and CLEANWIN.
784
	 */
785
	wrpr %g1, 0, %cwp
786
	add %g4, %g2, %g2
787
	cmp %g2, NWINDOWS - 2
788
	bg 2f					! fix the CANRESTORE=NWINDOWS-1 anomaly
789
	mov NWINDOWS - 2, %g1			! use dealy slot for both cases
790
	sub %g1, %g2, %g1
791
 
792
	wrpr %g0, 0, %otherwin
793
	wrpr %g1, 0, %cansave			! NWINDOWS - 2 - CANRESTORE
794
	wrpr %g2, 0, %canrestore		! OTHERWIN + windows in the buffer
795
	wrpr %g2, 0, %cleanwin			! avoid information leak
796
 
797
1:
798
	restore
799
 
800
.if \is_syscall
801
	done
802
.else
803
	retry
804
.endif
805
 
806
	/*
807
	 * We got here in order to avoid inconsistency of the window state registers.
808
	 * If the:
809
	 *
810
	 * 	save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
811
	 *
812
	 * instruction trapped and spilled a register window into the userspace
813
	 * window buffer, we have just restored NWINDOWS - 1 register windows.
814
	 * However, CANRESTORE can be only NWINDOW - 2 at most.
815
	 *
816
	 * The solution is to manually switch to (CWP - 1) mod NWINDOWS
817
	 * and set the window state registers so that:
818
	 *
819
	 * 	CANRESTORE 	= NWINDOWS - 2
820
	 *	CLEANWIN	= NWINDOWS - 2
821
	 *	CANSAVE 	= 0
822
	 *	OTHERWIN	= 0
823
	 *
824
	 * The RESTORE instruction is therfore to be skipped.
825
	 */
826
2:
827
	wrpr %g0, 0, %otherwin
828
	wrpr %g0, 0, %cansave
829
	wrpr %g1, 0, %canrestore
830
	wrpr %g1, 0, %cleanwin
831
 
832
	rdpr %cwp, %g1
833
	dec %g1
834
	and %g1, NWINDOWS - 1, %g1
835
	wrpr %g1, 0, %cwp			! CWP--
836
 
837
.if \is_syscall
838
	done
839
.else
840
	retry
841
.endif
842
 
843
.endm
844
 
845
.global preemptible_handler
846
preemptible_handler:
847
	PREEMPTIBLE_HANDLER_TEMPLATE 0
848
 
849
.global trap_instruction_handler
850
trap_instruction_handler:
851
	PREEMPTIBLE_HANDLER_TEMPLATE 1