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/asm-offsets.h> 232b28162cSMarc Zyngier#include <asm/cpufeature.h> 242b28162cSMarc Zyngier#include <asm/kvm_arm.h> 252b28162cSMarc Zyngier#include <asm/kvm_asm.h> 262b28162cSMarc Zyngier#include <asm/kvm_mmu.h> 272b28162cSMarc Zyngier 282b28162cSMarc Zyngier .text 292b28162cSMarc Zyngier .pushsection .hyp.text, "ax" 302b28162cSMarc Zyngier 312b28162cSMarc Zyngier.macro save_x0_to_x3 322b28162cSMarc Zyngier stp x0, x1, [sp, #-16]! 332b28162cSMarc Zyngier stp x2, x3, [sp, #-16]! 342b28162cSMarc Zyngier.endm 352b28162cSMarc Zyngier 362b28162cSMarc Zyngier.macro restore_x0_to_x3 372b28162cSMarc Zyngier ldp x2, x3, [sp], #16 382b28162cSMarc Zyngier ldp x0, x1, [sp], #16 392b28162cSMarc Zyngier.endm 402b28162cSMarc Zyngier 41*b81125c7SMarc Zyngier.macro do_el2_call 42*b81125c7SMarc Zyngier /* 43*b81125c7SMarc Zyngier * Shuffle the parameters before calling the function 44*b81125c7SMarc Zyngier * pointed to in x0. Assumes parameters in x[1,2,3]. 45*b81125c7SMarc Zyngier */ 46*b81125c7SMarc Zyngier sub sp, sp, #16 47*b81125c7SMarc Zyngier str lr, [sp] 48*b81125c7SMarc Zyngier mov lr, x0 49*b81125c7SMarc Zyngier mov x0, x1 50*b81125c7SMarc Zyngier mov x1, x2 51*b81125c7SMarc Zyngier mov x2, x3 52*b81125c7SMarc Zyngier blr lr 53*b81125c7SMarc Zyngier ldr lr, [sp] 54*b81125c7SMarc Zyngier add sp, sp, #16 55*b81125c7SMarc Zyngier.endm 56*b81125c7SMarc Zyngier 57*b81125c7SMarc ZyngierENTRY(__vhe_hyp_call) 58*b81125c7SMarc Zyngier do_el2_call 59*b81125c7SMarc Zyngier /* 60*b81125c7SMarc Zyngier * We used to rely on having an exception return to get 61*b81125c7SMarc Zyngier * an implicit isb. In the E2H case, we don't have it anymore. 62*b81125c7SMarc Zyngier * rather than changing all the leaf functions, just do it here 63*b81125c7SMarc Zyngier * before returning to the rest of the kernel. 64*b81125c7SMarc Zyngier */ 65*b81125c7SMarc Zyngier isb 66*b81125c7SMarc Zyngier ret 67*b81125c7SMarc ZyngierENDPROC(__vhe_hyp_call) 68*b81125c7SMarc Zyngier 692b28162cSMarc Zyngierel1_sync: // Guest trapped into EL2 702b28162cSMarc Zyngier save_x0_to_x3 712b28162cSMarc Zyngier 722b28162cSMarc Zyngier mrs x1, esr_el2 732b28162cSMarc Zyngier lsr x2, x1, #ESR_ELx_EC_SHIFT 742b28162cSMarc Zyngier 752b28162cSMarc Zyngier cmp x2, #ESR_ELx_EC_HVC64 762b28162cSMarc Zyngier b.ne el1_trap 772b28162cSMarc Zyngier 782b28162cSMarc Zyngier mrs x3, vttbr_el2 // If vttbr is valid, the 64bit guest 792b28162cSMarc Zyngier cbnz x3, el1_trap // called HVC 802b28162cSMarc Zyngier 812b28162cSMarc Zyngier /* Here, we're pretty sure the host called HVC. */ 822b28162cSMarc Zyngier restore_x0_to_x3 832b28162cSMarc Zyngier 842b28162cSMarc Zyngier /* Check for __hyp_get_vectors */ 852b28162cSMarc Zyngier cbnz x0, 1f 862b28162cSMarc Zyngier mrs x0, vbar_el2 872b28162cSMarc Zyngier b 2f 882b28162cSMarc Zyngier 89*b81125c7SMarc Zyngier1: 902b28162cSMarc Zyngier /* 91*b81125c7SMarc Zyngier * Perform the EL2 call 922b28162cSMarc Zyngier */ 932b28162cSMarc Zyngier kern_hyp_va x0 94*b81125c7SMarc Zyngier do_el2_call 952b28162cSMarc Zyngier 962b28162cSMarc Zyngier2: eret 972b28162cSMarc Zyngier 982b28162cSMarc Zyngierel1_trap: 992b28162cSMarc Zyngier /* 1002b28162cSMarc Zyngier * x1: ESR 1012b28162cSMarc Zyngier * x2: ESR_EC 1022b28162cSMarc Zyngier */ 1032b28162cSMarc Zyngier 1042b28162cSMarc Zyngier /* Guest accessed VFP/SIMD registers, save host, restore Guest */ 1052b28162cSMarc Zyngier cmp x2, #ESR_ELx_EC_FP_ASIMD 1062b28162cSMarc Zyngier b.eq __fpsimd_guest_restore 1072b28162cSMarc Zyngier 1082b28162cSMarc Zyngier cmp x2, #ESR_ELx_EC_DABT_LOW 1092b28162cSMarc Zyngier mov x0, #ESR_ELx_EC_IABT_LOW 1102b28162cSMarc Zyngier ccmp x2, x0, #4, ne 1112b28162cSMarc Zyngier b.ne 1f // Not an abort we care about 1122b28162cSMarc Zyngier 1132b28162cSMarc Zyngier /* This is an abort. Check for permission fault */ 1142b28162cSMarc Zyngieralternative_if_not ARM64_WORKAROUND_834220 1152b28162cSMarc Zyngier and x2, x1, #ESR_ELx_FSC_TYPE 1162b28162cSMarc Zyngier cmp x2, #FSC_PERM 1172b28162cSMarc Zyngier b.ne 1f // Not a permission fault 1182b28162cSMarc Zyngieralternative_else 1192b28162cSMarc Zyngier nop // Use the permission fault path to 1202b28162cSMarc Zyngier nop // check for a valid S1 translation, 1212b28162cSMarc Zyngier nop // regardless of the ESR value. 1222b28162cSMarc Zyngieralternative_endif 1232b28162cSMarc Zyngier 1242b28162cSMarc Zyngier /* 1252b28162cSMarc Zyngier * Check for Stage-1 page table walk, which is guaranteed 1262b28162cSMarc Zyngier * to give a valid HPFAR_EL2. 1272b28162cSMarc Zyngier */ 1282b28162cSMarc Zyngier tbnz x1, #7, 1f // S1PTW is set 1292b28162cSMarc Zyngier 1302b28162cSMarc Zyngier /* Preserve PAR_EL1 */ 1312b28162cSMarc Zyngier mrs x3, par_el1 1322b28162cSMarc Zyngier stp x3, xzr, [sp, #-16]! 1332b28162cSMarc Zyngier 1342b28162cSMarc Zyngier /* 1352b28162cSMarc Zyngier * Permission fault, HPFAR_EL2 is invalid. 1362b28162cSMarc Zyngier * Resolve the IPA the hard way using the guest VA. 1372b28162cSMarc Zyngier * Stage-1 translation already validated the memory access rights. 1382b28162cSMarc Zyngier * As such, we can use the EL1 translation regime, and don't have 1392b28162cSMarc Zyngier * to distinguish between EL0 and EL1 access. 1402b28162cSMarc Zyngier */ 1412b28162cSMarc Zyngier mrs x2, far_el2 1422b28162cSMarc Zyngier at s1e1r, x2 1432b28162cSMarc Zyngier isb 1442b28162cSMarc Zyngier 1452b28162cSMarc Zyngier /* Read result */ 1462b28162cSMarc Zyngier mrs x3, par_el1 1472b28162cSMarc Zyngier ldp x0, xzr, [sp], #16 // Restore PAR_EL1 from the stack 1482b28162cSMarc Zyngier msr par_el1, x0 1492b28162cSMarc Zyngier tbnz x3, #0, 3f // Bail out if we failed the translation 1502b28162cSMarc Zyngier ubfx x3, x3, #12, #36 // Extract IPA 1512b28162cSMarc Zyngier lsl x3, x3, #4 // and present it like HPFAR 1522b28162cSMarc Zyngier b 2f 1532b28162cSMarc Zyngier 1542b28162cSMarc Zyngier1: mrs x3, hpfar_el2 1552b28162cSMarc Zyngier mrs x2, far_el2 1562b28162cSMarc Zyngier 1572b28162cSMarc Zyngier2: mrs x0, tpidr_el2 1582b28162cSMarc Zyngier str w1, [x0, #VCPU_ESR_EL2] 1592b28162cSMarc Zyngier str x2, [x0, #VCPU_FAR_EL2] 1602b28162cSMarc Zyngier str x3, [x0, #VCPU_HPFAR_EL2] 1612b28162cSMarc Zyngier 1622b28162cSMarc Zyngier mov x1, #ARM_EXCEPTION_TRAP 1632b28162cSMarc Zyngier b __guest_exit 1642b28162cSMarc Zyngier 1652b28162cSMarc Zyngier /* 1662b28162cSMarc Zyngier * Translation failed. Just return to the guest and 1672b28162cSMarc Zyngier * let it fault again. Another CPU is probably playing 1682b28162cSMarc Zyngier * behind our back. 1692b28162cSMarc Zyngier */ 1702b28162cSMarc Zyngier3: restore_x0_to_x3 1712b28162cSMarc Zyngier 1722b28162cSMarc Zyngier eret 1732b28162cSMarc Zyngier 1742b28162cSMarc Zyngierel1_irq: 1752b28162cSMarc Zyngier save_x0_to_x3 1762b28162cSMarc Zyngier mrs x0, tpidr_el2 1772b28162cSMarc Zyngier mov x1, #ARM_EXCEPTION_IRQ 1782b28162cSMarc Zyngier b __guest_exit 1792b28162cSMarc Zyngier 18053fd5b64SMarc ZyngierENTRY(__hyp_do_panic) 18153fd5b64SMarc Zyngier mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\ 18253fd5b64SMarc Zyngier PSR_MODE_EL1h) 18353fd5b64SMarc Zyngier msr spsr_el2, lr 18453fd5b64SMarc Zyngier ldr lr, =panic 18553fd5b64SMarc Zyngier msr elr_el2, lr 18653fd5b64SMarc Zyngier eret 18753fd5b64SMarc ZyngierENDPROC(__hyp_do_panic) 18853fd5b64SMarc Zyngier 18953fd5b64SMarc Zyngier.macro invalid_vector label, target = __hyp_panic 1902b28162cSMarc Zyngier .align 2 1912b28162cSMarc Zyngier\label: 1922b28162cSMarc Zyngier b \target 1932b28162cSMarc ZyngierENDPROC(\label) 1942b28162cSMarc Zyngier.endm 1952b28162cSMarc Zyngier 1962b28162cSMarc Zyngier /* None of these should ever happen */ 1972b28162cSMarc Zyngier invalid_vector el2t_sync_invalid 1982b28162cSMarc Zyngier invalid_vector el2t_irq_invalid 1992b28162cSMarc Zyngier invalid_vector el2t_fiq_invalid 2002b28162cSMarc Zyngier invalid_vector el2t_error_invalid 2012b28162cSMarc Zyngier invalid_vector el2h_sync_invalid 2022b28162cSMarc Zyngier invalid_vector el2h_irq_invalid 2032b28162cSMarc Zyngier invalid_vector el2h_fiq_invalid 2042b28162cSMarc Zyngier invalid_vector el2h_error_invalid 2052b28162cSMarc Zyngier invalid_vector el1_sync_invalid 2062b28162cSMarc Zyngier invalid_vector el1_irq_invalid 2072b28162cSMarc Zyngier invalid_vector el1_fiq_invalid 2082b28162cSMarc Zyngier invalid_vector el1_error_invalid 2092b28162cSMarc Zyngier 2102b28162cSMarc Zyngier .ltorg 2112b28162cSMarc Zyngier 2122b28162cSMarc Zyngier .align 11 2132b28162cSMarc Zyngier 214044ac37dSMarc ZyngierENTRY(__kvm_hyp_vector) 2152b28162cSMarc Zyngier ventry el2t_sync_invalid // Synchronous EL2t 2162b28162cSMarc Zyngier ventry el2t_irq_invalid // IRQ EL2t 2172b28162cSMarc Zyngier ventry el2t_fiq_invalid // FIQ EL2t 2182b28162cSMarc Zyngier ventry el2t_error_invalid // Error EL2t 2192b28162cSMarc Zyngier 2202b28162cSMarc Zyngier ventry el2h_sync_invalid // Synchronous EL2h 2212b28162cSMarc Zyngier ventry el2h_irq_invalid // IRQ EL2h 2222b28162cSMarc Zyngier ventry el2h_fiq_invalid // FIQ EL2h 2232b28162cSMarc Zyngier ventry el2h_error_invalid // Error EL2h 2242b28162cSMarc Zyngier 2252b28162cSMarc Zyngier ventry el1_sync // Synchronous 64-bit EL1 2262b28162cSMarc Zyngier ventry el1_irq // IRQ 64-bit EL1 2272b28162cSMarc Zyngier ventry el1_fiq_invalid // FIQ 64-bit EL1 2282b28162cSMarc Zyngier ventry el1_error_invalid // Error 64-bit EL1 2292b28162cSMarc Zyngier 2302b28162cSMarc Zyngier ventry el1_sync // Synchronous 32-bit EL1 2312b28162cSMarc Zyngier ventry el1_irq // IRQ 32-bit EL1 2322b28162cSMarc Zyngier ventry el1_fiq_invalid // FIQ 32-bit EL1 2332b28162cSMarc Zyngier ventry el1_error_invalid // Error 32-bit EL1 234044ac37dSMarc ZyngierENDPROC(__kvm_hyp_vector) 235