#include <sys/elf_common.h>
#include <machine/asm.h>
#include <machine/hypervisor.h>
#include "assym.inc"
#include "hyp.h"
.macro save_host_registers
sub sp, sp, #(32 * 8)
str x30, [sp, #(30 * 8)]
stp x28, x29, [sp, #(28 * 8)]
stp x26, x27, [sp, #(26 * 8)]
stp x24, x25, [sp, #(24 * 8)]
stp x22, x23, [sp, #(22 * 8)]
stp x20, x21, [sp, #(20 * 8)]
stp x18, x19, [sp, #(18 * 8)]
stp x16, x17, [sp, #(16 * 8)]
stp x14, x15, [sp, #(14 * 8)]
stp x12, x13, [sp, #(12 * 8)]
stp x10, x11, [sp, #(10 * 8)]
stp x8, x9, [sp, #(8 * 8)]
stp x6, x7, [sp, #(6 * 8)]
stp x4, x5, [sp, #(4 * 8)]
stp x2, x3, [sp, #(2 * 8)]
stp x0, x1, [sp, #(0 * 8)]
.endm
.macro restore_host_registers
ldp x0, x1, [sp, #(0 * 8)]
ldp x2, x3, [sp, #(2 * 8)]
ldp x4, x5, [sp, #(4 * 8)]
ldp x6, x7, [sp, #(6 * 8)]
ldp x8, x9, [sp, #(8 * 8)]
ldp x10, x11, [sp, #(10 * 8)]
ldp x12, x13, [sp, #(12 * 8)]
ldp x14, x15, [sp, #(14 * 8)]
ldp x16, x17, [sp, #(16 * 8)]
ldp x18, x19, [sp, #(18 * 8)]
ldp x20, x21, [sp, #(20 * 8)]
ldp x22, x23, [sp, #(22 * 8)]
ldp x24, x25, [sp, #(24 * 8)]
ldp x26, x27, [sp, #(26 * 8)]
ldp x28, x29, [sp, #(28 * 8)]
ldr x30, [sp, #(30 * 8)]
add sp, sp, #(32 * 8)
.endm
.macro save_guest_registers
stp x0, x1, [sp, #-(2 * 8)]!
mrs x0, tpidr_el2
stp x2, x3, [x0, #(TF_X + 2 * 8)]
stp x4, x5, [x0, #(TF_X + 4 * 8)]
stp x6, x7, [x0, #(TF_X + 6 * 8)]
stp x8, x9, [x0, #(TF_X + 8 * 8)]
stp x10, x11, [x0, #(TF_X + 10 * 8)]
stp x12, x13, [x0, #(TF_X + 12 * 8)]
stp x14, x15, [x0, #(TF_X + 14 * 8)]
stp x16, x17, [x0, #(TF_X + 16 * 8)]
stp x18, x19, [x0, #(TF_X + 18 * 8)]
stp x20, x21, [x0, #(TF_X + 20 * 8)]
stp x22, x23, [x0, #(TF_X + 22 * 8)]
stp x24, x25, [x0, #(TF_X + 24 * 8)]
stp x26, x27, [x0, #(TF_X + 26 * 8)]
stp x28, x29, [x0, #(TF_X + 28 * 8)]
str lr, [x0, #(TF_LR)]
ldp x2, x3, [sp], #(2 * 8)
stp x2, x3, [x0, #(TF_X + 0 * 8)]
.endm
.macro restore_guest_registers
ldp x2, x3, [x0, #(TF_X + 0 * 8)]
stp x2, x3, [sp, #-(2 * 8)]!
ldr lr, [x0, #(TF_LR)]
ldp x28, x29, [x0, #(TF_X + 28 * 8)]
ldp x26, x27, [x0, #(TF_X + 26 * 8)]
ldp x24, x25, [x0, #(TF_X + 24 * 8)]
ldp x22, x23, [x0, #(TF_X + 22 * 8)]
ldp x20, x21, [x0, #(TF_X + 20 * 8)]
ldp x18, x19, [x0, #(TF_X + 18 * 8)]
ldp x16, x17, [x0, #(TF_X + 16 * 8)]
ldp x14, x15, [x0, #(TF_X + 14 * 8)]
ldp x12, x13, [x0, #(TF_X + 12 * 8)]
ldp x10, x11, [x0, #(TF_X + 10 * 8)]
ldp x8, x9, [x0, #(TF_X + 8 * 8)]
ldp x6, x7, [x0, #(TF_X + 6 * 8)]
ldp x4, x5, [x0, #(TF_X + 4 * 8)]
ldp x2, x3, [x0, #(TF_X + 2 * 8)]
ldp x0, x1, [sp], #(2 * 8)
.endm
.macro vempty
.align 7
1: b 1b
.endm
.macro vector name
.align 7
b handle_\name
.endm
.text
.align 11
hyp_vectors:
vempty
vempty
vempty
vempty
vector el2_el2h_sync
vector el2_el2h_irq
vector el2_el2h_fiq
vector el2_el2h_error
vector el2_el1_sync64
vector el2_el1_irq64
vector el2_el1_fiq64
vector el2_el1_error64
vempty
vempty
vempty
vempty
.macro do_world_switch_to_host
save_guest_registers
restore_host_registers
mov x9, #VTTBR_HOST
msr vttbr_el2, x9
#ifdef VMM_VHE
msr vbar_el1, x1
#endif
.endm
.macro handle_el2_excp type
#ifndef VMM_VHE
str x9, [sp, #-16]!
mrs x9, vttbr_el2
cmp x9, #VTTBR_HOST
beq 1f
ldr x9, [sp], #16
#endif
do_world_switch_to_host
mov x0, \type
ret
#ifndef VMM_VHE
1:
ldr x9, [sp], #16
mov x0, \type
ERET
#endif
.endm
LENTRY(handle_el2_el2h_sync)
handle_el2_excp #EXCP_TYPE_EL2_SYNC
LEND(handle_el2_el2h_sync)
LENTRY(handle_el2_el2h_irq)
handle_el2_excp #EXCP_TYPE_EL2_IRQ
LEND(handle_el2_el2h_irq)
LENTRY(handle_el2_el2h_fiq)
handle_el2_excp #EXCP_TYPE_EL2_FIQ
LEND(handle_el2_el2h_fiq)
LENTRY(handle_el2_el2h_error)
handle_el2_excp #EXCP_TYPE_EL2_ERROR
LEND(handle_el2_el2h_error)
LENTRY(handle_el2_el1_sync64)
#ifndef VMM_VHE
str x9, [sp, #-16]!
mrs x9, vttbr_el2
cmp x9, #VTTBR_HOST
ldr x9, [sp], #16
bne 1f
cmp x0, #(HYP_CLEANUP)
b.eq vmm_cleanup
str lr, [sp, #-16]!
bl vmm_hyp_enter
ldr lr, [sp], #16
ERET
1:
#endif
do_world_switch_to_host
mov x0, #EXCP_TYPE_EL1_SYNC
ret
LEND(handle_el2_el1_sync64)
LENTRY(handle_el2_el1_irq64)
do_world_switch_to_host
str x9, [sp, #-16]!
mrs x9, ich_misr_el2
cmp x9, xzr
beq 1f
mov x0, #EXCP_TYPE_MAINT_IRQ
b 2f
1:
mov x0, #EXCP_TYPE_EL1_IRQ
2:
ldr x9, [sp], #16
ret
LEND(handle_el2_el1_irq64)
LENTRY(handle_el2_el1_fiq64)
do_world_switch_to_host
mov x0, #EXCP_TYPE_EL1_FIQ
ret
LEND(handle_el2_el1_fiq64)
LENTRY(handle_el2_el1_error64)
do_world_switch_to_host
mov x0, #EXCP_TYPE_EL1_ERROR
ret
LEND(handle_el2_el1_error64)
ENTRY(VMM_HYP_FUNC(do_call_guest))
#ifdef VMM_VHE
mrs x1, vbar_el1
adrp x2, hyp_vectors
add x2, x2, :lo12:hyp_vectors
msr vbar_el1, x2
isb
#endif
msr tpidr_el2, x0
save_host_registers
restore_guest_registers
ERET
END(VMM_HYP_FUNC(do_call_guest))
GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(GNU_PROPERTY_AARCH64_FEATURE_1_VAL)