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> 16*6279017eSWill Deacon#include <asm/spectre.h> 172b28162cSMarc Zyngier 18e9ee186bSJames Morse.macro save_caller_saved_regs_vect 19e9ee186bSJames Morse /* x0 and x1 were saved in the vector entry */ 20e9ee186bSJames Morse stp x2, x3, [sp, #-16]! 21e9ee186bSJames Morse stp x4, x5, [sp, #-16]! 22e9ee186bSJames Morse stp x6, x7, [sp, #-16]! 23e9ee186bSJames Morse stp x8, x9, [sp, #-16]! 24e9ee186bSJames Morse stp x10, x11, [sp, #-16]! 25e9ee186bSJames Morse stp x12, x13, [sp, #-16]! 26e9ee186bSJames Morse stp x14, x15, [sp, #-16]! 27e9ee186bSJames Morse stp x16, x17, [sp, #-16]! 28e9ee186bSJames Morse.endm 29e9ee186bSJames Morse 30e9ee186bSJames Morse.macro restore_caller_saved_regs_vect 31e9ee186bSJames Morse ldp x16, x17, [sp], #16 32e9ee186bSJames Morse ldp x14, x15, [sp], #16 33e9ee186bSJames Morse ldp x12, x13, [sp], #16 34e9ee186bSJames Morse ldp x10, x11, [sp], #16 35e9ee186bSJames Morse ldp x8, x9, [sp], #16 36e9ee186bSJames Morse ldp x6, x7, [sp], #16 37e9ee186bSJames Morse ldp x4, x5, [sp], #16 38e9ee186bSJames Morse ldp x2, x3, [sp], #16 39e9ee186bSJames Morse ldp x0, x1, [sp], #16 40e9ee186bSJames Morse.endm 41e9ee186bSJames Morse 422b28162cSMarc Zyngier .text 432b28162cSMarc Zyngier 442b28162cSMarc Zyngierel1_sync: // Guest trapped into EL2 452b28162cSMarc Zyngier 464464e210SChristoffer Dall mrs x0, esr_el2 474464e210SChristoffer Dall lsr x0, x0, #ESR_ELx_EC_SHIFT 4868381b2bSShanker Donthineni cmp x0, #ESR_ELx_EC_HVC64 49f72af90cSMarc Zyngier ccmp x0, #ESR_ELx_EC_HVC32, #4, ne 502b28162cSMarc Zyngier b.ne el1_trap 512b28162cSMarc Zyngier 52f72af90cSMarc Zyngier /* 53f72af90cSMarc Zyngier * Fastest possible path for ARM_SMCCC_ARCH_WORKAROUND_1. 54f72af90cSMarc Zyngier * The workaround has already been applied on the host, 55f72af90cSMarc Zyngier * so let's quickly get back to the guest. We don't bother 56f72af90cSMarc Zyngier * restoring x1, as it can be clobbered anyway. 57f72af90cSMarc Zyngier */ 58f72af90cSMarc Zyngier ldr x1, [sp] // Guest's x0 59f72af90cSMarc Zyngier eor w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1 60b4f18c06SMarc Zyngier cbz w1, wa_epilogue 61b4f18c06SMarc Zyngier 62b4f18c06SMarc Zyngier /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */ 63b4f18c06SMarc Zyngier eor w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_1 ^ \ 64b4f18c06SMarc Zyngier ARM_SMCCC_ARCH_WORKAROUND_2) 65f72af90cSMarc Zyngier cbnz w1, el1_trap 66b4f18c06SMarc Zyngier 67b4f18c06SMarc Zyngierwa_epilogue: 68b4f18c06SMarc Zyngier mov x0, xzr 69f72af90cSMarc Zyngier add sp, sp, #16 70f72af90cSMarc Zyngier eret 71679db708SWill Deacon sb 72f72af90cSMarc Zyngier 732b28162cSMarc Zyngierel1_trap: 744464e210SChristoffer Dall get_vcpu_ptr x1, x0 7568381b2bSShanker Donthineni mov x0, #ARM_EXCEPTION_TRAP 762b28162cSMarc Zyngier b __guest_exit 772b28162cSMarc Zyngier 782b28162cSMarc Zyngierel1_irq: 794464e210SChristoffer Dall get_vcpu_ptr x1, x0 8068381b2bSShanker Donthineni mov x0, #ARM_EXCEPTION_IRQ 812b28162cSMarc Zyngier b __guest_exit 822b28162cSMarc Zyngier 831b51e5faSMarc Zyngierel1_error: 844464e210SChristoffer Dall get_vcpu_ptr x1, x0 851b51e5faSMarc Zyngier mov x0, #ARM_EXCEPTION_EL1_SERROR 861b51e5faSMarc Zyngier b __guest_exit 871b51e5faSMarc Zyngier 88e4e11cc0SChristoffer Dallel2_sync: 8988a84cccSJames Morse /* Check for illegal exception return */ 90e4e11cc0SChristoffer Dall mrs x0, spsr_el2 9188a84cccSJames Morse tbnz x0, #20, 1f 92e4e11cc0SChristoffer Dall 9388a84cccSJames Morse save_caller_saved_regs_vect 9488a84cccSJames Morse stp x29, x30, [sp, #-16]! 9588a84cccSJames Morse bl kvm_unexpected_el2_exception 9688a84cccSJames Morse ldp x29, x30, [sp], #16 9788a84cccSJames Morse restore_caller_saved_regs_vect 98e4e11cc0SChristoffer Dall 9988a84cccSJames Morse eret 10088a84cccSJames Morse 10188a84cccSJames Morse1: 102e4e11cc0SChristoffer Dall /* Let's attempt a recovery from the illegal exception return */ 103e4e11cc0SChristoffer Dall get_vcpu_ptr x1, x0 104e4e11cc0SChristoffer Dall mov x0, #ARM_EXCEPTION_IL 105e4e11cc0SChristoffer Dall b __guest_exit 106e4e11cc0SChristoffer Dall 107e4e11cc0SChristoffer Dall 108395ea79eSMarc Zyngierel2_error: 109e9ee186bSJames Morse save_caller_saved_regs_vect 110e9ee186bSJames Morse stp x29, x30, [sp, #-16]! 1117e80f637SMarc Zyngier 112e9ee186bSJames Morse bl kvm_unexpected_el2_exception 113e9ee186bSJames Morse 114e9ee186bSJames Morse ldp x29, x30, [sp], #16 115e9ee186bSJames Morse restore_caller_saved_regs_vect 116e9ee186bSJames Morse 117395ea79eSMarc Zyngier eret 118679db708SWill Deacon sb 119395ea79eSMarc Zyngier 1207db21530SAndrew Scull.macro invalid_vector label, target = __guest_exit_panic 1212b28162cSMarc Zyngier .align 2 122617a2f39SMark BrownSYM_CODE_START(\label) 1232b28162cSMarc Zyngier b \target 124617a2f39SMark BrownSYM_CODE_END(\label) 1252b28162cSMarc Zyngier.endm 1262b28162cSMarc Zyngier 1272b28162cSMarc Zyngier /* None of these should ever happen */ 1282b28162cSMarc Zyngier invalid_vector el2t_sync_invalid 1292b28162cSMarc Zyngier invalid_vector el2t_irq_invalid 1302b28162cSMarc Zyngier invalid_vector el2t_fiq_invalid 1312b28162cSMarc Zyngier invalid_vector el2t_error_invalid 1322b28162cSMarc Zyngier invalid_vector el2h_irq_invalid 1332b28162cSMarc Zyngier invalid_vector el2h_fiq_invalid 1342b28162cSMarc Zyngier invalid_vector el1_fiq_invalid 1352b28162cSMarc Zyngier 1362b28162cSMarc Zyngier .ltorg 1372b28162cSMarc Zyngier 1382b28162cSMarc Zyngier .align 11 1392b28162cSMarc Zyngier 1403dbf100bSJames Morse.macro check_preamble_length start, end 1413dbf100bSJames Morse/* kvm_patch_vector_branch() generates code that jumps over the preamble. */ 1423dbf100bSJames Morse.if ((\end-\start) != KVM_VECTOR_PREAMBLE) 1433dbf100bSJames Morse .error "KVM vector preamble length mismatch" 1443dbf100bSJames Morse.endif 1453dbf100bSJames Morse.endm 1463dbf100bSJames Morse 1477e80f637SMarc Zyngier.macro valid_vect target 1487e80f637SMarc Zyngier .align 7 1493dbf100bSJames Morse661: 1500e5b9c08SJames Morse esb 1517e80f637SMarc Zyngier stp x0, x1, [sp, #-16]! 1523dbf100bSJames Morse662: 1537e80f637SMarc Zyngier b \target 1543dbf100bSJames Morse 1553dbf100bSJames Morsecheck_preamble_length 661b, 662b 1567e80f637SMarc Zyngier.endm 1577e80f637SMarc Zyngier 1587e80f637SMarc Zyngier.macro invalid_vect target 1597e80f637SMarc Zyngier .align 7 1603dbf100bSJames Morse661: 1610e5b9c08SJames Morse nop 1627db21530SAndrew Scull stp x0, x1, [sp, #-16]! 1633dbf100bSJames Morse662: 16471dcb8beSMarc Zyngier b \target 1653dbf100bSJames Morse 1663dbf100bSJames Morsecheck_preamble_length 661b, 662b 1677e80f637SMarc Zyngier.endm 1687e80f637SMarc Zyngier 169617a2f39SMark BrownSYM_CODE_START(__kvm_hyp_vector) 1707e80f637SMarc Zyngier invalid_vect el2t_sync_invalid // Synchronous EL2t 1717e80f637SMarc Zyngier invalid_vect el2t_irq_invalid // IRQ EL2t 1727e80f637SMarc Zyngier invalid_vect el2t_fiq_invalid // FIQ EL2t 1737e80f637SMarc Zyngier invalid_vect el2t_error_invalid // Error EL2t 1742b28162cSMarc Zyngier 175e4e11cc0SChristoffer Dall valid_vect el2_sync // Synchronous EL2h 1767e80f637SMarc Zyngier invalid_vect el2h_irq_invalid // IRQ EL2h 1777e80f637SMarc Zyngier invalid_vect el2h_fiq_invalid // FIQ EL2h 1787e80f637SMarc Zyngier valid_vect el2_error // Error EL2h 1792b28162cSMarc Zyngier 1807e80f637SMarc Zyngier valid_vect el1_sync // Synchronous 64-bit EL1 1817e80f637SMarc Zyngier valid_vect el1_irq // IRQ 64-bit EL1 1827e80f637SMarc Zyngier invalid_vect el1_fiq_invalid // FIQ 64-bit EL1 1837e80f637SMarc Zyngier valid_vect el1_error // Error 64-bit EL1 1842b28162cSMarc Zyngier 1857e80f637SMarc Zyngier valid_vect el1_sync // Synchronous 32-bit EL1 1867e80f637SMarc Zyngier valid_vect el1_irq // IRQ 32-bit EL1 1877e80f637SMarc Zyngier invalid_vect el1_fiq_invalid // FIQ 32-bit EL1 1887e80f637SMarc Zyngier valid_vect el1_error // Error 32-bit EL1 189617a2f39SMark BrownSYM_CODE_END(__kvm_hyp_vector) 190e8b22d0fSMarc Zyngier 191e8b22d0fSMarc Zyngier.macro hyp_ventry 192e8b22d0fSMarc Zyngier .align 7 1930e5b9c08SJames Morse1: esb 1940e5b9c08SJames Morse .rept 26 195e8b22d0fSMarc Zyngier nop 196e8b22d0fSMarc Zyngier .endr 197e8b22d0fSMarc Zyngier/* 198e8b22d0fSMarc Zyngier * The default sequence is to directly branch to the KVM vectors, 199e8b22d0fSMarc Zyngier * using the computed offset. This applies for VHE as well as 2005d994374SJames Morse * !ARM64_HARDEN_EL2_VECTORS. The first vector must always run the preamble. 201e8b22d0fSMarc Zyngier * 202e8b22d0fSMarc Zyngier * For ARM64_HARDEN_EL2_VECTORS configurations, this gets replaced 203e8b22d0fSMarc Zyngier * with: 204e8b22d0fSMarc Zyngier * 205e8b22d0fSMarc Zyngier * stp x0, x1, [sp, #-16]! 206e8b22d0fSMarc Zyngier * movz x0, #(addr & 0xffff) 207e8b22d0fSMarc Zyngier * movk x0, #((addr >> 16) & 0xffff), lsl #16 208e8b22d0fSMarc Zyngier * movk x0, #((addr >> 32) & 0xffff), lsl #32 209e8b22d0fSMarc Zyngier * br x0 210e8b22d0fSMarc Zyngier * 2113dbf100bSJames Morse * Where: 2123dbf100bSJames Morse * addr = kern_hyp_va(__kvm_hyp_vector) + vector-offset + KVM_VECTOR_PREAMBLE. 213e8b22d0fSMarc Zyngier * See kvm_patch_vector_branch for details. 214e8b22d0fSMarc Zyngier */ 215e8b22d0fSMarc Zyngieralternative_cb kvm_patch_vector_branch 2165d994374SJames Morse stp x0, x1, [sp, #-16]! 2175d994374SJames Morse b __kvm_hyp_vector + (1b - 0b + KVM_VECTOR_PREAMBLE) 218e8b22d0fSMarc Zyngier nop 219e8b22d0fSMarc Zyngier nop 220e8b22d0fSMarc Zyngier nop 221e8b22d0fSMarc Zyngieralternative_cb_end 222e8b22d0fSMarc Zyngier.endm 223e8b22d0fSMarc Zyngier 224e8b22d0fSMarc Zyngier.macro generate_vectors 225e8b22d0fSMarc Zyngier0: 226e8b22d0fSMarc Zyngier .rept 16 227e8b22d0fSMarc Zyngier hyp_ventry 228e8b22d0fSMarc Zyngier .endr 229e8b22d0fSMarc Zyngier .org 0b + SZ_2K // Safety measure 230e8b22d0fSMarc Zyngier.endm 231e8b22d0fSMarc Zyngier 232e8b22d0fSMarc Zyngier .align 11 2336e52aab9SMark BrownSYM_CODE_START(__bp_harden_hyp_vecs) 234e8b22d0fSMarc Zyngier .rept BP_HARDEN_EL2_SLOTS 235e8b22d0fSMarc Zyngier generate_vectors 236e8b22d0fSMarc Zyngier .endr 2376e52aab9SMark Brown1: .org __bp_harden_hyp_vecs + __BP_HARDEN_HYP_VECS_SZ 2386e52aab9SMark Brown .org 1b 2396e52aab9SMark BrownSYM_CODE_END(__bp_harden_hyp_vecs) 240