HelenOS sources
#
#
#
# - Redistributions of source code must retain the above copyright
# - Redistributions in binary form must reproduce the above copyright
# - The name of the author may not be used to endorse or promote products
#
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
#
.register %g2, #scratch
.register %g3, #scratch
.text
#include <abi/asmtool.h>
#include <arch/trap/trap_table.h>
#include <arch/trap/regwin.h>
#include <arch/trap/interrupt.h>
#include <arch/trap/exception.h>
#include <arch/trap/syscall.h>
#include <arch/trap/mmu.h>
#include <arch/mm/mmu.h>
#include <arch/mm/page.h>
#include <arch/stack.h>
#include <arch/regdef.h>
#define TABLE_SIZE TRAP_TABLE_SIZE
#define ENTRY_SIZE TRAP_TABLE_ENTRY_SIZE
.align TABLE_SIZE
SYMBOL(trap_table)
.org trap_table + TT_INSTRUCTION_ACCESS_EXCEPTION*ENTRY_SIZE
SYMBOL(instruction_access_exception_tl0)
wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
mov TT_INSTRUCTION_ACCESS_EXCEPTION, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INSTRUCTION_ACCESS_ERROR*ENTRY_SIZE
SYMBOL(instruction_access_error_tl0)
mov TT_INSTRUCTION_ACCESS_ERROR, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_ILLEGAL_INSTRUCTION*ENTRY_SIZE
SYMBOL(illegal_instruction_tl0)
mov TT_ILLEGAL_INSTRUCTION, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_PRIVILEGED_OPCODE*ENTRY_SIZE
SYMBOL(privileged_opcode_tl0)
mov TT_PRIVILEGED_OPCODE, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_UNIMPLEMENTED_LDD*ENTRY_SIZE
SYMBOL(unimplemented_LDD_tl0)
mov TT_UNIMPLEMENTED_LDD, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_UNIMPLEMENTED_STD*ENTRY_SIZE
SYMBOL(unimplemented_STD_tl0)
mov TT_UNIMPLEMENTED_STD, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_FP_DISABLED*ENTRY_SIZE
SYMBOL(fp_disabled_tl0)
mov TT_FP_DISABLED, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_FP_EXCEPTION_IEEE_754*ENTRY_SIZE
SYMBOL(fp_exception_ieee_754_tl0)
mov TT_FP_EXCEPTION_IEEE_754, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_FP_EXCEPTION_OTHER*ENTRY_SIZE
SYMBOL(fp_exception_other_tl0)
mov TT_FP_EXCEPTION_OTHER, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_TAG_OVERFLOW*ENTRY_SIZE
SYMBOL(tag_overflow_tl0)
mov TT_TAG_OVERFLOW, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_CLEAN_WINDOW*ENTRY_SIZE
SYMBOL(clean_window_tl0)
CLEAN_WINDOW_HANDLER
.org trap_table + TT_DIVISION_BY_ZERO*ENTRY_SIZE
SYMBOL(division_by_zero_tl0)
mov TT_DIVISION_BY_ZERO, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_DATA_ACCESS_EXCEPTION*ENTRY_SIZE
SYMBOL(data_access_exception_tl0)
wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
mov TT_DATA_ACCESS_EXCEPTION, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_DATA_ACCESS_ERROR*ENTRY_SIZE
SYMBOL(data_access_error_tl0)
mov TT_DATA_ACCESS_ERROR, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
SYMBOL(mem_address_not_aligned_tl0)
mov TT_MEM_ADDRESS_NOT_ALIGNED, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_LDDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
SYMBOL(LDDF_mem_address_not_aligned_tl0)
mov TT_LDDF_MEM_ADDRESS_NOT_ALIGNED, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_STDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
SYMBOL(STDF_mem_address_not_aligned_tl0)
mov TT_STDF_MEM_ADDRESS_NOT_ALIGNED, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_PRIVILEGED_ACTION*ENTRY_SIZE
SYMBOL(privileged_action_tl0)
mov TT_PRIVILEGED_ACTION, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_LDQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
SYMBOL(LDQF_mem_address_not_aligned_tl0)
mov TT_LDQF_MEM_ADDRESS_NOT_ALIGNED, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_STQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
SYMBOL(STQF_mem_address_not_aligned_tl0)
mov TT_STQF_MEM_ADDRESS_NOT_ALIGNED, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_1*ENTRY_SIZE
SYMBOL(interrupt_level_1_handler_tl0)
mov TT_INTERRUPT_LEVEL_1, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_2*ENTRY_SIZE
SYMBOL(interrupt_level_2_handler_tl0)
mov TT_INTERRUPT_LEVEL_2, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_3*ENTRY_SIZE
SYMBOL(interrupt_level_3_handler_tl0)
mov TT_INTERRUPT_LEVEL_3, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_4*ENTRY_SIZE
SYMBOL(interrupt_level_4_handler_tl0)
mov TT_INTERRUPT_LEVEL_4, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_5*ENTRY_SIZE
SYMBOL(interrupt_level_5_handler_tl0)
mov TT_INTERRUPT_LEVEL_5, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_6*ENTRY_SIZE
SYMBOL(interrupt_level_6_handler_tl0)
mov TT_INTERRUPT_LEVEL_6, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_7*ENTRY_SIZE
SYMBOL(interrupt_level_7_handler_tl0)
mov TT_INTERRUPT_LEVEL_7, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_8*ENTRY_SIZE
SYMBOL(interrupt_level_8_handler_tl0)
mov TT_INTERRUPT_LEVEL_8, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_9*ENTRY_SIZE
SYMBOL(interrupt_level_9_handler_tl0)
mov TT_INTERRUPT_LEVEL_9, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_10*ENTRY_SIZE
SYMBOL(interrupt_level_10_handler_tl0)
mov TT_INTERRUPT_LEVEL_10, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_11*ENTRY_SIZE
SYMBOL(interrupt_level_11_handler_tl0)
mov TT_INTERRUPT_LEVEL_11, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_12*ENTRY_SIZE
SYMBOL(interrupt_level_12_handler_tl0)
mov TT_INTERRUPT_LEVEL_12, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_13*ENTRY_SIZE
SYMBOL(interrupt_level_13_handler_tl0)
mov TT_INTERRUPT_LEVEL_13, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_14*ENTRY_SIZE
SYMBOL(interrupt_level_14_handler_tl0)
mov TT_INTERRUPT_LEVEL_14, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_LEVEL_15*ENTRY_SIZE
SYMBOL(interrupt_level_15_handler_tl0)
mov TT_INTERRUPT_LEVEL_15, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_INTERRUPT_VECTOR_TRAP*ENTRY_SIZE
SYMBOL(interrupt_vector_trap_handler_tl0)
mov TT_INTERRUPT_VECTOR_TRAP, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + TT_FAST_INSTRUCTION_ACCESS_MMU_MISS*ENTRY_SIZE
SYMBOL(fast_instruction_access_mmu_miss_handler_tl0)
FAST_INSTRUCTION_ACCESS_MMU_MISS_HANDLER
.org trap_table + TT_FAST_DATA_ACCESS_MMU_MISS*ENTRY_SIZE
SYMBOL(fast_data_access_mmu_miss_handler_tl0)
FAST_DATA_ACCESS_MMU_MISS_HANDLER 0
.org trap_table + TT_FAST_DATA_ACCESS_PROTECTION*ENTRY_SIZE
SYMBOL(fast_data_access_protection_handler_tl0)
FAST_DATA_ACCESS_PROTECTION_HANDLER 0
.org trap_table + TT_SPILL_0_NORMAL*ENTRY_SIZE
SYMBOL(spill_0_normal_tl0)
SPILL_NORMAL_HANDLER_KERNEL
.org trap_table + TT_SPILL_1_NORMAL*ENTRY_SIZE
SYMBOL(spill_1_normal_tl0)
SPILL_NORMAL_HANDLER_USERSPACE
.org trap_table + TT_SPILL_2_NORMAL*ENTRY_SIZE
SYMBOL(spill_2_normal_tl0)
SPILL_TO_USPACE_WINDOW_BUFFER
.org trap_table + TT_SPILL_0_OTHER*ENTRY_SIZE
SYMBOL(spill_0_other_tl0)
SPILL_TO_USPACE_WINDOW_BUFFER
.org trap_table + TT_FILL_0_NORMAL*ENTRY_SIZE
SYMBOL(fill_0_normal_tl0)
FILL_NORMAL_HANDLER_KERNEL
.org trap_table + TT_FILL_1_NORMAL*ENTRY_SIZE
SYMBOL(fill_1_normal_tl0)
FILL_NORMAL_HANDLER_USERSPACE
.irp cur, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,\
58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,\
77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,\
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,\
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,\
127
.org trap_table + (TT_TRAP_INSTRUCTION_0+\cur)*ENTRY_SIZE
SYMBOL(trap_instruction_\cur\()_tl0)
mov \cur, %g2
ba %xcc, trap_instruction_handler
clr %g5
.endr
.org trap_table + (TT_INSTRUCTION_ACCESS_EXCEPTION+512)*ENTRY_SIZE
SYMBOL(instruction_access_exception_tl1)
wrpr %g0, 1, %tl
wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
mov TT_INSTRUCTION_ACCESS_EXCEPTION, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + (TT_INSTRUCTION_ACCESS_ERROR+512)*ENTRY_SIZE
SYMBOL(instruction_access_error_tl1)
wrpr %g0, 1, %tl
mov TT_INSTRUCTION_ACCESS_ERROR, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + (TT_ILLEGAL_INSTRUCTION+512)*ENTRY_SIZE
SYMBOL(illegal_instruction_tl1)
wrpr %g0, 1, %tl
mov TT_ILLEGAL_INSTRUCTION, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + (TT_CLEAN_WINDOW+512)*ENTRY_SIZE
SYMBOL(clean_window_tl1)
CLEAN_WINDOW_HANDLER
.org trap_table + (TT_DIVISION_BY_ZERO+512)*ENTRY_SIZE
SYMBOL(division_by_zero_tl1)
wrpr %g0, 1, %tl
mov TT_DIVISION_BY_ZERO, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + (TT_DATA_ACCESS_EXCEPTION+512)*ENTRY_SIZE
SYMBOL(data_access_exception_tl1)
wrpr %g0, 1, %tl
wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
mov TT_DATA_ACCESS_EXCEPTION, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + (TT_DATA_ACCESS_ERROR+512)*ENTRY_SIZE
SYMBOL(data_access_error_tl1)
wrpr %g0, 1, %tl
mov TT_DATA_ACCESS_ERROR, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + (TT_MEM_ADDRESS_NOT_ALIGNED+512)*ENTRY_SIZE
SYMBOL(mem_address_not_aligned_tl1)
wrpr %g0, 1, %tl
mov TT_MEM_ADDRESS_NOT_ALIGNED, %g2
clr %g5
PREEMPTIBLE_HANDLER exc_dispatch
.org trap_table + (TT_FAST_DATA_ACCESS_MMU_MISS+512)*ENTRY_SIZE
SYMBOL(fast_data_access_mmu_miss_handler_tl1)
FAST_DATA_ACCESS_MMU_MISS_HANDLER 1
.org trap_table + (TT_FAST_DATA_ACCESS_PROTECTION+512)*ENTRY_SIZE
SYMBOL(fast_data_access_protection_handler_tl1)
FAST_DATA_ACCESS_PROTECTION_HANDLER 1
.org trap_table + (TT_SPILL_0_NORMAL+512)*ENTRY_SIZE
SYMBOL(spill_0_normal_tl1)
SPILL_NORMAL_HANDLER_KERNEL
.org trap_table + (TT_SPILL_2_NORMAL+512)*ENTRY_SIZE
SYMBOL(spill_2_normal_tl1)
SPILL_TO_USPACE_WINDOW_BUFFER
.org trap_table + (TT_SPILL_0_OTHER+512)*ENTRY_SIZE
SYMBOL(spill_0_other_tl1)
SPILL_TO_USPACE_WINDOW_BUFFER
.org trap_table + (TT_FILL_0_NORMAL+512)*ENTRY_SIZE
SYMBOL(fill_0_normal_tl1)
FILL_NORMAL_HANDLER_KERNEL
.align TABLE_SIZE
#define NOT(x) ((x) == 0)
.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
.if NOT(\is_syscall)
rdpr %tstate, %g3
and %g3, TSTATE_CWP_MASK, %g4
wrpr %g4, 0, %cwp ! resynchronize CWP
andcc %g3, TSTATE_PRIV_BIT, %g0 ! if this trap came from the privileged mode...
bnz %xcc, 0f ! ...skip setting of kernel stack and primary context
nop
.endif
wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(2), %wstate
wrpr %g0, NWINDOWS - 1, %cleanwin ! prevent unnecessary clean_window exceptions
save %g6, -ISTATE_SIZE, %sp
.if \is_syscall
mov %i0, %o0
mov %i1, %o1
mov %i2, %o2
mov %i3, %o3
mov %i4, %o4
mov %i5, %o5
.endif
rdpr %canrestore, %l0
wrpr %l0, %otherwin
wrpr %g0, %canrestore
mov VA_PRIMARY_CONTEXT_REG, %l0
stxa %g0, [%l0] ASI_DMMU
rd %pc, %l0
flush %l0
.if NOT(\is_syscall)
ba,a %xcc, 1f
0:
save %sp, -ISTATE_SIZE, %sp
1:
.endif
wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
mov %g1, %l0
.if NOT(\is_syscall)
mov %g2, %o0
.else
! store the syscall number on the stack as 7th argument
stx %g2, [%sp + STACK_BIAS + ISTATE_OFFSET_ARG6]
.endif
rdpr %tstate, %g1
rdpr %tpc, %g2
rdpr %tnpc, %g3
rd %y, %g4
stx %g1, [%sp + STACK_BIAS + ISTATE_OFFSET_TSTATE]
stx %g2, [%sp + STACK_BIAS + ISTATE_OFFSET_TPC]
stx %g3, [%sp + STACK_BIAS + ISTATE_OFFSET_TNPC]
stx %g5, [%sp + STACK_BIAS + ISTATE_OFFSET_TLB_TAG_ACCESS]
stx %g4, [%sp + STACK_BIAS + ISTATE_OFFSET_Y]
wrpr %g0, 0, %tl
wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
SAVE_GLOBALS
.if NOT(\is_syscall)
call %l0
add %sp, STACK_BIAS, %o1
.else
call syscall_handler
wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT | PSTATE_IE_BIT, %pstate
mov %o0, %i0 ! copy the value returned by the syscall
.endif
RESTORE_GLOBALS
rdpr %pstate, %l1 ! we must preserve the PEF bit
wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
wrpr %g0, 1, %tl
ldx [%sp + STACK_BIAS + ISTATE_OFFSET_TSTATE], %g1
ldx [%sp + STACK_BIAS + ISTATE_OFFSET_TPC], %g2
ldx [%sp + STACK_BIAS + ISTATE_OFFSET_TNPC], %g3
and %l1, PSTATE_PEF_BIT, %l1
sllx %l1, TSTATE_PSTATE_SHIFT, %l1
sethi %hi(TSTATE_PEF_BIT), %g4
andn %g1, %g4, %g1
or %g1, %l1, %g1
wrpr %g1, 0, %tstate
wrpr %g2, 0, %tpc
wrpr %g3, 0, %tnpc
ldx [%sp + STACK_BIAS + ISTATE_OFFSET_Y], %g4
wr %g4, %y
rdpr %otherwin, %l0
brnz %l0, 0f
nop
and %g1, TSTATE_CWP_MASK, %l0
inc %l0
and %l0, NWINDOWS - 1, %l0 ! %l0 mod NWINDOWS
rdpr %cwp, %l1
cmp %l0, %l1
bz %xcc, 0f ! CWP is ok
nop
mov %sp, %g2
stx %i0, [%sp + STACK_BIAS + ISTATE_OFFSET_O0]
stx %i1, [%sp + STACK_BIAS + ISTATE_OFFSET_O1]
stx %i2, [%sp + STACK_BIAS + ISTATE_OFFSET_O2]
stx %i3, [%sp + STACK_BIAS + ISTATE_OFFSET_O3]
stx %i4, [%sp + STACK_BIAS + ISTATE_OFFSET_O4]
stx %i5, [%sp + STACK_BIAS + ISTATE_OFFSET_O5]
stx %i6, [%sp + STACK_BIAS + ISTATE_OFFSET_O6]
stx %i7, [%sp + STACK_BIAS + ISTATE_OFFSET_O7]
wrpr %l0, 0, %cwp
mov %g2, %sp
ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O0], %i0
ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O1], %i1
ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O2], %i2
ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O3], %i3
ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O4], %i4
ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O5], %i5
ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O6], %i6
ldx [%sp + STACK_BIAS + ISTATE_OFFSET_O7], %i7
0:
.if NOT(\is_syscall)
rdpr %tstate, %g1
andcc %g1, TSTATE_PRIV_BIT, %g0 ! if we are not returning to userspace...,
bnz %xcc, 1f ! ...skip restoring userspace windows
nop
.endif
wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(1), %wstate
wr %g0, ASI_DMMU, %asi
ldxa [VA_SECONDARY_CONTEXT_REG] %asi, %g1
stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi
rd %pc, %g1
flush %g1
rdpr %cwp, %g1
rdpr %otherwin, %g2
sub %g1, %g2, %g3
dec %g3
and %g3, NWINDOWS - 1, %g3
wrpr %g3, 0, %cwp
clr %g4
0: andcc %g7, UWB_ALIGNMENT - 1, %g0 ! alignment check
bz %xcc, 0f ! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill
nop
add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7
ldx [%g7 + L0_OFFSET], %l0
ldx [%g7 + L1_OFFSET], %l1
ldx [%g7 + L2_OFFSET], %l2
ldx [%g7 + L3_OFFSET], %l3
ldx [%g7 + L4_OFFSET], %l4
ldx [%g7 + L5_OFFSET], %l5
ldx [%g7 + L6_OFFSET], %l6
ldx [%g7 + L7_OFFSET], %l7
ldx [%g7 + I0_OFFSET], %i0
ldx [%g7 + I1_OFFSET], %i1
ldx [%g7 + I2_OFFSET], %i2
ldx [%g7 + I3_OFFSET], %i3
ldx [%g7 + I4_OFFSET], %i4
ldx [%g7 + I5_OFFSET], %i5
ldx [%g7 + I6_OFFSET], %i6
ldx [%g7 + I7_OFFSET], %i7
dec %g3
and %g3, NWINDOWS - 1, %g3
wrpr %g3, 0, %cwp ! switch to the preceeding window
ba %xcc, 0b
inc %g4
0:
wrpr %g1, 0, %cwp
add %g4, %g2, %g2
cmp %g2, NWINDOWS - 2
bg %xcc, 2f ! fix the CANRESTORE=NWINDOWS-1 anomaly
mov NWINDOWS - 2, %g1 ! use dealy slot for both cases
sub %g1, %g2, %g1
wrpr %g0, 0, %otherwin
wrpr %g1, 0, %cansave ! NWINDOWS - 2 - CANRESTORE
wrpr %g2, 0, %canrestore ! OTHERWIN + windows in the buffer
wrpr %g2, 0, %cleanwin ! avoid information leak
1:
restore
.if \is_syscall
done
.else
retry
.endif
2:
wrpr %g0, 0, %otherwin
wrpr %g0, 0, %cansave
wrpr %g1, 0, %canrestore
wrpr %g1, 0, %cleanwin
rdpr %cwp, %g1
dec %g1
and %g1, NWINDOWS - 1, %g1
wrpr %g1, 0, %cwp ! CWP--
.if \is_syscall
done
.else
retry
.endif
.endm
SYMBOL(preemptible_handler)
PREEMPTIBLE_HANDLER_TEMPLATE 0
SYMBOL(trap_instruction_handler)
PREEMPTIBLE_HANDLER_TEMPLATE 1
HelenOS homepage, sources at GitHub