.macro kvm_save_host_gpr base
.irp n,1,2,3,22,23,24,25,26,27,28,29,30,31
st.d $r\n, \base, HGPR_OFFSET(\n)
.endr
.endm
.macro kvm_restore_host_gpr base
.irp n,1,2,3,22,23,24,25,26,27,28,29,30,31
ld.d $r\n, \base, HGPR_OFFSET(\n)
.endr
.endm
.macro kvm_save_guest_gprs base
.irp n,1,2,3,4,5,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
st.d $r\n, \base, GGPR_OFFSET(\n)
.endr
.endm
.macro kvm_restore_guest_gprs base
.irp n,1,2,3,4,5,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
ld.d $r\n, \base, GGPR_OFFSET(\n)
.endr
.endm
.macro kvm_switch_to_guest
csrrd t0, LOONGARCH_CSR_ECFG
bstrins.w t0, zero, CSR_ECFG_VS_SHIFT_END, CSR_ECFG_VS_SHIFT
csrwr t0, LOONGARCH_CSR_ECFG
ld.d t0, a2, KVM_ARCH_GEENTRY
csrwr t0, LOONGARCH_CSR_EENTRY
ld.d t0, a2, KVM_ARCH_GPC
csrwr t0, LOONGARCH_CSR_ERA
ld.d t0, a2, KVM_ARCH_KVMPGD
csrwr t0, LOONGARCH_CSR_PGDL
csrrd t1, LOONGARCH_CSR_GSTAT
bstrpick.w t1, t1, CSR_GSTAT_GID_SHIFT_END, CSR_GSTAT_GID_SHIFT
csrrd t0, LOONGARCH_CSR_GTLBC
bstrins.w t0, t1, CSR_GTLBC_TGID_SHIFT_END, CSR_GTLBC_TGID_SHIFT
csrwr t0, LOONGARCH_CSR_GTLBC
ori t0, zero, CSR_PRMD_PIE
csrwr t0, LOONGARCH_CSR_PRMD
ori t0, zero, CSR_GSTAT_PVM
csrxchg t0, t0, LOONGARCH_CSR_GSTAT
kvm_restore_guest_gprs a2
ld.d a2, a2, (KVM_ARCH_GGPR + 8 * REG_A2)
ertn
.endm
.text
.cfi_sections .debug_frame
SYM_CODE_START(kvm_exc_entry)
UNWIND_HINT_UNDEFINED
csrwr a2, KVM_TEMP_KS
csrrd a2, KVM_VCPU_KS
addi.d a2, a2, KVM_VCPU_ARCH
kvm_save_guest_gprs a2
csrrd t0, KVM_TEMP_KS
st.d t0, a2, (KVM_ARCH_GGPR + 8 * REG_A2)
csrrd s1, KVM_VCPU_KS
ld.d s0, s1, KVM_VCPU_RUN
csrrd t0, LOONGARCH_CSR_ESTAT
st.d t0, a2, KVM_ARCH_HESTAT
csrrd t0, LOONGARCH_CSR_ERA
st.d t0, a2, KVM_ARCH_GPC
csrrd t0, LOONGARCH_CSR_BADV
st.d t0, a2, KVM_ARCH_HBADV
csrrd t0, LOONGARCH_CSR_BADI
st.d t0, a2, KVM_ARCH_HBADI
csrrd t0, LOONGARCH_CSR_ECFG
ld.d t1, a2, KVM_ARCH_HECFG
or t0, t0, t1
csrwr t0, LOONGARCH_CSR_ECFG
ld.d t0, a2, KVM_ARCH_HEENTRY
csrwr t0, LOONGARCH_CSR_EENTRY
ld.d t0, a2, KVM_ARCH_HPGD
csrwr t0, LOONGARCH_CSR_PGDL
ori t0, zero, CSR_GSTAT_PVM
csrxchg zero, t0, LOONGARCH_CSR_GSTAT
csrrd t0, LOONGARCH_CSR_GTLBC
bstrins.w t0, zero, CSR_GTLBC_TGID_SHIFT_END, CSR_GTLBC_TGID_SHIFT
csrwr t0, LOONGARCH_CSR_GTLBC
ld.d tp, a2, KVM_ARCH_HTP
ld.d sp, a2, KVM_ARCH_HSP
ld.d u0, a2, KVM_ARCH_HPERCPU
addi.d sp, sp, -PT_SIZE
or a0, s0, zero
or a1, s1, zero
ld.d t8, a2, KVM_ARCH_HANDLE_EXIT
jirl ra, t8, 0
or a2, s1, zero
addi.d a2, a2, KVM_VCPU_ARCH
blez a0, ret_to_host
st.d u0, a2, KVM_ARCH_HPERCPU
csrwr s1, KVM_VCPU_KS
kvm_switch_to_guest
ret_to_host:
ld.d a2, a2, KVM_ARCH_HSP
addi.d a2, a2, -PT_SIZE
kvm_restore_host_gpr a2
jr ra
SYM_INNER_LABEL(kvm_exc_entry_end, SYM_L_LOCAL)
SYM_CODE_END(kvm_exc_entry)
SYM_FUNC_START(kvm_enter_guest)
addi.d a2, sp, -PT_SIZE
kvm_save_host_gpr a2
addi.d a2, a1, KVM_VCPU_ARCH
st.d sp, a2, KVM_ARCH_HSP
st.d tp, a2, KVM_ARCH_HTP
st.d u0, a2, KVM_ARCH_HPERCPU
csrwr a1, KVM_VCPU_KS
kvm_switch_to_guest
SYM_INNER_LABEL(kvm_enter_guest_end, SYM_L_LOCAL)
SYM_FUNC_END(kvm_enter_guest)
SYM_FUNC_START(kvm_save_fpu)
fpu_save_csr a0 t1
fpu_save_double a0 t1
fpu_save_cc a0 t1 t2
jr ra
SYM_FUNC_END(kvm_save_fpu)
SYM_FUNC_START(kvm_restore_fpu)
fpu_restore_double a0 t1
fpu_restore_csr a0 t1 t2
fpu_restore_cc a0 t1 t2
jr ra
SYM_FUNC_END(kvm_restore_fpu)
SYM_FUNC_START(kvm_save_lsx)
fpu_save_csr a0 t1
fpu_save_cc a0 t1 t2
lsx_save_data a0 t1
jr ra
SYM_FUNC_END(kvm_save_lsx)
SYM_FUNC_START(kvm_restore_lsx)
lsx_restore_data a0 t1
fpu_restore_cc a0 t1 t2
fpu_restore_csr a0 t1 t2
jr ra
SYM_FUNC_END(kvm_restore_lsx)
SYM_FUNC_START(kvm_save_lasx)
fpu_save_csr a0 t1
fpu_save_cc a0 t1 t2
lasx_save_data a0 t1
jr ra
SYM_FUNC_END(kvm_save_lasx)
SYM_FUNC_START(kvm_restore_lasx)
lasx_restore_data a0 t1
fpu_restore_cc a0 t1 t2
fpu_restore_csr a0 t1 t2
jr ra
SYM_FUNC_END(kvm_restore_lasx)
.section ".rodata"
SYM_DATA(kvm_exception_size, .quad kvm_exc_entry_end - kvm_exc_entry)
SYM_DATA(kvm_enter_guest_size, .quad kvm_enter_guest_end - kvm_enter_guest)
STACK_FRAME_NON_STANDARD kvm_restore_fpu
STACK_FRAME_NON_STANDARD kvm_restore_lsx
STACK_FRAME_NON_STANDARD kvm_restore_lasx