1caab277bSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 22b28162cSMarc Zyngier/* 3e8b22d0fSMarc Zyngier * Copyright (C) 2015-2018 - ARM Ltd 42b28162cSMarc Zyngier * Author: Marc Zyngier <marc.zyngier@arm.com> 52b28162cSMarc Zyngier */ 62b28162cSMarc Zyngier 7f72af90cSMarc Zyngier#include <linux/arm-smccc.h> 82b28162cSMarc Zyngier#include <linux/linkage.h> 92b28162cSMarc Zyngier 102b28162cSMarc Zyngier#include <asm/alternative.h> 112b28162cSMarc Zyngier#include <asm/assembler.h> 122b28162cSMarc Zyngier#include <asm/cpufeature.h> 132b28162cSMarc Zyngier#include <asm/kvm_arm.h> 142b28162cSMarc Zyngier#include <asm/kvm_asm.h> 15e8b22d0fSMarc Zyngier#include <asm/mmu.h> 162b28162cSMarc Zyngier 17e9ee186bSJames Morse.macro save_caller_saved_regs_vect 18e9ee186bSJames Morse /* x0 and x1 were saved in the vector entry */ 19e9ee186bSJames Morse stp x2, x3, [sp, #-16]! 20e9ee186bSJames Morse stp x4, x5, [sp, #-16]! 21e9ee186bSJames Morse stp x6, x7, [sp, #-16]! 22e9ee186bSJames Morse stp x8, x9, [sp, #-16]! 23e9ee186bSJames Morse stp x10, x11, [sp, #-16]! 24e9ee186bSJames Morse stp x12, x13, [sp, #-16]! 25e9ee186bSJames Morse stp x14, x15, [sp, #-16]! 26e9ee186bSJames Morse stp x16, x17, [sp, #-16]! 27e9ee186bSJames Morse.endm 28e9ee186bSJames Morse 29e9ee186bSJames Morse.macro restore_caller_saved_regs_vect 30e9ee186bSJames Morse ldp x16, x17, [sp], #16 31e9ee186bSJames Morse ldp x14, x15, [sp], #16 32e9ee186bSJames Morse ldp x12, x13, [sp], #16 33e9ee186bSJames Morse ldp x10, x11, [sp], #16 34e9ee186bSJames Morse ldp x8, x9, [sp], #16 35e9ee186bSJames Morse ldp x6, x7, [sp], #16 36e9ee186bSJames Morse ldp x4, x5, [sp], #16 37e9ee186bSJames Morse ldp x2, x3, [sp], #16 38e9ee186bSJames Morse ldp x0, x1, [sp], #16 39e9ee186bSJames Morse.endm 40e9ee186bSJames Morse 412b28162cSMarc Zyngier .text 422b28162cSMarc Zyngier 432b28162cSMarc Zyngierel1_sync: // Guest trapped into EL2 442b28162cSMarc Zyngier 454464e210SChristoffer Dall mrs x0, esr_el2 464464e210SChristoffer Dall lsr x0, x0, #ESR_ELx_EC_SHIFT 4768381b2bSShanker Donthineni cmp x0, #ESR_ELx_EC_HVC64 48f72af90cSMarc Zyngier ccmp x0, #ESR_ELx_EC_HVC32, #4, ne 492b28162cSMarc Zyngier b.ne el1_trap 502b28162cSMarc Zyngier 51f72af90cSMarc Zyngier /* 52f72af90cSMarc Zyngier * Fastest possible path for ARM_SMCCC_ARCH_WORKAROUND_1. 53f72af90cSMarc Zyngier * The workaround has already been applied on the host, 54f72af90cSMarc Zyngier * so let's quickly get back to the guest. We don't bother 55f72af90cSMarc Zyngier * restoring x1, as it can be clobbered anyway. 56f72af90cSMarc Zyngier */ 57f72af90cSMarc Zyngier ldr x1, [sp] // Guest's x0 58f72af90cSMarc Zyngier eor w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1 59b4f18c06SMarc Zyngier cbz w1, wa_epilogue 60b4f18c06SMarc Zyngier 61b4f18c06SMarc Zyngier /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */ 62b4f18c06SMarc Zyngier eor w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_1 ^ \ 63b4f18c06SMarc Zyngier ARM_SMCCC_ARCH_WORKAROUND_2) 64f72af90cSMarc Zyngier cbnz w1, el1_trap 65b4f18c06SMarc Zyngier 66b4f18c06SMarc Zyngier#ifdef CONFIG_ARM64_SSBD 67b4f18c06SMarc Zyngieralternative_cb arm64_enable_wa2_handling 68b4f18c06SMarc Zyngier b wa2_end 69b4f18c06SMarc Zyngieralternative_cb_end 70b4f18c06SMarc Zyngier get_vcpu_ptr x2, x0 71b4f18c06SMarc Zyngier ldr x0, [x2, #VCPU_WORKAROUND_FLAGS] 72b4f18c06SMarc Zyngier 73b4f18c06SMarc Zyngier // Sanitize the argument and update the guest flags 74b4f18c06SMarc Zyngier ldr x1, [sp, #8] // Guest's x1 75b4f18c06SMarc Zyngier clz w1, w1 // Murphy's device: 76b4f18c06SMarc Zyngier lsr w1, w1, #5 // w1 = !!w1 without using 77b4f18c06SMarc Zyngier eor w1, w1, #1 // the flags... 78b4f18c06SMarc Zyngier bfi x0, x1, #VCPU_WORKAROUND_2_FLAG_SHIFT, #1 79b4f18c06SMarc Zyngier str x0, [x2, #VCPU_WORKAROUND_FLAGS] 80b4f18c06SMarc Zyngier 81b4f18c06SMarc Zyngier /* Check that we actually need to perform the call */ 82b4f18c06SMarc Zyngier hyp_ldr_this_cpu x0, arm64_ssbd_callback_required, x2 83b4f18c06SMarc Zyngier cbz x0, wa2_end 84b4f18c06SMarc Zyngier 85b4f18c06SMarc Zyngier mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2 86b4f18c06SMarc Zyngier smc #0 87b4f18c06SMarc Zyngier 88b4f18c06SMarc Zyngier /* Don't leak data from the SMC call */ 89b4f18c06SMarc Zyngier mov x3, xzr 90b4f18c06SMarc Zyngierwa2_end: 91b4f18c06SMarc Zyngier mov x2, xzr 92b4f18c06SMarc Zyngier mov x1, xzr 93b4f18c06SMarc Zyngier#endif 94b4f18c06SMarc Zyngier 95b4f18c06SMarc Zyngierwa_epilogue: 96b4f18c06SMarc Zyngier mov x0, xzr 97f72af90cSMarc Zyngier add sp, sp, #16 98f72af90cSMarc Zyngier eret 99679db708SWill Deacon sb 100f72af90cSMarc Zyngier 1012b28162cSMarc Zyngierel1_trap: 1024464e210SChristoffer Dall get_vcpu_ptr x1, x0 10368381b2bSShanker Donthineni mov x0, #ARM_EXCEPTION_TRAP 1042b28162cSMarc Zyngier b __guest_exit 1052b28162cSMarc Zyngier 1062b28162cSMarc Zyngierel1_irq: 1074464e210SChristoffer Dall get_vcpu_ptr x1, x0 10868381b2bSShanker Donthineni mov x0, #ARM_EXCEPTION_IRQ 1092b28162cSMarc Zyngier b __guest_exit 1102b28162cSMarc Zyngier 1111b51e5faSMarc Zyngierel1_error: 1124464e210SChristoffer Dall get_vcpu_ptr x1, x0 1131b51e5faSMarc Zyngier mov x0, #ARM_EXCEPTION_EL1_SERROR 1141b51e5faSMarc Zyngier b __guest_exit 1151b51e5faSMarc Zyngier 116e4e11cc0SChristoffer Dallel2_sync: 11788a84cccSJames Morse /* Check for illegal exception return */ 118e4e11cc0SChristoffer Dall mrs x0, spsr_el2 11988a84cccSJames Morse tbnz x0, #20, 1f 120e4e11cc0SChristoffer Dall 12188a84cccSJames Morse save_caller_saved_regs_vect 12288a84cccSJames Morse stp x29, x30, [sp, #-16]! 12388a84cccSJames Morse bl kvm_unexpected_el2_exception 12488a84cccSJames Morse ldp x29, x30, [sp], #16 12588a84cccSJames Morse restore_caller_saved_regs_vect 126e4e11cc0SChristoffer Dall 12788a84cccSJames Morse eret 12888a84cccSJames Morse 12988a84cccSJames Morse1: 130e4e11cc0SChristoffer Dall /* Let's attempt a recovery from the illegal exception return */ 131e4e11cc0SChristoffer Dall get_vcpu_ptr x1, x0 132e4e11cc0SChristoffer Dall mov x0, #ARM_EXCEPTION_IL 133e4e11cc0SChristoffer Dall b __guest_exit 134e4e11cc0SChristoffer Dall 135e4e11cc0SChristoffer Dall 136395ea79eSMarc Zyngierel2_error: 137e9ee186bSJames Morse save_caller_saved_regs_vect 138e9ee186bSJames Morse stp x29, x30, [sp, #-16]! 1397e80f637SMarc Zyngier 140e9ee186bSJames Morse bl kvm_unexpected_el2_exception 141e9ee186bSJames Morse 142e9ee186bSJames Morse ldp x29, x30, [sp], #16 143e9ee186bSJames Morse restore_caller_saved_regs_vect 144e9ee186bSJames Morse 145395ea79eSMarc Zyngier eret 146679db708SWill Deacon sb 147395ea79eSMarc Zyngier 148*7db21530SAndrew Scull.macro invalid_vector label, target = __guest_exit_panic 1492b28162cSMarc Zyngier .align 2 150617a2f39SMark BrownSYM_CODE_START(\label) 1512b28162cSMarc Zyngier b \target 152617a2f39SMark BrownSYM_CODE_END(\label) 1532b28162cSMarc Zyngier.endm 1542b28162cSMarc Zyngier 1552b28162cSMarc Zyngier /* None of these should ever happen */ 1562b28162cSMarc Zyngier invalid_vector el2t_sync_invalid 1572b28162cSMarc Zyngier invalid_vector el2t_irq_invalid 1582b28162cSMarc Zyngier invalid_vector el2t_fiq_invalid 1592b28162cSMarc Zyngier invalid_vector el2t_error_invalid 1602b28162cSMarc Zyngier invalid_vector el2h_irq_invalid 1612b28162cSMarc Zyngier invalid_vector el2h_fiq_invalid 1622b28162cSMarc Zyngier invalid_vector el1_fiq_invalid 1632b28162cSMarc Zyngier 1642b28162cSMarc Zyngier .ltorg 1652b28162cSMarc Zyngier 1662b28162cSMarc Zyngier .align 11 1672b28162cSMarc Zyngier 1683dbf100bSJames Morse.macro check_preamble_length start, end 1693dbf100bSJames Morse/* kvm_patch_vector_branch() generates code that jumps over the preamble. */ 1703dbf100bSJames Morse.if ((\end-\start) != KVM_VECTOR_PREAMBLE) 1713dbf100bSJames Morse .error "KVM vector preamble length mismatch" 1723dbf100bSJames Morse.endif 1733dbf100bSJames Morse.endm 1743dbf100bSJames Morse 1757e80f637SMarc Zyngier.macro valid_vect target 1767e80f637SMarc Zyngier .align 7 1773dbf100bSJames Morse661: 1780e5b9c08SJames Morse esb 1797e80f637SMarc Zyngier stp x0, x1, [sp, #-16]! 1803dbf100bSJames Morse662: 1817e80f637SMarc Zyngier b \target 1823dbf100bSJames Morse 1833dbf100bSJames Morsecheck_preamble_length 661b, 662b 1847e80f637SMarc Zyngier.endm 1857e80f637SMarc Zyngier 1867e80f637SMarc Zyngier.macro invalid_vect target 1877e80f637SMarc Zyngier .align 7 1883dbf100bSJames Morse661: 1890e5b9c08SJames Morse nop 190*7db21530SAndrew Scull stp x0, x1, [sp, #-16]! 1913dbf100bSJames Morse662: 19271dcb8beSMarc Zyngier b \target 1933dbf100bSJames Morse 1943dbf100bSJames Morsecheck_preamble_length 661b, 662b 1957e80f637SMarc Zyngier.endm 1967e80f637SMarc Zyngier 197617a2f39SMark BrownSYM_CODE_START(__kvm_hyp_vector) 1987e80f637SMarc Zyngier invalid_vect el2t_sync_invalid // Synchronous EL2t 1997e80f637SMarc Zyngier invalid_vect el2t_irq_invalid // IRQ EL2t 2007e80f637SMarc Zyngier invalid_vect el2t_fiq_invalid // FIQ EL2t 2017e80f637SMarc Zyngier invalid_vect el2t_error_invalid // Error EL2t 2022b28162cSMarc Zyngier 203e4e11cc0SChristoffer Dall valid_vect el2_sync // Synchronous EL2h 2047e80f637SMarc Zyngier invalid_vect el2h_irq_invalid // IRQ EL2h 2057e80f637SMarc Zyngier invalid_vect el2h_fiq_invalid // FIQ EL2h 2067e80f637SMarc Zyngier valid_vect el2_error // Error EL2h 2072b28162cSMarc Zyngier 2087e80f637SMarc Zyngier valid_vect el1_sync // Synchronous 64-bit EL1 2097e80f637SMarc Zyngier valid_vect el1_irq // IRQ 64-bit EL1 2107e80f637SMarc Zyngier invalid_vect el1_fiq_invalid // FIQ 64-bit EL1 2117e80f637SMarc Zyngier valid_vect el1_error // Error 64-bit EL1 2122b28162cSMarc Zyngier 2137e80f637SMarc Zyngier valid_vect el1_sync // Synchronous 32-bit EL1 2147e80f637SMarc Zyngier valid_vect el1_irq // IRQ 32-bit EL1 2157e80f637SMarc Zyngier invalid_vect el1_fiq_invalid // FIQ 32-bit EL1 2167e80f637SMarc Zyngier valid_vect el1_error // Error 32-bit EL1 217617a2f39SMark BrownSYM_CODE_END(__kvm_hyp_vector) 218e8b22d0fSMarc Zyngier 219e8b22d0fSMarc Zyngier#ifdef CONFIG_KVM_INDIRECT_VECTORS 220e8b22d0fSMarc Zyngier.macro hyp_ventry 221e8b22d0fSMarc Zyngier .align 7 2220e5b9c08SJames Morse1: esb 2230e5b9c08SJames Morse .rept 26 224e8b22d0fSMarc Zyngier nop 225e8b22d0fSMarc Zyngier .endr 226e8b22d0fSMarc Zyngier/* 227e8b22d0fSMarc Zyngier * The default sequence is to directly branch to the KVM vectors, 228e8b22d0fSMarc Zyngier * using the computed offset. This applies for VHE as well as 2295d994374SJames Morse * !ARM64_HARDEN_EL2_VECTORS. The first vector must always run the preamble. 230e8b22d0fSMarc Zyngier * 231e8b22d0fSMarc Zyngier * For ARM64_HARDEN_EL2_VECTORS configurations, this gets replaced 232e8b22d0fSMarc Zyngier * with: 233e8b22d0fSMarc Zyngier * 234e8b22d0fSMarc Zyngier * stp x0, x1, [sp, #-16]! 235e8b22d0fSMarc Zyngier * movz x0, #(addr & 0xffff) 236e8b22d0fSMarc Zyngier * movk x0, #((addr >> 16) & 0xffff), lsl #16 237e8b22d0fSMarc Zyngier * movk x0, #((addr >> 32) & 0xffff), lsl #32 238e8b22d0fSMarc Zyngier * br x0 239e8b22d0fSMarc Zyngier * 2403dbf100bSJames Morse * Where: 2413dbf100bSJames Morse * addr = kern_hyp_va(__kvm_hyp_vector) + vector-offset + KVM_VECTOR_PREAMBLE. 242e8b22d0fSMarc Zyngier * See kvm_patch_vector_branch for details. 243e8b22d0fSMarc Zyngier */ 244e8b22d0fSMarc Zyngieralternative_cb kvm_patch_vector_branch 2455d994374SJames Morse stp x0, x1, [sp, #-16]! 2465d994374SJames Morse b __kvm_hyp_vector + (1b - 0b + KVM_VECTOR_PREAMBLE) 247e8b22d0fSMarc Zyngier nop 248e8b22d0fSMarc Zyngier nop 249e8b22d0fSMarc Zyngier nop 250e8b22d0fSMarc Zyngieralternative_cb_end 251e8b22d0fSMarc Zyngier.endm 252e8b22d0fSMarc Zyngier 253e8b22d0fSMarc Zyngier.macro generate_vectors 254e8b22d0fSMarc Zyngier0: 255e8b22d0fSMarc Zyngier .rept 16 256e8b22d0fSMarc Zyngier hyp_ventry 257e8b22d0fSMarc Zyngier .endr 258e8b22d0fSMarc Zyngier .org 0b + SZ_2K // Safety measure 259e8b22d0fSMarc Zyngier.endm 260e8b22d0fSMarc Zyngier 261e8b22d0fSMarc Zyngier .align 11 2626e52aab9SMark BrownSYM_CODE_START(__bp_harden_hyp_vecs) 263e8b22d0fSMarc Zyngier .rept BP_HARDEN_EL2_SLOTS 264e8b22d0fSMarc Zyngier generate_vectors 265e8b22d0fSMarc Zyngier .endr 2666e52aab9SMark Brown1: .org __bp_harden_hyp_vecs + __BP_HARDEN_HYP_VECS_SZ 2676e52aab9SMark Brown .org 1b 2686e52aab9SMark BrownSYM_CODE_END(__bp_harden_hyp_vecs) 269e8b22d0fSMarc Zyngier#endif 270