Subversion Repositories HelenOS

Rev

Rev 1851 | Rev 1855 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1851 Rev 1852
Line 30... Line 30...
30
 * This file contains kernel trap table.
30
 * This file contains kernel trap table.
31
 */
31
 */
32
 
32
 
33
.register %g2, #scratch
33
.register %g2, #scratch
34
.register %g3, #scratch
34
.register %g3, #scratch
35
.register %g6, #scratch
-
 
36
.register %g7, #scratch 
-
 
37
 
35
 
38
.text
36
.text
39
 
37
 
40
#include <arch/trap/trap_table.h>
38
#include <arch/trap/trap_table.h>
41
#include <arch/trap/regwin.h>
39
#include <arch/trap/regwin.h>
Line 201... Line 199...
201
 
199
 
202
/* TT = 0x80, TL = 0, spill_0_normal handler */
200
/* TT = 0x80, TL = 0, spill_0_normal handler */
203
.org trap_table + TT_SPILL_0_NORMAL*ENTRY_SIZE
201
.org trap_table + TT_SPILL_0_NORMAL*ENTRY_SIZE
204
.global spill_0_normal
202
.global spill_0_normal
205
spill_0_normal:
203
spill_0_normal:
206
	SPILL_NORMAL_HANDLER
204
	SPILL_NORMAL_HANDLER_KERNEL
207
 
205
 
208
/* TT = 0xc0, TL = 0, fill_0_normal handler */
206
/* TT = 0xc0, TL = 0, fill_0_normal handler */
209
.org trap_table + TT_FILL_0_NORMAL*ENTRY_SIZE
207
.org trap_table + TT_FILL_0_NORMAL*ENTRY_SIZE
210
.global fill_0_normal
208
.global fill_0_normal
211
fill_0_normal:
209
fill_0_normal:
212
	FILL_NORMAL_HANDLER
210
	FILL_NORMAL_HANDLER_KERNEL
213
 
211
 
214
/*
212
/*
215
 * Handlers for TL>0.
213
 * Handlers for TL>0.
216
 */
214
 */
217
 
215
 
Line 265... Line 263...
265
 
263
 
266
/* TT = 0x80, TL > 0, spill_0_normal handler */
264
/* TT = 0x80, TL > 0, spill_0_normal handler */
267
.org trap_table + (TT_SPILL_0_NORMAL+512)*ENTRY_SIZE
265
.org trap_table + (TT_SPILL_0_NORMAL+512)*ENTRY_SIZE
268
.global spill_0_normal_high
266
.global spill_0_normal_high
269
spill_0_normal_high:
267
spill_0_normal_high:
270
	SPILL_NORMAL_HANDLER
268
	SPILL_NORMAL_HANDLER_KERNEL
271
 
269
 
272
/* TT = 0xc0, TL > 0, fill_0_normal handler */
270
/* TT = 0xc0, TL > 0, fill_0_normal handler */
273
.org trap_table + (TT_FILL_0_NORMAL+512)*ENTRY_SIZE
271
.org trap_table + (TT_FILL_0_NORMAL+512)*ENTRY_SIZE
274
.global fill_0_normal_high
272
.global fill_0_normal_high
275
fill_0_normal_high:
273
fill_0_normal_high:
276
	FILL_NORMAL_HANDLER
274
	FILL_NORMAL_HANDLER_KERNEL
277
 
275
 
278
 
276
 
279
/* Preemptible trap handler for TL=1.
277
/* Preemptible trap handler for TL=1.
280
 *
278
 *
281
 * This trap handler makes arrangements to make calling of scheduler() from
279
 * This trap handler makes arrangements to make calling of scheduler() from
282
 * within a trap context possible. It is guaranteed to function only when traps
280
 * within a trap context possible. It is called from several other trap
283
 * are not nested (i.e. for TL=1).
281
 * handlers.
284
 *
282
 *
285
 * Every trap handler on TL=1 that makes a call to the scheduler needs to
-
 
286
 * be based on this function. The reason behind it is that the nested
-
 
287
 * trap levels and the automatic saving of the interrupted context by hardware
283
 * This function can be entered either with interrupt globals or alternate globals.
288
 * does not work well together with scheduling (i.e. a thread cannot be rescheduled
284
 * Memory management trap handlers are obliged to switch to one of those global sets
289
 * with TL>0). Therefore it is necessary to eliminate the effect of trap levels
285
 * prior to calling this function. Register window management functions are not
290
 * by software and save the necessary state on the kernel stack.
286
 * allowed to modify the alternate global registers.
291
 *
-
 
292
 * Note that for traps with TL>1, more state needs to be saved. This function
-
 
293
 * is therefore not going to work when TL>1.
-
 
294
 *
-
 
295
 * The caller is responsible for doing SAVE and allocating
-
 
296
 * PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE bytes on the stack.
-
 
297
 *
287
 *
298
 * Input registers:
288
 * Input registers:
299
 * 	%l0	 	Address of function to call.
289
 *	%g1		Address of function to call.
300
 * Output registers:
290
 * 	%g2	 	Argument for the function.
-
 
291
 *	%g6		Pre-set as kernel stack base if trap from userspace.
301
 *	 %l1 - %l7 	Copy of %g1 - %g7
292
 *	%g7		Reserved.
302
 */
