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> 166279017eSWill 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 478bb08411SMark Rutland ubfx x0, x0, #ESR_ELx_EC_SHIFT, #ESR_ELx_EC_WIDTH 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) 65558c303cSJames Morse cbz w1, wa_epilogue 66558c303cSJames Morse 67558c303cSJames Morse eor w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_2 ^ \ 68558c303cSJames Morse ARM_SMCCC_ARCH_WORKAROUND_3) 69f72af90cSMarc Zyngier cbnz w1, el1_trap 70b4f18c06SMarc Zyngier 71b4f18c06SMarc Zyngierwa_epilogue: 72b4f18c06SMarc Zyngier mov x0, xzr 73f72af90cSMarc Zyngier add sp, sp, #16 74f72af90cSMarc Zyngier eret 75679db708SWill Deacon sb 76f72af90cSMarc Zyngier 772b28162cSMarc Zyngierel1_trap: 784464e210SChristoffer Dall get_vcpu_ptr x1, x0 7968381b2bSShanker Donthineni mov x0, #ARM_EXCEPTION_TRAP 802b28162cSMarc Zyngier b __guest_exit 812b28162cSMarc Zyngier 822b28162cSMarc Zyngierel1_irq: 8374501499SMarc Zyngierel1_fiq: 844464e210SChristoffer Dall get_vcpu_ptr x1, x0 8568381b2bSShanker Donthineni mov x0, #ARM_EXCEPTION_IRQ 862b28162cSMarc Zyngier b __guest_exit 872b28162cSMarc Zyngier 881b51e5faSMarc Zyngierel1_error: 894464e210SChristoffer Dall get_vcpu_ptr x1, x0 901b51e5faSMarc Zyngier mov x0, #ARM_EXCEPTION_EL1_SERROR 911b51e5faSMarc Zyngier b __guest_exit 921b51e5faSMarc Zyngier 93e4e11cc0SChristoffer Dallel2_sync: 9488a84cccSJames Morse /* Check for illegal exception return */ 95e4e11cc0SChristoffer Dall mrs x0, spsr_el2 9688a84cccSJames Morse tbnz x0, #20, 1f 97e4e11cc0SChristoffer Dall 9888a84cccSJames Morse save_caller_saved_regs_vect 9988a84cccSJames Morse stp x29, x30, [sp, #-16]! 10088a84cccSJames Morse bl kvm_unexpected_el2_exception 10188a84cccSJames Morse ldp x29, x30, [sp], #16 10288a84cccSJames Morse restore_caller_saved_regs_vect 103e4e11cc0SChristoffer Dall 10488a84cccSJames Morse eret 10588a84cccSJames Morse 10688a84cccSJames Morse1: 107e4e11cc0SChristoffer Dall /* Let's attempt a recovery from the illegal exception return */ 108e4e11cc0SChristoffer Dall get_vcpu_ptr x1, x0 109e4e11cc0SChristoffer Dall mov x0, #ARM_EXCEPTION_IL 110e4e11cc0SChristoffer Dall b __guest_exit 111e4e11cc0SChristoffer Dall 112e4e11cc0SChristoffer Dall 113395ea79eSMarc Zyngierel2_error: 114e9ee186bSJames Morse save_caller_saved_regs_vect 115e9ee186bSJames Morse stp x29, x30, [sp, #-16]! 1167e80f637SMarc Zyngier 117e9ee186bSJames Morse bl kvm_unexpected_el2_exception 118e9ee186bSJames Morse 119e9ee186bSJames Morse ldp x29, x30, [sp], #16 120e9ee186bSJames Morse restore_caller_saved_regs_vect 121e9ee186bSJames Morse 122395ea79eSMarc Zyngier eret 123679db708SWill Deacon sb 124395ea79eSMarc Zyngier 1257db21530SAndrew Scull.macro invalid_vector label, target = __guest_exit_panic 1262b28162cSMarc Zyngier .align 2 127610e4dc8SJoey GoulySYM_CODE_START_LOCAL(\label) 1282b28162cSMarc Zyngier b \target 129617a2f39SMark BrownSYM_CODE_END(\label) 1302b28162cSMarc Zyngier.endm 1312b28162cSMarc Zyngier 1322b28162cSMarc Zyngier /* None of these should ever happen */ 1332b28162cSMarc Zyngier invalid_vector el2t_sync_invalid 1342b28162cSMarc Zyngier invalid_vector el2t_irq_invalid 1352b28162cSMarc Zyngier invalid_vector el2t_fiq_invalid 1362b28162cSMarc Zyngier invalid_vector el2t_error_invalid 1372b28162cSMarc Zyngier invalid_vector el2h_irq_invalid 1382b28162cSMarc Zyngier invalid_vector el2h_fiq_invalid 1392b28162cSMarc Zyngier 1402b28162cSMarc Zyngier .ltorg 1412b28162cSMarc Zyngier 1422b28162cSMarc Zyngier .align 11 1432b28162cSMarc Zyngier 1443dbf100bSJames Morse.macro check_preamble_length start, end 1453dbf100bSJames Morse/* kvm_patch_vector_branch() generates code that jumps over the preamble. */ 1463dbf100bSJames Morse.if ((\end-\start) != KVM_VECTOR_PREAMBLE) 1473dbf100bSJames Morse .error "KVM vector preamble length mismatch" 1483dbf100bSJames Morse.endif 1493dbf100bSJames Morse.endm 1503dbf100bSJames Morse 1517e80f637SMarc Zyngier.macro valid_vect target 1527e80f637SMarc Zyngier .align 7 1533dbf100bSJames Morse661: 1540e5b9c08SJames Morse esb 1557e80f637SMarc Zyngier stp x0, x1, [sp, #-16]! 1563dbf100bSJames Morse662: 157*dcf89d11SMostafa Saleh /* 158*dcf89d11SMostafa Saleh * spectre vectors __bp_harden_hyp_vecs generate br instructions at runtime 159*dcf89d11SMostafa Saleh * that jump at offset 8 at __kvm_hyp_vector. 160*dcf89d11SMostafa Saleh * As hyp .text is guarded section, it needs bti j. 161*dcf89d11SMostafa Saleh */ 162*dcf89d11SMostafa Saleh bti j 1637e80f637SMarc Zyngier b \target 1643dbf100bSJames Morse 1653dbf100bSJames Morsecheck_preamble_length 661b, 662b 1667e80f637SMarc Zyngier.endm 1677e80f637SMarc Zyngier 1687e80f637SMarc Zyngier.macro invalid_vect target 1697e80f637SMarc Zyngier .align 7 1703dbf100bSJames Morse661: 1710e5b9c08SJames Morse nop 1727db21530SAndrew Scull stp x0, x1, [sp, #-16]! 1733dbf100bSJames Morse662: 174*dcf89d11SMostafa Saleh /* Check valid_vect */ 175*dcf89d11SMostafa Saleh bti j 17671dcb8beSMarc Zyngier b \target 1773dbf100bSJames Morse 1783dbf100bSJames Morsecheck_preamble_length 661b, 662b 1797e80f637SMarc Zyngier.endm 1807e80f637SMarc Zyngier 181617a2f39SMark BrownSYM_CODE_START(__kvm_hyp_vector) 1827e80f637SMarc Zyngier invalid_vect el2t_sync_invalid // Synchronous EL2t 1837e80f637SMarc Zyngier invalid_vect el2t_irq_invalid // IRQ EL2t 1847e80f637SMarc Zyngier invalid_vect el2t_fiq_invalid // FIQ EL2t 1857e80f637SMarc Zyngier invalid_vect el2t_error_invalid // Error EL2t 1862b28162cSMarc Zyngier 187e4e11cc0SChristoffer Dall valid_vect el2_sync // Synchronous EL2h 1887e80f637SMarc Zyngier invalid_vect el2h_irq_invalid // IRQ EL2h 1897e80f637SMarc Zyngier invalid_vect el2h_fiq_invalid // FIQ EL2h 1907e80f637SMarc Zyngier valid_vect el2_error // Error EL2h 1912b28162cSMarc Zyngier 1927e80f637SMarc Zyngier valid_vect el1_sync // Synchronous 64-bit EL1 1937e80f637SMarc Zyngier valid_vect el1_irq // IRQ 64-bit EL1 19474501499SMarc Zyngier valid_vect el1_fiq // FIQ 64-bit EL1 1957e80f637SMarc Zyngier valid_vect el1_error // Error 64-bit EL1 1962b28162cSMarc Zyngier 1977e80f637SMarc Zyngier valid_vect el1_sync // Synchronous 32-bit EL1 1987e80f637SMarc Zyngier valid_vect el1_irq // IRQ 32-bit EL1 19974501499SMarc Zyngier valid_vect el1_fiq // FIQ 32-bit EL1 2007e80f637SMarc Zyngier valid_vect el1_error // Error 32-bit EL1 201617a2f39SMark BrownSYM_CODE_END(__kvm_hyp_vector) 202e8b22d0fSMarc Zyngier 203b881cdceSWill Deacon.macro spectrev2_smccc_wa1_smc 204b881cdceSWill Deacon sub sp, sp, #(8 * 4) 205b881cdceSWill Deacon stp x2, x3, [sp, #(8 * 0)] 206b881cdceSWill Deacon stp x0, x1, [sp, #(8 * 2)] 2074c0bd995SMark Rutland alternative_cb ARM64_ALWAYS_SYSTEM, spectre_bhb_patch_wa3 208558c303cSJames Morse /* Patched to mov WA3 when supported */ 209b881cdceSWill Deacon mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1 210558c303cSJames Morse alternative_cb_end 211b881cdceSWill Deacon smc #0 212b881cdceSWill Deacon ldp x2, x3, [sp, #(8 * 0)] 213b881cdceSWill Deacon add sp, sp, #(8 * 2) 214b881cdceSWill Deacon.endm 215b881cdceSWill Deacon 216b881cdceSWill Deacon.macro hyp_ventry indirect, spectrev2 217e8b22d0fSMarc Zyngier .align 7 2180e5b9c08SJames Morse1: esb 219b881cdceSWill Deacon .if \spectrev2 != 0 220b881cdceSWill Deacon spectrev2_smccc_wa1_smc 221b881cdceSWill Deacon .else 222b881cdceSWill Deacon stp x0, x1, [sp, #-16]! 223558c303cSJames Morse mitigate_spectre_bhb_loop x0 224228a26b9SJames Morse mitigate_spectre_bhb_clear_insn 225b881cdceSWill Deacon .endif 226b881cdceSWill Deacon .if \indirect != 0 2274c0bd995SMark Rutland alternative_cb ARM64_ALWAYS_SYSTEM, kvm_patch_vector_branch 228e8b22d0fSMarc Zyngier /* 229c4792b6dSWill Deacon * For ARM64_SPECTRE_V3A configurations, these NOPs get replaced with: 230e8b22d0fSMarc Zyngier * 231e8b22d0fSMarc Zyngier * movz x0, #(addr & 0xffff) 232e8b22d0fSMarc Zyngier * movk x0, #((addr >> 16) & 0xffff), lsl #16 233e8b22d0fSMarc Zyngier * movk x0, #((addr >> 32) & 0xffff), lsl #32 234e8b22d0fSMarc Zyngier * br x0 235e8b22d0fSMarc Zyngier * 2363dbf100bSJames Morse * Where: 2373dbf100bSJames Morse * addr = kern_hyp_va(__kvm_hyp_vector) + vector-offset + KVM_VECTOR_PREAMBLE. 238e8b22d0fSMarc Zyngier * See kvm_patch_vector_branch for details. 239e8b22d0fSMarc Zyngier */ 240b881cdceSWill Deacon nop 241e8b22d0fSMarc Zyngier nop 242e8b22d0fSMarc Zyngier nop 243e8b22d0fSMarc Zyngier nop 244e8b22d0fSMarc Zyngier alternative_cb_end 245b881cdceSWill Deacon .endif 246b881cdceSWill Deacon b __kvm_hyp_vector + (1b - 0b + KVM_VECTOR_PREAMBLE) 247e8b22d0fSMarc Zyngier.endm 248e8b22d0fSMarc Zyngier 249b881cdceSWill Deacon.macro generate_vectors indirect, spectrev2 250e8b22d0fSMarc Zyngier0: 251e8b22d0fSMarc Zyngier .rept 16 252b881cdceSWill Deacon hyp_ventry \indirect, \spectrev2 253e8b22d0fSMarc Zyngier .endr 254e8b22d0fSMarc Zyngier .org 0b + SZ_2K // Safety measure 255e8b22d0fSMarc Zyngier.endm 256e8b22d0fSMarc Zyngier 257e8b22d0fSMarc Zyngier .align 11 2586e52aab9SMark BrownSYM_CODE_START(__bp_harden_hyp_vecs) 259b881cdceSWill Deacon generate_vectors indirect = 0, spectrev2 = 1 // HYP_VECTOR_SPECTRE_DIRECT 260b881cdceSWill Deacon generate_vectors indirect = 1, spectrev2 = 0 // HYP_VECTOR_INDIRECT 261b881cdceSWill Deacon generate_vectors indirect = 1, spectrev2 = 1 // HYP_VECTOR_SPECTRE_INDIRECT 2626e52aab9SMark Brown1: .org __bp_harden_hyp_vecs + __BP_HARDEN_HYP_VECS_SZ 2636e52aab9SMark Brown .org 1b 2646e52aab9SMark BrownSYM_CODE_END(__bp_harden_hyp_vecs) 265