1/* 2 * Copyright (C) 2016 - 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#include <asm/asm-offsets.h> 20#include <asm/kvm_arm.h> 21#include <asm/kvm_asm.h> 22 23 .arch_extension virt 24 25 .text 26 .pushsection .hyp.text, "ax" 27 28#define USR_REGS_OFFSET (CPU_CTXT_GP_REGS + GP_REGS_USR) 29 30/* int __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host) */ 31ENTRY(__guest_enter) 32 @ Save host registers 33 add r1, r1, #(USR_REGS_OFFSET + S_R4) 34 stm r1!, {r4-r12} 35 str lr, [r1, #4] @ Skip SP_usr (already saved) 36 37 @ Restore guest registers 38 add r0, r0, #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R0) 39 ldr lr, [r0, #S_LR] 40 ldm r0, {r0-r12} 41 42 clrex 43 eret 44ENDPROC(__guest_enter) 45 46ENTRY(__guest_exit) 47 /* 48 * return convention: 49 * guest r0, r1, r2 saved on the stack 50 * r0: vcpu pointer 51 * r1: exception code 52 */ 53 54 add r2, r0, #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R3) 55 stm r2!, {r3-r12} 56 str lr, [r2, #4] 57 add r2, r0, #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R0) 58 pop {r3, r4, r5} @ r0, r1, r2 59 stm r2, {r3-r5} 60 61 ldr r0, [r0, #VCPU_HOST_CTXT] 62 add r0, r0, #(USR_REGS_OFFSET + S_R4) 63 ldm r0!, {r4-r12} 64 ldr lr, [r0, #4] 65 66 mov r0, r1 67 mrs r1, SPSR 68 mrs r2, ELR_hyp 69 mrc p15, 4, r3, c5, c2, 0 @ HSR 70 71 /* 72 * Force loads and stores to complete before unmasking aborts 73 * and forcing the delivery of the exception. This gives us a 74 * single instruction window, which the handler will try to 75 * match. 76 */ 77 dsb sy 78 cpsie a 79 80 .global abort_guest_exit_start 81abort_guest_exit_start: 82 83 isb 84 85 .global abort_guest_exit_end 86abort_guest_exit_end: 87 88 /* 89 * If we took an abort, r0[31] will be set, and cmp will set 90 * the N bit in PSTATE. 91 */ 92 cmp r0, #0 93 msrmi SPSR_cxsf, r1 94 msrmi ELR_hyp, r2 95 mcrmi p15, 4, r3, c5, c2, 0 @ HSR 96 97 bx lr 98ENDPROC(__guest_exit) 99 100/* 101 * If VFPv3 support is not available, then we will not switch the VFP 102 * registers; however cp10 and cp11 accesses will still trap and fallback 103 * to the regular coprocessor emulation code, which currently will 104 * inject an undefined exception to the guest. 105 */ 106#ifdef CONFIG_VFPv3 107ENTRY(__vfp_guest_restore) 108 push {r3, r4, lr} 109 110 @ NEON/VFP used. Turn on VFP access. 111 mrc p15, 4, r1, c1, c1, 2 @ HCPTR 112 bic r1, r1, #(HCPTR_TCP(10) | HCPTR_TCP(11)) 113 mcr p15, 4, r1, c1, c1, 2 @ HCPTR 114 isb 115 116 @ Switch VFP/NEON hardware state to the guest's 117 mov r4, r0 118 ldr r0, [r0, #VCPU_HOST_CTXT] 119 add r0, r0, #CPU_CTXT_VFP 120 bl __vfp_save_state 121 add r0, r4, #(VCPU_GUEST_CTXT + CPU_CTXT_VFP) 122 bl __vfp_restore_state 123 124 pop {r3, r4, lr} 125 pop {r0, r1, r2} 126 clrex 127 eret 128ENDPROC(__vfp_guest_restore) 129#endif 130 131 .popsection 132 133