12b28162cSMarc Zyngier/* 22b28162cSMarc Zyngier * Copyright (C) 2015 - ARM Ltd 32b28162cSMarc Zyngier * Author: Marc Zyngier <marc.zyngier@arm.com> 42b28162cSMarc Zyngier * 52b28162cSMarc Zyngier * This program is free software; you can redistribute it and/or modify 62b28162cSMarc Zyngier * it under the terms of the GNU General Public License version 2 as 72b28162cSMarc Zyngier * published by the Free Software Foundation. 82b28162cSMarc Zyngier * 92b28162cSMarc Zyngier * This program is distributed in the hope that it will be useful, 102b28162cSMarc Zyngier * but WITHOUT ANY WARRANTY; without even the implied warranty of 112b28162cSMarc Zyngier * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 122b28162cSMarc Zyngier * GNU General Public License for more details. 132b28162cSMarc Zyngier * 142b28162cSMarc Zyngier * You should have received a copy of the GNU General Public License 152b28162cSMarc Zyngier * along with this program. If not, see <http://www.gnu.org/licenses/>. 162b28162cSMarc Zyngier */ 172b28162cSMarc Zyngier 182b28162cSMarc Zyngier#include <linux/linkage.h> 192b28162cSMarc Zyngier 202b28162cSMarc Zyngier#include <asm/alternative.h> 212b28162cSMarc Zyngier#include <asm/assembler.h> 222b28162cSMarc Zyngier#include <asm/cpufeature.h> 232b28162cSMarc Zyngier#include <asm/kvm_arm.h> 242b28162cSMarc Zyngier#include <asm/kvm_asm.h> 252b28162cSMarc Zyngier#include <asm/kvm_mmu.h> 262b28162cSMarc Zyngier 272b28162cSMarc Zyngier .text 282b28162cSMarc Zyngier .pushsection .hyp.text, "ax" 292b28162cSMarc Zyngier 30b81125c7SMarc Zyngier.macro do_el2_call 31b81125c7SMarc Zyngier /* 32b81125c7SMarc Zyngier * Shuffle the parameters before calling the function 33b81125c7SMarc Zyngier * pointed to in x0. Assumes parameters in x[1,2,3]. 34b81125c7SMarc Zyngier */ 356c9ae25dSMarc Zyngier str lr, [sp, #-16]! 36b81125c7SMarc Zyngier mov lr, x0 37b81125c7SMarc Zyngier mov x0, x1 38b81125c7SMarc Zyngier mov x1, x2 39b81125c7SMarc Zyngier mov x2, x3 40b81125c7SMarc Zyngier blr lr 416c9ae25dSMarc Zyngier ldr lr, [sp], #16 42b81125c7SMarc Zyngier.endm 43b81125c7SMarc Zyngier 44b81125c7SMarc ZyngierENTRY(__vhe_hyp_call) 45b81125c7SMarc Zyngier do_el2_call 46b81125c7SMarc Zyngier /* 47b81125c7SMarc Zyngier * We used to rely on having an exception return to get 48b81125c7SMarc Zyngier * an implicit isb. In the E2H case, we don't have it anymore. 49b81125c7SMarc Zyngier * rather than changing all the leaf functions, just do it here 50b81125c7SMarc Zyngier * before returning to the rest of the kernel. 51b81125c7SMarc Zyngier */ 52b81125c7SMarc Zyngier isb 53b81125c7SMarc Zyngier ret 54b81125c7SMarc ZyngierENDPROC(__vhe_hyp_call) 553421e9d8SMarc Zyngier 562b28162cSMarc Zyngierel1_sync: // Guest trapped into EL2 5768381b2bSShanker Donthineni stp x0, x1, [sp, #-16]! 582b28162cSMarc Zyngier 595f05a72aSMarc Zyngieralternative_if_not ARM64_HAS_VIRT_HOST_EXTN 602b28162cSMarc Zyngier mrs x1, esr_el2 615f05a72aSMarc Zyngieralternative_else 625f05a72aSMarc Zyngier mrs x1, esr_el1 635f05a72aSMarc Zyngieralternative_endif 6468381b2bSShanker Donthineni lsr x0, x1, #ESR_ELx_EC_SHIFT 652b28162cSMarc Zyngier 6668381b2bSShanker Donthineni cmp x0, #ESR_ELx_EC_HVC64 672b28162cSMarc Zyngier b.ne el1_trap 682b28162cSMarc Zyngier 6968381b2bSShanker Donthineni mrs x1, vttbr_el2 // If vttbr is valid, the 64bit guest 7068381b2bSShanker Donthineni cbnz x1, el1_trap // called HVC 712b28162cSMarc Zyngier 722b28162cSMarc Zyngier /* Here, we're pretty sure the host called HVC. */ 7368381b2bSShanker Donthineni ldp x0, x1, [sp], #16 742b28162cSMarc Zyngier 755fbe9a59SMarc Zyngier /* Check for a stub HVC call */ 765fbe9a59SMarc Zyngier cmp x0, #HVC_STUB_HCALL_NR 775fbe9a59SMarc Zyngier b.hs 1f 785fbe9a59SMarc Zyngier 795fbe9a59SMarc Zyngier /* 805fbe9a59SMarc Zyngier * Compute the idmap address of __kvm_handle_stub_hvc and 815fbe9a59SMarc Zyngier * jump there. Since we use kimage_voffset, do not use the 825fbe9a59SMarc Zyngier * HYP VA for __kvm_handle_stub_hvc, but the kernel VA instead 835fbe9a59SMarc Zyngier * (by loading it from the constant pool). 845fbe9a59SMarc Zyngier * 855fbe9a59SMarc Zyngier * Preserve x0-x4, which may contain stub parameters. 865fbe9a59SMarc Zyngier */ 875fbe9a59SMarc Zyngier ldr x5, =__kvm_handle_stub_hvc 885fbe9a59SMarc Zyngier ldr_l x6, kimage_voffset 895fbe9a59SMarc Zyngier 905fbe9a59SMarc Zyngier /* x5 = __pa(x5) */ 915fbe9a59SMarc Zyngier sub x5, x5, x6 925fbe9a59SMarc Zyngier br x5 932b28162cSMarc Zyngier 94b81125c7SMarc Zyngier1: 952b28162cSMarc Zyngier /* 96b81125c7SMarc Zyngier * Perform the EL2 call 972b28162cSMarc Zyngier */ 982b28162cSMarc Zyngier kern_hyp_va x0 99b81125c7SMarc Zyngier do_el2_call 1002b28162cSMarc Zyngier 1015fbe9a59SMarc Zyngier eret 1022b28162cSMarc Zyngier 1032b28162cSMarc Zyngierel1_trap: 1042b28162cSMarc Zyngier /* 10568381b2bSShanker Donthineni * x0: ESR_EC 1062b28162cSMarc Zyngier */ 10732b03d10SJames Morse ldr x1, [sp, #16 + 8] // vcpu stored by __guest_enter 1082b28162cSMarc Zyngier 10982e0191aSSuzuki K Poulose /* 11082e0191aSSuzuki K Poulose * We trap the first access to the FP/SIMD to save the host context 11182e0191aSSuzuki K Poulose * and restore the guest context lazily. 11282e0191aSSuzuki K Poulose * If FP/SIMD is not implemented, handle the trap and inject an 11382e0191aSSuzuki K Poulose * undefined instruction exception to the guest. 11482e0191aSSuzuki K Poulose */ 11582e0191aSSuzuki K Poulosealternative_if_not ARM64_HAS_NO_FPSIMD 11668381b2bSShanker Donthineni cmp x0, #ESR_ELx_EC_FP_ASIMD 1172b28162cSMarc Zyngier b.eq __fpsimd_guest_restore 11882e0191aSSuzuki K Poulosealternative_else_nop_endif 1192b28162cSMarc Zyngier 12068381b2bSShanker Donthineni mov x0, #ARM_EXCEPTION_TRAP 1212b28162cSMarc Zyngier b __guest_exit 1222b28162cSMarc Zyngier 1232b28162cSMarc Zyngierel1_irq: 12468381b2bSShanker Donthineni stp x0, x1, [sp, #-16]! 12532b03d10SJames Morse ldr x1, [sp, #16 + 8] 12668381b2bSShanker Donthineni mov x0, #ARM_EXCEPTION_IRQ 1272b28162cSMarc Zyngier b __guest_exit 1282b28162cSMarc Zyngier 1291b51e5faSMarc Zyngierel1_error: 1301b51e5faSMarc Zyngier stp x0, x1, [sp, #-16]! 13132b03d10SJames Morse ldr x1, [sp, #16 + 8] 1321b51e5faSMarc Zyngier mov x0, #ARM_EXCEPTION_EL1_SERROR 1331b51e5faSMarc Zyngier b __guest_exit 1341b51e5faSMarc Zyngier 135395ea79eSMarc Zyngierel2_error: 136395ea79eSMarc Zyngier /* 137395ea79eSMarc Zyngier * Only two possibilities: 138395ea79eSMarc Zyngier * 1) Either we come from the exit path, having just unmasked 139395ea79eSMarc Zyngier * PSTATE.A: change the return code to an EL2 fault, and 140395ea79eSMarc Zyngier * carry on, as we're already in a sane state to handle it. 141395ea79eSMarc Zyngier * 2) Or we come from anywhere else, and that's a bug: we panic. 142395ea79eSMarc Zyngier * 143395ea79eSMarc Zyngier * For (1), x0 contains the original return code and x1 doesn't 144395ea79eSMarc Zyngier * contain anything meaningful at that stage. We can reuse them 145395ea79eSMarc Zyngier * as temp registers. 146395ea79eSMarc Zyngier * For (2), who cares? 147395ea79eSMarc Zyngier */ 148395ea79eSMarc Zyngier mrs x0, elr_el2 149395ea79eSMarc Zyngier adr x1, abort_guest_exit_start 150395ea79eSMarc Zyngier cmp x0, x1 151395ea79eSMarc Zyngier adr x1, abort_guest_exit_end 152395ea79eSMarc Zyngier ccmp x0, x1, #4, ne 153395ea79eSMarc Zyngier b.ne __hyp_panic 154395ea79eSMarc Zyngier mov x0, #(1 << ARM_EXIT_WITH_SERROR_BIT) 155395ea79eSMarc Zyngier eret 156395ea79eSMarc Zyngier 15753fd5b64SMarc ZyngierENTRY(__hyp_do_panic) 15853fd5b64SMarc Zyngier mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\ 15953fd5b64SMarc Zyngier PSR_MODE_EL1h) 16053fd5b64SMarc Zyngier msr spsr_el2, lr 16153fd5b64SMarc Zyngier ldr lr, =panic 16253fd5b64SMarc Zyngier msr elr_el2, lr 16353fd5b64SMarc Zyngier eret 16453fd5b64SMarc ZyngierENDPROC(__hyp_do_panic) 16553fd5b64SMarc Zyngier 166*c97e166eSJames MorseENTRY(__hyp_panic) 167*c97e166eSJames Morse /* 168*c97e166eSJames Morse * '=kvm_host_cpu_state' is a host VA from the constant pool, it may 169*c97e166eSJames Morse * not be accessible by this address from EL2, hyp_panic() converts 170*c97e166eSJames Morse * it with kern_hyp_va() before use. 171*c97e166eSJames Morse */ 172*c97e166eSJames Morse ldr x0, =kvm_host_cpu_state 173*c97e166eSJames Morse mrs x1, tpidr_el2 174*c97e166eSJames Morse add x0, x0, x1 175*c97e166eSJames Morse b hyp_panic 176*c97e166eSJames MorseENDPROC(__hyp_panic) 177*c97e166eSJames Morse 17853fd5b64SMarc Zyngier.macro invalid_vector label, target = __hyp_panic 1792b28162cSMarc Zyngier .align 2 1802b28162cSMarc Zyngier\label: 1812b28162cSMarc Zyngier b \target 1822b28162cSMarc ZyngierENDPROC(\label) 1832b28162cSMarc Zyngier.endm 1842b28162cSMarc Zyngier 1852b28162cSMarc Zyngier /* None of these should ever happen */ 1862b28162cSMarc Zyngier invalid_vector el2t_sync_invalid 1872b28162cSMarc Zyngier invalid_vector el2t_irq_invalid 1882b28162cSMarc Zyngier invalid_vector el2t_fiq_invalid 1892b28162cSMarc Zyngier invalid_vector el2t_error_invalid 1902b28162cSMarc Zyngier invalid_vector el2h_sync_invalid 1912b28162cSMarc Zyngier invalid_vector el2h_irq_invalid 1922b28162cSMarc Zyngier invalid_vector el2h_fiq_invalid 1932b28162cSMarc Zyngier invalid_vector el1_sync_invalid 1942b28162cSMarc Zyngier invalid_vector el1_irq_invalid 1952b28162cSMarc Zyngier invalid_vector el1_fiq_invalid 1962b28162cSMarc Zyngier 1972b28162cSMarc Zyngier .ltorg 1982b28162cSMarc Zyngier 1992b28162cSMarc Zyngier .align 11 2002b28162cSMarc Zyngier 201044ac37dSMarc ZyngierENTRY(__kvm_hyp_vector) 2022b28162cSMarc Zyngier ventry el2t_sync_invalid // Synchronous EL2t 2032b28162cSMarc Zyngier ventry el2t_irq_invalid // IRQ EL2t 2042b28162cSMarc Zyngier ventry el2t_fiq_invalid // FIQ EL2t 2052b28162cSMarc Zyngier ventry el2t_error_invalid // Error EL2t 2062b28162cSMarc Zyngier 2072b28162cSMarc Zyngier ventry el2h_sync_invalid // Synchronous EL2h 2082b28162cSMarc Zyngier ventry el2h_irq_invalid // IRQ EL2h 2092b28162cSMarc Zyngier ventry el2h_fiq_invalid // FIQ EL2h 210395ea79eSMarc Zyngier ventry el2_error // Error EL2h 2112b28162cSMarc Zyngier 2122b28162cSMarc Zyngier ventry el1_sync // Synchronous 64-bit EL1 2132b28162cSMarc Zyngier ventry el1_irq // IRQ 64-bit EL1 2142b28162cSMarc Zyngier ventry el1_fiq_invalid // FIQ 64-bit EL1 2151b51e5faSMarc Zyngier ventry el1_error // Error 64-bit EL1 2162b28162cSMarc Zyngier 2172b28162cSMarc Zyngier ventry el1_sync // Synchronous 32-bit EL1 2182b28162cSMarc Zyngier ventry el1_irq // IRQ 32-bit EL1 2192b28162cSMarc Zyngier ventry el1_fiq_invalid // FIQ 32-bit EL1 2201b51e5faSMarc Zyngier ventry el1_error // Error 32-bit EL1 221044ac37dSMarc ZyngierENDPROC(__kvm_hyp_vector) 222