190 lines
3.8 KiB
ArmAsm
190 lines
3.8 KiB
ArmAsm
/*
|
|
** hypervisor:kernel - low level world manipulation
|
|
*/
|
|
.section .gint.mapped, "ax"
|
|
.align 2
|
|
|
|
.global _hypervisor_kernel_abi
|
|
.global _hypervisor_kernel_world_switch
|
|
|
|
/* hypervisor_kernel_abi(): Kernel ABI entry */
|
|
_hypervisor_kernel_abi:
|
|
/* check trapa validity */
|
|
mov.l abi_trapa_reg, r1
|
|
mov.l @r1, r1
|
|
shlr2 r1
|
|
mov #1, r2
|
|
cmp/hi r1, r2
|
|
bf abi_error
|
|
|
|
/* involve syscall if possible */
|
|
shll2 r1
|
|
mova abi_syscall_table, r0
|
|
mov.l @(r0, r1), r3
|
|
tst r3, r3
|
|
bt abi_error
|
|
jmp @r3
|
|
nop
|
|
|
|
/* error handling */
|
|
abi_error:
|
|
mov #-1, r0
|
|
ldc r0, R0_BANK
|
|
rte
|
|
nop
|
|
|
|
.align 4
|
|
abi_trapa_reg:
|
|
.long 0xff000020
|
|
abi_syscall_table:
|
|
.long _hypervisor_kernel_world_switch
|
|
.long 0x00000000 ! _hypervisor_kernel_schedule
|
|
|
|
|
|
|
|
/* hypervisor world_switch(struct hworld *world): Performs a world switch
|
|
|
|
This hypervisor call will check the world validity then it will save the
|
|
current world environment information, install the new world then perform
|
|
an world switch. */
|
|
_hypervisor_kernel_world_switch:
|
|
/* enable exception but block all interruption */
|
|
mov.l sr_ws_config, r0
|
|
stc sr, r1
|
|
or r0, r1
|
|
ldc r1, sr
|
|
|
|
/* check potential error */
|
|
stc R4_BANK, r4
|
|
tst r4, r4
|
|
bt kernel_world_error
|
|
mov.l hypervisor_world_current, r5
|
|
mov.l @r5, r5
|
|
tst r5, r5
|
|
bt kernel_world_error
|
|
|
|
/* switch stack (user -> kernel) */
|
|
mov.l r15, @r5
|
|
mov.l @(4, r5), r15
|
|
|
|
/* save the current context */
|
|
sts.l pr, @-r15
|
|
mov.l r4, @-r15
|
|
mov.l r5, @-r15
|
|
mov.l drivers_context_save, r0
|
|
jsr @r0
|
|
mov.l @(8, r5), r4
|
|
mov.l @r15+, r5
|
|
mov.l @r15+, r4
|
|
lds.l @r15+, pr
|
|
|
|
/* switch stack (kernel -> user) */
|
|
mov.l r15, @(4, r5)
|
|
mov.l @r5, r15
|
|
|
|
/* save cpu context */
|
|
add #100, r5
|
|
sts.l pr, @-r5
|
|
stc.l spc, @-r5
|
|
stc.l ssr, @-r5
|
|
sts.l mach, @-r5
|
|
sts.l macl, @-r5
|
|
stc.l gbr, @-r5
|
|
mov.l r15, @-r5
|
|
mov.l r14, @-r5
|
|
mov.l r13, @-r5
|
|
mov.l r12, @-r5
|
|
mov.l r11, @-r5
|
|
mov.l r10, @-r5
|
|
mov.l r9, @-r5
|
|
mov.l r8, @-r5
|
|
stc.l R7_BANK, @-r5
|
|
stc.l R6_BANK, @-r5
|
|
stc.l R5_BANK, @-r5
|
|
stc.l R4_BANK, @-r5
|
|
stc.l R3_BANK, @-r5
|
|
stc.l R2_BANK, @-r5
|
|
stc.l R1_BANK, @-r5
|
|
stc.l R0_BANK, @-r5
|
|
|
|
/* restore cpu context */
|
|
add #12, r4
|
|
ldc.l @r4+, R0_BANK
|
|
ldc.l @r4+, R1_BANK
|
|
ldc.l @r4+, R2_BANK
|
|
ldc.l @r4+, R3_BANK
|
|
ldc.l @r4+, R4_BANK
|
|
ldc.l @r4+, R5_BANK
|
|
ldc.l @r4+, R6_BANK
|
|
ldc.l @r4+, R7_BANK
|
|
mov.l @r4+, r8
|
|
mov.l @r4+, r9
|
|
mov.l @r4+, r10
|
|
mov.l @r4+, r11
|
|
mov.l @r4+, r12
|
|
mov.l @r4+, r13
|
|
mov.l @r4+, r14
|
|
mov.l @r4+, r15
|
|
ldc.l @r4+, gbr
|
|
lds.l @r4+, macl
|
|
lds.l @r4+, mach
|
|
ldc.l @r4+, ssr
|
|
ldc.l @r4+, spc
|
|
lds.l @r4+, pr
|
|
|
|
/* switch stack (user -> kernel) */
|
|
add #-100, r4
|
|
mov.l r15, @r4
|
|
mov.l @(4, r4), r15
|
|
|
|
/* indicate that the world has changed */
|
|
mov.l hypervisor_world_current, r0
|
|
mov.l r4, @r0
|
|
|
|
/* save the current context
|
|
Note that the SR register can be restored. So, interruption /
|
|
exceptions can occur during this lack of time between JSR and the
|
|
resotoration of the SR register. */
|
|
stc.l ssr, @-r15
|
|
stc.l spc, @-r15
|
|
sts.l pr, @-r15
|
|
mov.l r4, @-r15
|
|
stc.l sr, @-r15
|
|
mov.l drivers_context_restore, r0
|
|
jsr @r0
|
|
mov.l @(8, r4), r4
|
|
ldc.l @r15+, sr
|
|
mov.l @r15+, r4
|
|
lds.l @r15+, pr
|
|
ldc.l @r15+, spc
|
|
ldc.l @r15+, ssr
|
|
|
|
/* switch stack (kernel -> user) */
|
|
mov.l r15, @(4, r4)
|
|
mov.l @r4, r15
|
|
|
|
/* force hypervisor VBR re-installation, because it possible that the
|
|
VBR has been changed during the handler */
|
|
mov.l hypervisor_vbr_redirect, r0
|
|
mov.l hypervisor_vbr, r1
|
|
stc vbr, r2
|
|
mov.l r2, @r0
|
|
ldc.l @r1+, vbr
|
|
|
|
/* perform the world switch */
|
|
rte
|
|
nop
|
|
|
|
kernel_world_error:
|
|
rts
|
|
mov #-2, r0
|
|
|
|
.align 4
|
|
sr_ws_config: .long 0x600000f0
|
|
!wswitch_debug: .long _wswitch_debug
|
|
hypervisor_vbr: .long _hypervisor_vbr
|
|
hypervisor_vbr_redirect: .long _hypervisor_vbr_redirect
|
|
hypervisor_world_current: .long _hypervisor_world_current
|
|
drivers_context_save: .long _drivers_save
|
|
drivers_context_restore: .long _drivers_restore
|