293
 */
303
.global preemptible_handler
294
.global preemptible_handler
304
preemptible_handler:
295
preemptible_handler:
-
 
296
	rdpr %tstate, %g3
-
 
297
	andcc %g3, TSTATE_PRIV_BIT, %g0		! if this trap came from the privileged mode...
-
 
298
	bnz 0f					! ...skip setting of kernel stack and primary context
-
 
299
	nop
-
 
300
 
-
 
301
	/*
-
 
302
	 * Switch to kernel stack. The old stack is
-
 
303
	 * automatically saved in the old window's %sp
-
 
304
	 * and the new window's %fp.
-
 
305
	 */
-
 
306
	save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
-
 
307
 
-
 
308
	/*
-
 
309
	 * Mark the CANSAVE windows as OTHER windows.
-
 
310
	 * Set CLEANWIN to NWINDOW-1 so that clean_window traps do not occur.
-
 
311
	 */
-
 
312
	rdpr %cansave, %l0
-
 
313
	wrpr %l0, %otherwin
-
 
314
	wrpr %g0, %cansave
-
 
315
	wrpr %g0, NWINDOW-1, %cleanwin
-
 
316
 
-
 
317
	/*
-
 
318
	 * Switch to primary context 0.
-
 
319
	 */
-
 
320
	mov VA_PRIMARY_CONTEXT_REG, %l0
-
 
321
        stxa %g0, [%l0] ASI_DMMU
-
 
322
	set kernel_image_start, %l0
-
 
323
        flush %l0
-
 
324
 
-
 
325
	ba 1f
-
 
326
	nop
-
 
327
 
-
 
328
0:
-
 
329
	save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
-
 
330
 
305
	/*
331
	/*
-
 
332
	 * At this moment, we are using the kernel stack 
-
 
333
	 * and have successfully allocated a register window.
-
 
334
	 */
-
 
335
1:
-
 
336
 
-
 
337
	/*
-
 
338
	 * Copy arguments.
-
 
339
	 */
-
 
340
	mov %g1, %l0
-
 
341
	mov %g2, %o0
-
 
342
 
-
 
343
	/*
306
	 * Save TSTATE, TPC, TNPC and PSTATE aside.
344
	 * Save TSTATE, TPC and TNPC aside.
307
	 */
345
	 */
308
	rdpr %tstate, %g1
346
	rdpr %tstate, %g1
309
	rdpr %tpc, %g2
347
	rdpr %tpc, %g2
310
	rdpr %tnpc, %g3
348
	rdpr %tnpc, %g3
311
	rdpr %pstate, %g4
-
 
312
 
349
 
313
	/*
350
	/*
314
	 * The following memory accesses will not fault
351
	 * The following memory accesses will not fault
315
	 * because special provisions are made to have
352
	 * because special provisions are made to have
316
	 * the kernel stack of THREAD locked in DTLB.
353
	 * the kernel stack of THREAD locked in DTLB.
317
	 */
354
	 */
318
	stx %g1, [%fp + STACK_BIAS + SAVED_TSTATE]
355
	stx %g1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE]
319
	stx %g2, [%fp + STACK_BIAS + SAVED_TPC]
356
	stx %g2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC]
320
	stx %g3, [%fp + STACK_BIAS + SAVED_TNPC]
357
	stx %g3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC]
321
	stx %g4, [%fp + STACK_BIAS + SAVED_PSTATE]
-
 
322
	
358
	
323
	/*
-
 
324
	 * Write 0 to TL.
-
 
325
	 */
-
 
326
	wrpr %g0, 0, %tl
359
	wrpr %g0, 0, %tl
327
	
-
 
328
	/*
-
 
329
	 * Alter PSTATE.
-
 
330
	 * - switch to normal globals.
-
 
331
	 */
-
 
332
	and %g4, ~(PSTATE_AG_BIT|PSTATE_IG_BIT|PSTATE_MG_BIT), %g4
-
 
333
	wrpr %g4, 0, %pstate
360
	wrpr %g0, PSTATE_PRIV_BIT, %pstate
334
	 
-
 
335
	/*
-
 
336
	 * Save the normal globals.
-
 
337
	 */
