| /* SPDX-License-Identifier: GPL-2.0 */ |
| /* |
| * Copyright (C) 2018 - os kernal |
| * Author: fire3 <fire3@example.com> |
| */ |
| .text |
| #include <linux/linkage.h> |
| #include <asm/asm-offsets.h> |
| #include <asm/page.h> |
| #include <asm/regdef.h> |
| |
| .set noat |
| |
| ENTRY(__sw64_vcpu_run) |
| |
| /* save host fpregs */ |
| ldl $1, TI_TASK($8) |
| rfpcr $f0 |
| fstd $f0, TASK_THREAD_FPCR($1) |
| vstd $f2, TASK_THREAD_F2($1) |
| vstd $f3, TASK_THREAD_F3($1) |
| vstd $f4, TASK_THREAD_F4($1) |
| vstd $f5, TASK_THREAD_F5($1) |
| vstd $f6, TASK_THREAD_F6($1) |
| vstd $f7, TASK_THREAD_F7($1) |
| vstd $f8, TASK_THREAD_F8($1) |
| vstd $f9, TASK_THREAD_F9($1) |
| |
| ldi sp, -VCPU_RET_SIZE(sp) |
| /* r16 = guest kvm_vcpu_arch.vcb struct pointer */ |
| /* r17 = guest kvm_vcpu_arch.kvm_regs struct pointer */ |
| /* r18 = hcall args */ |
| /* save host pt_regs to current kernel stack */ |
| ldi sp, -PT_REGS_SIZE(sp) |
| stl $9, PT_REGS_R9(sp) |
| stl $10, PT_REGS_R10(sp) |
| stl $11, PT_REGS_R11(sp) |
| stl $12, PT_REGS_R12(sp) |
| stl $13, PT_REGS_R13(sp) |
| stl $14, PT_REGS_R14(sp) |
| stl $15, PT_REGS_R15(sp) |
| stl $26, PT_REGS_R26(sp) |
| |
| /* restore guest switch stack from guest kvm_regs struct */ |
| ldl $0, KVM_REGS_R0($17) |
| ldl $1, KVM_REGS_R1($17) |
| /* restore $2 later */ |
| ldl $3, KVM_REGS_R3($17) |
| ldl $4, KVM_REGS_R4($17) |
| ldl $5, KVM_REGS_R5($17) |
| ldl $6, KVM_REGS_R6($17) |
| ldl $7, KVM_REGS_R7($17) |
| ldl $8, KVM_REGS_R8($17) |
| ldl $9, KVM_REGS_R9($17) |
| ldl $10, KVM_REGS_R10($17) |
| ldl $11, KVM_REGS_R11($17) |
| ldl $12, KVM_REGS_R12($17) |
| ldl $13, KVM_REGS_R13($17) |
| ldl $14, KVM_REGS_R14($17) |
| ldl $15, KVM_REGS_R15($17) |
| ldl $19, KVM_REGS_R19($17) |
| ldl $20, KVM_REGS_R20($17) |
| ldl $21, KVM_REGS_R21($17) |
| ldl $22, KVM_REGS_R22($17) |
| ldl $23, KVM_REGS_R23($17) |
| ldl $24, KVM_REGS_R24($17) |
| ldl $25, KVM_REGS_R25($17) |
| ldl $26, KVM_REGS_R26($17) |
| ldl $27, KVM_REGS_R27($17) |
| ldl $28, KVM_REGS_R28($17) |
| |
| fldd $f0, KVM_REGS_FPCR($17) |
| wfpcr $f0 |
| fimovd $f0, $2 |
| and $2, 0x3, $2 |
| beq $2, $g_setfpec_0 |
| subl $2, 0x1, $2 |
| beq $2, $g_setfpec_1 |
| subl $2, 0x1, $2 |
| beq $2, $g_setfpec_2 |
| setfpec3 |
| br $g_setfpec_over |
| $g_setfpec_0: |
| setfpec0 |
| br $g_setfpec_over |
| $g_setfpec_1: |
| setfpec1 |
| br $g_setfpec_over |
| $g_setfpec_2: |
| setfpec2 |
| $g_setfpec_over: |
| ldl $2, KVM_REGS_R2($17) |
| vldd $f0, KVM_REGS_F0($17) |
| vldd $f1, KVM_REGS_F1($17) |
| vldd $f2, KVM_REGS_F2($17) |
| vldd $f3, KVM_REGS_F3($17) |
| vldd $f4, KVM_REGS_F4($17) |
| vldd $f5, KVM_REGS_F5($17) |
| vldd $f6, KVM_REGS_F6($17) |
| vldd $f7, KVM_REGS_F7($17) |
| vldd $f8, KVM_REGS_F8($17) |
| vldd $f9, KVM_REGS_F9($17) |
| vldd $f10, KVM_REGS_F10($17) |
| vldd $f11, KVM_REGS_F11($17) |
| vldd $f12, KVM_REGS_F12($17) |
| vldd $f13, KVM_REGS_F13($17) |
| vldd $f14, KVM_REGS_F14($17) |
| vldd $f15, KVM_REGS_F15($17) |
| vldd $f16, KVM_REGS_F16($17) |
| vldd $f17, KVM_REGS_F17($17) |
| vldd $f18, KVM_REGS_F18($17) |
| vldd $f19, KVM_REGS_F19($17) |
| vldd $f20, KVM_REGS_F20($17) |
| vldd $f21, KVM_REGS_F21($17) |
| vldd $f22, KVM_REGS_F22($17) |
| vldd $f23, KVM_REGS_F23($17) |
| vldd $f24, KVM_REGS_F24($17) |
| vldd $f25, KVM_REGS_F25($17) |
| vldd $f26, KVM_REGS_F26($17) |
| vldd $f27, KVM_REGS_F27($17) |
| vldd $f28, KVM_REGS_F28($17) |
| vldd $f29, KVM_REGS_F29($17) |
| vldd $f30, KVM_REGS_F30($17) |
| |
| ldi $17, KVM_REGS_PS($17) |
| |
| /* enter guest */ |
| /* r16 = guest vcpucb pointer */ |
| /* r17 = base of guest kvm_regs.ps, saved/restored by hmcode */ |
| |
| /* enter guest now */ |
| sys_call 0x31 |
| /* exit guest now */ |
| |
| ldi $17, -KVM_REGS_PS($17) /* r17: base of kvm_regs */ |
| |
| vstd $f0, KVM_REGS_F0($17) |
| vstd $f1, KVM_REGS_F1($17) |
| vstd $f2, KVM_REGS_F2($17) |
| vstd $f3, KVM_REGS_F3($17) |
| vstd $f4, KVM_REGS_F4($17) |
| vstd $f5, KVM_REGS_F5($17) |
| vstd $f6, KVM_REGS_F6($17) |
| vstd $f7, KVM_REGS_F7($17) |
| vstd $f8, KVM_REGS_F8($17) |
| vstd $f9, KVM_REGS_F9($17) |
| vstd $f10, KVM_REGS_F10($17) |
| vstd $f11, KVM_REGS_F11($17) |
| vstd $f12, KVM_REGS_F12($17) |
| vstd $f13, KVM_REGS_F13($17) |
| vstd $f14, KVM_REGS_F14($17) |
| vstd $f15, KVM_REGS_F15($17) |
| vstd $f16, KVM_REGS_F16($17) |
| vstd $f17, KVM_REGS_F17($17) |
| vstd $f18, KVM_REGS_F18($17) |
| vstd $f19, KVM_REGS_F19($17) |
| vstd $f20, KVM_REGS_F20($17) |
| vstd $f21, KVM_REGS_F21($17) |
| vstd $f22, KVM_REGS_F22($17) |
| vstd $f23, KVM_REGS_F23($17) |
| vstd $f24, KVM_REGS_F24($17) |
| vstd $f25, KVM_REGS_F25($17) |
| vstd $f26, KVM_REGS_F26($17) |
| vstd $f27, KVM_REGS_F27($17) |
| vstd $f28, KVM_REGS_F28($17) |
| vstd $f29, KVM_REGS_F29($17) |
| vstd $f30, KVM_REGS_F30($17) |
| |
| rfpcr $f0 |
| fstd $f0, KVM_REGS_FPCR($17) |
| |
| /* don't save r0 Hmcode have saved r0 for us */ |
| stl $1, KVM_REGS_R1($17) |
| stl $2, KVM_REGS_R2($17) |
| stl $3, KVM_REGS_R3($17) |
| stl $4, KVM_REGS_R4($17) |
| stl $5, KVM_REGS_R5($17) |
| stl $6, KVM_REGS_R6($17) |
| stl $7, KVM_REGS_R7($17) |
| stl $8, KVM_REGS_R8($17) |
| stl $9, KVM_REGS_R9($17) |
| stl $10, KVM_REGS_R10($17) |
| stl $11, KVM_REGS_R11($17) |
| stl $12, KVM_REGS_R12($17) |
| stl $13, KVM_REGS_R13($17) |
| stl $14, KVM_REGS_R14($17) |
| stl $15, KVM_REGS_R15($17) |
| stl $19, KVM_REGS_R19($17) |
| stl $20, KVM_REGS_R20($17) |
| stl $21, KVM_REGS_R21($17) |
| stl $22, KVM_REGS_R22($17) |
| stl $23, KVM_REGS_R23($17) |
| stl $24, KVM_REGS_R24($17) |
| stl $25, KVM_REGS_R25($17) |
| stl $26, KVM_REGS_R26($17) |
| stl $27, KVM_REGS_R27($17) |
| stl $28, KVM_REGS_R28($17) |
| |
| /* restore host regs from host sp */ |
| ldl $9, PT_REGS_R9(sp) |
| ldl $10, PT_REGS_R10(sp) |
| ldl $11, PT_REGS_R11(sp) |
| ldl $12, PT_REGS_R12(sp) |
| ldl $13, PT_REGS_R13(sp) |
| ldl $14, PT_REGS_R14(sp) |
| ldl $15, PT_REGS_R15(sp) |
| ldl $26, PT_REGS_R26(sp) |
| ldi sp, PT_REGS_SIZE(sp) |
| |
| ldi $8, 0x3fff |
| bic sp, $8, $8 |
| /* restore host fpregs */ |
| ldl $1, TI_TASK($8) |
| fldd $f0, TASK_THREAD_FPCR($1) |
| wfpcr $f0 |
| fimovd $f0, $2 |
| and $2, 0x3, $2 |
| beq $2, $setfpec_0 |
| subl $2, 0x1, $2 |
| beq $2, $setfpec_1 |
| subl $2, 0x1, $2 |
| beq $2, $setfpec_2 |
| setfpec3 |
| br $setfpec_over |
| $setfpec_0: |
| setfpec0 |
| br $setfpec_over |
| $setfpec_1: |
| setfpec1 |
| br $setfpec_over |
| $setfpec_2: |
| setfpec2 |
| $setfpec_over: |
| vldd $f2, TASK_THREAD_F2($1) |
| vldd $f3, TASK_THREAD_F3($1) |
| vldd $f4, TASK_THREAD_F4($1) |
| vldd $f5, TASK_THREAD_F5($1) |
| vldd $f6, TASK_THREAD_F6($1) |
| vldd $f7, TASK_THREAD_F7($1) |
| vldd $f8, TASK_THREAD_F8($1) |
| vldd $f9, TASK_THREAD_F9($1) |
| |
| /* if $0 > 0, handle hcall */ |
| bgt $0, $ret_to |
| |
| stl $26, VCPU_RET_RA(sp) |
| stl $0, VCPU_RET_R0(sp) |
| |
| /* Hmcode will setup in */ |
| /* restore $16 $17 $18, do interrupt trick */ |
| ldi sp, -(HOST_INT_SIZE + PT_REGS_SIZE)(sp) |
| ldl $16, HOST_INT_R16(sp) |
| ldl $17, HOST_INT_R17(sp) |
| ldl $18, HOST_INT_R18(sp) |
| ldi sp, (HOST_INT_SIZE + PT_REGS_SIZE)(sp) |
| |
| ldi $19, -PT_REGS_SIZE(sp) |
| call $26, do_entInt |
| ldl $26, VCPU_RET_RA(sp) |
| ldl $0, VCPU_RET_R0(sp) |
| $ret_to: |
| /* ret($0) indicate hcall number */ |
| ldi sp, VCPU_RET_SIZE(sp) /* pop stack */ |
| ret |