xref: /openbmc/linux/arch/arm64/kvm/hyp/hyp-entry.S (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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