-
 
338
	SAVE_GLOBALS
361
	SAVE_GLOBALS
339
	
362
	
340
	/*
363
	/*
341
	 * Call the higher-level handler.
364
	 * Call the higher-level handler and pass istate as second parameter.
342
	 */
365
	 */
343
	mov %fp, %o1				! calculate istate address
-
 
344
	call %l0
366
	call %l0
345
	add %o1, STACK_BIAS + SAVED_PSTATE, %o1	! calculate istate address
367
	add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
346
	
368
 
347
	/*
-
 
348
	 * Restore	 the normal global register set.
-
 
349
	 */
-
 
350
	RESTORE_GLOBALS
369
	RESTORE_GLOBALS
-
 
370
	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
-
 
371
	wrpr %g0, 1, %tl
351
	
372
	
352
	/*
373
	/*
353
	 * Restore PSTATE from saved copy.
374
	 * Read TSTATE, TPC and TNPC from saved copy.
354
	 * Alternate/Interrupt/MM globals become active.
-
 
355
	 */
375
	 */
356
	ldx [%fp + STACK_BIAS + SAVED_PSTATE], %l4
376
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE], %g1
357
	wrpr %l4, 0, %pstate
377
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC], %g2
-
 
378
	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC], %g3
358
	
379
 
359
	/*
380
	/*
360
	 * Write 1 to TL.
381
	 * Restore TSTATE, TPC and TNPC from saved copies.
361
	 */
382
	 */
-
 
383
	wrpr %g1, 0, %tstate
362
	wrpr %g0, 1, %tl
384
	wrpr %g2, 0, %tpc
-
 
385
	wrpr %g3, 0, %tnpc
363
	
386
 
364
	/*
387
	/*
-
 
388
	 * If OTHERWIN is zero, then all the userspace windows have been
-
 
389
	 * spilled to kernel memory (i.e. register window buffer). If
-
 
390
	 * OTHERWIN is non-zero, then some userspace windows are still
-
 
391
	 * valid. Others might have been spilled. However, the CWP pointer
365
	 * Read TSTATE, TPC and TNPC from saved copy.
392
	 * needs no fixing because the scheduler had not been called.
366
	 */
393
	 */
367
	ldx [%fp + STACK_BIAS + SAVED_TSTATE], %g1
-
 
368
	ldx [%fp + STACK_BIAS + SAVED_TPC], %g2
394
	rdpr %otherwin, %l0
369
	ldx [%fp + STACK_BIAS + SAVED_TNPC], %g3
395
	brnz %l0, 0f
-
 
396
	nop
370
 
397
 
371
	/*
398
	/*
372
	 * Do restore to match the save instruction from the top-level handler.
399
	 * OTHERWIN == 0
373
	 */
400
	 */
374
	restore
-
 
375
 
401
 
376
	/*
402
	/*
377
	 * On execution of the RETRY instruction, CWP will be restored from the TSTATE
-
 
378
	 * register. However, because of scheduling, it is possible that CWP in the saved
-
 
379
	 * TSTATE is different from the current CWP. The following chunk of code fixes
403
	 * If TSTATE.CWP + 1 == CWP, then we still do not have to fix CWP.
380
	 * CWP in the saved copy of TSTATE.
-
 
381
	 */
404
	 */
382
	rdpr %cwp, %g4		! read current CWP
405
	and %g1, TSTATE_CWP_MASK, %l0
-
 
406
	inc %l0
383
	and %g1, ~0x1f, %g1	! clear CWP field in saved TSTATE
407
	and %l0, TSTATE_CWP_MASK, %l0	! %l0 mod NWINDOW
-
 
408
	rdpr %cwp, %l1
-
 
409
	cmp %l0, %l1
384
	or %g1, %g4, %g1	! write current CWP to TSTATE
410
	bz 0f				! CWP is ok
-
 
411
	nop
385
	
412
 
386
	/*
413
	/*
387
	 * Restore TSTATE, TPC and TNPC from saved copies.
414
	 * Fix CWP.
388
	 */
415
	 */
389
	wrpr %g1, 0, %tstate
416
	mov %fp, %g1
-
 
417
	flushw
390
	wrpr %g2, 0, %tpc
418
	wrpr %l0, 0, %cwp
391
	wrpr %g3, 0, %tnpc
419
	mov %g1, %fp
392
	 
420
	
393
	/*
421
	/*
394
	 * Return from interrupt.
422
	 * OTHERWIN != 0 or fall-through from the OTHERWIN == 0 case.
395
	 */
423
	 */
-
 
424
0:
-
 
425
	! TODO: restore register windows from register window memory buffer
-
 
426
 
-
 
427
	restore
396
	retry
428
	retry