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 563421e9d8SMarc Zyngier/* 573421e9d8SMarc Zyngier * Compute the idmap address of __kvm_hyp_reset based on the idmap 583421e9d8SMarc Zyngier * start passed as a parameter, and jump there. 593421e9d8SMarc Zyngier * 603421e9d8SMarc Zyngier * x0: HYP phys_idmap_start 613421e9d8SMarc Zyngier */ 623421e9d8SMarc ZyngierENTRY(__kvm_hyp_teardown) 633421e9d8SMarc Zyngier mov x4, x0 643421e9d8SMarc Zyngier adr_l x3, __kvm_hyp_reset 653421e9d8SMarc Zyngier 663421e9d8SMarc Zyngier /* insert __kvm_hyp_reset()s offset into phys_idmap_start */ 673421e9d8SMarc Zyngier bfi x4, x3, #0, #PAGE_SHIFT 683421e9d8SMarc Zyngier br x4 693421e9d8SMarc ZyngierENDPROC(__kvm_hyp_teardown) 70b81125c7SMarc Zyngier 712b28162cSMarc Zyngierel1_sync: // Guest trapped into EL2 7268381b2bSShanker Donthineni stp x0, x1, [sp, #-16]! 732b28162cSMarc Zyngier 745f05a72aSMarc Zyngieralternative_if_not ARM64_HAS_VIRT_HOST_EXTN 752b28162cSMarc Zyngier mrs x1, esr_el2 765f05a72aSMarc Zyngieralternative_else 775f05a72aSMarc Zyngier mrs x1, esr_el1 785f05a72aSMarc Zyngieralternative_endif 7968381b2bSShanker Donthineni lsr x0, x1, #ESR_ELx_EC_SHIFT 802b28162cSMarc Zyngier 8168381b2bSShanker Donthineni cmp x0, #ESR_ELx_EC_HVC64 822b28162cSMarc Zyngier b.ne el1_trap 832b28162cSMarc Zyngier 8468381b2bSShanker Donthineni mrs x1, vttbr_el2 // If vttbr is valid, the 64bit guest 8568381b2bSShanker Donthineni cbnz x1, el1_trap // called HVC 862b28162cSMarc Zyngier 872b28162cSMarc Zyngier /* Here, we're pretty sure the host called HVC. */ 8868381b2bSShanker Donthineni ldp x0, x1, [sp], #16 892b28162cSMarc Zyngier 90*5fbe9a59SMarc Zyngier /* Check for a stub HVC call */ 91*5fbe9a59SMarc Zyngier cmp x0, #HVC_STUB_HCALL_NR 92*5fbe9a59SMarc Zyngier b.hs 1f 93*5fbe9a59SMarc Zyngier 94*5fbe9a59SMarc Zyngier /* 95*5fbe9a59SMarc Zyngier * Compute the idmap address of __kvm_handle_stub_hvc and 96*5fbe9a59SMarc Zyngier * jump there. Since we use kimage_voffset, do not use the 97*5fbe9a59SMarc Zyngier * HYP VA for __kvm_handle_stub_hvc, but the kernel VA instead 98*5fbe9a59SMarc Zyngier * (by loading it from the constant pool). 99*5fbe9a59SMarc Zyngier * 100*5fbe9a59SMarc Zyngier * Preserve x0-x4, which may contain stub parameters. 101*5fbe9a59SMarc Zyngier */ 102*5fbe9a59SMarc Zyngier ldr x5, =__kvm_handle_stub_hvc 103*5fbe9a59SMarc Zyngier ldr_l x6, kimage_voffset 104*5fbe9a59SMarc Zyngier 105*5fbe9a59SMarc Zyngier /* x5 = __pa(x5) */ 106*5fbe9a59SMarc Zyngier sub x5, x5, x6 107*5fbe9a59SMarc Zyngier br x5 1082b28162cSMarc Zyngier 109b81125c7SMarc Zyngier1: 1102b28162cSMarc Zyngier /* 111b81125c7SMarc Zyngier * Perform the EL2 call 1122b28162cSMarc Zyngier */ 1132b28162cSMarc Zyngier kern_hyp_va x0 114b81125c7SMarc Zyngier do_el2_call 1152b28162cSMarc Zyngier 116*5fbe9a59SMarc Zyngier eret 1172b28162cSMarc Zyngier 1182b28162cSMarc Zyngierel1_trap: 1192b28162cSMarc Zyngier /* 12068381b2bSShanker Donthineni * x0: ESR_EC 1212b28162cSMarc Zyngier */ 1222b28162cSMarc Zyngier 12382e0191aSSuzuki K Poulose /* 12482e0191aSSuzuki K Poulose * We trap the first access to the FP/SIMD to save the host context 12582e0191aSSuzuki K Poulose * and restore the guest context lazily. 12682e0191aSSuzuki K Poulose * If FP/SIMD is not implemented, handle the trap and inject an 12782e0191aSSuzuki K Poulose * undefined instruction exception to the guest. 12882e0191aSSuzuki K Poulose */ 12982e0191aSSuzuki K Poulosealternative_if_not ARM64_HAS_NO_FPSIMD 13068381b2bSShanker Donthineni cmp x0, #ESR_ELx_EC_FP_ASIMD 1312b28162cSMarc Zyngier b.eq __fpsimd_guest_restore 13282e0191aSSuzuki K Poulosealternative_else_nop_endif 1332b28162cSMarc Zyngier 13468381b2bSShanker Donthineni mrs x1, tpidr_el2 13568381b2bSShanker Donthineni mov x0, #ARM_EXCEPTION_TRAP 1362b28162cSMarc Zyngier b __guest_exit 1372b28162cSMarc Zyngier 1382b28162cSMarc Zyngierel1_irq: 13968381b2bSShanker Donthineni stp x0, x1, [sp, #-16]! 14068381b2bSShanker Donthineni mrs x1, tpidr_el2 14168381b2bSShanker Donthineni mov x0, #ARM_EXCEPTION_IRQ 1422b28162cSMarc Zyngier b __guest_exit 1432b28162cSMarc Zyngier 1441b51e5faSMarc Zyngierel1_error: 1451b51e5faSMarc Zyngier stp x0, x1, [sp, #-16]! 1461b51e5faSMarc Zyngier mrs x1, tpidr_el2 1471b51e5faSMarc Zyngier mov x0, #ARM_EXCEPTION_EL1_SERROR 1481b51e5faSMarc Zyngier b __guest_exit 1491b51e5faSMarc Zyngier 150395ea79eSMarc Zyngierel2_error: 151395ea79eSMarc Zyngier /* 152395ea79eSMarc Zyngier * Only two possibilities: 153395ea79eSMarc Zyngier * 1) Either we come from the exit path, having just unmasked 154395ea79eSMarc Zyngier * PSTATE.A: change the return code to an EL2 fault, and 155395ea79eSMarc Zyngier * carry on, as we're already in a sane state to handle it. 156395ea79eSMarc Zyngier * 2) Or we come from anywhere else, and that's a bug: we panic. 157395ea79eSMarc Zyngier * 158395ea79eSMarc Zyngier * For (1), x0 contains the original return code and x1 doesn't 159395ea79eSMarc Zyngier * contain anything meaningful at that stage. We can reuse them 160395ea79eSMarc Zyngier * as temp registers. 161395ea79eSMarc Zyngier * For (2), who cares? 162395ea79eSMarc Zyngier */ 163395ea79eSMarc Zyngier mrs x0, elr_el2 164395ea79eSMarc Zyngier adr x1, abort_guest_exit_start 165395ea79eSMarc Zyngier cmp x0, x1 166395ea79eSMarc Zyngier adr x1, abort_guest_exit_end 167395ea79eSMarc Zyngier ccmp x0, x1, #4, ne 168395ea79eSMarc Zyngier b.ne __hyp_panic 169395ea79eSMarc Zyngier mov x0, #(1 << ARM_EXIT_WITH_SERROR_BIT) 170395ea79eSMarc Zyngier eret 171395ea79eSMarc Zyngier 17253fd5b64SMarc ZyngierENTRY(__hyp_do_panic) 17353fd5b64SMarc Zyngier mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\ 17453fd5b64SMarc Zyngier PSR_MODE_EL1h) 17553fd5b64SMarc Zyngier msr spsr_el2, lr 17653fd5b64SMarc Zyngier ldr lr, =panic 17753fd5b64SMarc Zyngier msr elr_el2, lr 17853fd5b64SMarc Zyngier eret 17953fd5b64SMarc ZyngierENDPROC(__hyp_do_panic) 18053fd5b64SMarc Zyngier 18153fd5b64SMarc Zyngier.macro invalid_vector label, target = __hyp_panic 1822b28162cSMarc Zyngier .align 2 1832b28162cSMarc Zyngier\label: 1842b28162cSMarc Zyngier b \target 1852b28162cSMarc ZyngierENDPROC(\label) 1862b28162cSMarc Zyngier.endm 1872b28162cSMarc Zyngier 1882b28162cSMarc Zyngier /* None of these should ever happen */ 1892b28162cSMarc Zyngier invalid_vector el2t_sync_invalid 1902b28162cSMarc Zyngier invalid_vector el2t_irq_invalid 1912b28162cSMarc Zyngier invalid_vector el2t_fiq_invalid 1922b28162cSMarc Zyngier invalid_vector el2t_error_invalid 1932b28162cSMarc Zyngier invalid_vector el2h_sync_invalid 1942b28162cSMarc Zyngier invalid_vector el2h_irq_invalid 1952b28162cSMarc Zyngier invalid_vector el2h_fiq_invalid 1962b28162cSMarc Zyngier invalid_vector el1_sync_invalid 1972b28162cSMarc Zyngier invalid_vector el1_irq_invalid 1982b28162cSMarc Zyngier invalid_vector el1_fiq_invalid 1992b28162cSMarc Zyngier 2002b28162cSMarc Zyngier .ltorg 2012b28162cSMarc Zyngier 2022b28162cSMarc Zyngier .align 11 2032b28162cSMarc Zyngier 204044ac37dSMarc ZyngierENTRY(__kvm_hyp_vector) 2052b28162cSMarc Zyngier ventry el2t_sync_invalid // Synchronous EL2t 2062b28162cSMarc Zyngier ventry el2t_irq_invalid // IRQ EL2t 2072b28162cSMarc Zyngier ventry el2t_fiq_invalid // FIQ EL2t 2082b28162cSMarc Zyngier ventry el2t_error_invalid // Error EL2t 2092b28162cSMarc Zyngier 2102b28162cSMarc Zyngier ventry el2h_sync_invalid // Synchronous EL2h 2112b28162cSMarc Zyngier ventry el2h_irq_invalid // IRQ EL2h 2122b28162cSMarc Zyngier ventry el2h_fiq_invalid // FIQ EL2h 213395ea79eSMarc Zyngier ventry el2_error // Error EL2h 2142b28162cSMarc Zyngier 2152b28162cSMarc Zyngier ventry el1_sync // Synchronous 64-bit EL1 2162b28162cSMarc Zyngier ventry el1_irq // IRQ 64-bit EL1 2172b28162cSMarc Zyngier ventry el1_fiq_invalid // FIQ 64-bit EL1 2181b51e5faSMarc Zyngier ventry el1_error // Error 64-bit EL1 2192b28162cSMarc Zyngier 2202b28162cSMarc Zyngier ventry el1_sync // Synchronous 32-bit EL1 2212b28162cSMarc Zyngier ventry el1_irq // IRQ 32-bit EL1 2222b28162cSMarc Zyngier ventry el1_fiq_invalid // FIQ 32-bit EL1 2231b51e5faSMarc Zyngier ventry el1_error // Error 32-bit EL1 224044ac37dSMarc ZyngierENDPROC(__kvm_hyp_vector) 225