1/* 2 * Copyright (C) 2015 - ARM Ltd 3 * Author: Marc Zyngier <marc.zyngier@arm.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18#include <linux/linkage.h> 19 20#include <asm/alternative.h> 21#include <asm/assembler.h> 22#include <asm/cpufeature.h> 23#include <asm/kvm_arm.h> 24#include <asm/kvm_asm.h> 25#include <asm/kvm_mmu.h> 26 27 .text 28 .pushsection .hyp.text, "ax" 29 30.macro save_x0_to_x3 31 stp x0, x1, [sp, #-16]! 32 stp x2, x3, [sp, #-16]! 33.endm 34 35.macro restore_x0_to_x3 36 ldp x2, x3, [sp], #16 37 ldp x0, x1, [sp], #16 38.endm 39 40.macro do_el2_call 41 /* 42 * Shuffle the parameters before calling the function 43 * pointed to in x0. Assumes parameters in x[1,2,3]. 44 */ 45 mov lr, x0 46 mov x0, x1 47 mov x1, x2 48 mov x2, x3 49 blr lr 50.endm 51 52ENTRY(__vhe_hyp_call) 53 str lr, [sp, #-16]! 54 do_el2_call 55 ldr lr, [sp], #16 56 /* 57 * We used to rely on having an exception return to get 58 * an implicit isb. In the E2H case, we don't have it anymore. 59 * rather than changing all the leaf functions, just do it here 60 * before returning to the rest of the kernel. 61 */ 62 isb 63 ret 64ENDPROC(__vhe_hyp_call) 65 66el1_sync: // Guest trapped into EL2 67 save_x0_to_x3 68 69alternative_if_not ARM64_HAS_VIRT_HOST_EXTN 70 mrs x1, esr_el2 71alternative_else 72 mrs x1, esr_el1 73alternative_endif 74 lsr x2, x1, #ESR_ELx_EC_SHIFT 75 76 cmp x2, #ESR_ELx_EC_HVC64 77 b.ne el1_trap 78 79 mrs x3, vttbr_el2 // If vttbr is valid, the 64bit guest 80 cbnz x3, el1_trap // called HVC 81 82 /* Here, we're pretty sure the host called HVC. */ 83 restore_x0_to_x3 84 85 cmp x0, #HVC_GET_VECTORS 86 b.ne 1f 87 mrs x0, vbar_el2 88 b 2f 89 901: 91 /* 92 * Perform the EL2 call 93 */ 94 kern_hyp_va x0 95 do_el2_call 96 972: eret 98 99el1_trap: 100 /* 101 * x1: ESR 102 * x2: ESR_EC 103 */ 104 105 /* Guest accessed VFP/SIMD registers, save host, restore Guest */ 106 cmp x2, #ESR_ELx_EC_FP_ASIMD 107 b.eq __fpsimd_guest_restore 108 109 mrs x0, tpidr_el2 110 mov x1, #ARM_EXCEPTION_TRAP 111 b __guest_exit 112 113el1_irq: 114 save_x0_to_x3 115 mrs x0, tpidr_el2 116 mov x1, #ARM_EXCEPTION_IRQ 117 b __guest_exit 118 119ENTRY(__hyp_do_panic) 120 mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\ 121 PSR_MODE_EL1h) 122 msr spsr_el2, lr 123 ldr lr, =panic 124 msr elr_el2, lr 125 eret 126ENDPROC(__hyp_do_panic) 127 128.macro invalid_vector label, target = __hyp_panic 129 .align 2 130\label: 131 b \target 132ENDPROC(\label) 133.endm 134 135 /* None of these should ever happen */ 136 invalid_vector el2t_sync_invalid 137 invalid_vector el2t_irq_invalid 138 invalid_vector el2t_fiq_invalid 139 invalid_vector el2t_error_invalid 140 invalid_vector el2h_sync_invalid 141 invalid_vector el2h_irq_invalid 142 invalid_vector el2h_fiq_invalid 143 invalid_vector el2h_error_invalid 144 invalid_vector el1_sync_invalid 145 invalid_vector el1_irq_invalid 146 invalid_vector el1_fiq_invalid 147 invalid_vector el1_error_invalid 148 149 .ltorg 150 151 .align 11 152 153ENTRY(__kvm_hyp_vector) 154 ventry el2t_sync_invalid // Synchronous EL2t 155 ventry el2t_irq_invalid // IRQ EL2t 156 ventry el2t_fiq_invalid // FIQ EL2t 157 ventry el2t_error_invalid // Error EL2t 158 159 ventry el2h_sync_invalid // Synchronous EL2h 160 ventry el2h_irq_invalid // IRQ EL2h 161 ventry el2h_fiq_invalid // FIQ EL2h 162 ventry el2h_error_invalid // Error EL2h 163 164 ventry el1_sync // Synchronous 64-bit EL1 165 ventry el1_irq // IRQ 64-bit EL1 166 ventry el1_fiq_invalid // FIQ 64-bit EL1 167 ventry el1_error_invalid // Error 64-bit EL1 168 169 ventry el1_sync // Synchronous 32-bit EL1 170 ventry el1_irq // IRQ 32-bit EL1 171 ventry el1_fiq_invalid // FIQ 32-bit EL1 172 ventry el1_error_invalid // Error 32-bit EL1 173ENDPROC(__kvm_hyp_vector) 174