xref: /openbmc/linux/arch/arm64/kvm/hyp/hyp-entry.S (revision 74501499d4e0d4ba59ab2bc6be1873716549169d)
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
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:
79*74501499SMarc Zyngierel1_fiq:
804464e210SChristoffer Dall	get_vcpu_ptr	x1, x0
8168381b2bSShanker Donthineni	mov	x0, #ARM_EXCEPTION_IRQ
822b28162cSMarc Zyngier	b	__guest_exit
832b28162cSMarc Zyngier
841b51e5faSMarc Zyngierel1_error:
854464e210SChristoffer Dall	get_vcpu_ptr	x1, x0
861b51e5faSMarc Zyngier	mov	x0, #ARM_EXCEPTION_EL1_SERROR
871b51e5faSMarc Zyngier	b	__guest_exit
881b51e5faSMarc Zyngier
89e4e11cc0SChristoffer Dallel2_sync:
9088a84cccSJames Morse	/* Check for illegal exception return */
91e4e11cc0SChristoffer Dall	mrs	x0, spsr_el2
9288a84cccSJames Morse	tbnz	x0, #20, 1f
93e4e11cc0SChristoffer Dall
9488a84cccSJames Morse	save_caller_saved_regs_vect
9588a84cccSJames Morse	stp     x29, x30, [sp, #-16]!
9688a84cccSJames Morse	bl	kvm_unexpected_el2_exception
9788a84cccSJames Morse	ldp     x29, x30, [sp], #16
9888a84cccSJames Morse	restore_caller_saved_regs_vect
99e4e11cc0SChristoffer Dall
10088a84cccSJames Morse	eret
10188a84cccSJames Morse
10288a84cccSJames Morse1:
103e4e11cc0SChristoffer Dall	/* Let's attempt a recovery from the illegal exception return */
104e4e11cc0SChristoffer Dall	get_vcpu_ptr	x1, x0
105e4e11cc0SChristoffer Dall	mov	x0, #ARM_EXCEPTION_IL
106e4e11cc0SChristoffer Dall	b	__guest_exit
107e4e11cc0SChristoffer Dall
108e4e11cc0SChristoffer Dall
109395ea79eSMarc Zyngierel2_error:
110e9ee186bSJames Morse	save_caller_saved_regs_vect
111e9ee186bSJames Morse	stp     x29, x30, [sp, #-16]!
1127e80f637SMarc Zyngier
113e9ee186bSJames Morse	bl	kvm_unexpected_el2_exception
114e9ee186bSJames Morse
115e9ee186bSJames Morse	ldp     x29, x30, [sp], #16
116e9ee186bSJames Morse	restore_caller_saved_regs_vect
117e9ee186bSJames Morse
118395ea79eSMarc Zyngier	eret
119679db708SWill Deacon	sb
120395ea79eSMarc Zyngier
1217db21530SAndrew Scull.macro invalid_vector	label, target = __guest_exit_panic
1222b28162cSMarc Zyngier	.align	2
123610e4dc8SJoey GoulySYM_CODE_START_LOCAL(\label)
1242b28162cSMarc Zyngier	b \target
125617a2f39SMark BrownSYM_CODE_END(\label)
1262b28162cSMarc Zyngier.endm
1272b28162cSMarc Zyngier
1282b28162cSMarc Zyngier	/* None of these should ever happen */
1292b28162cSMarc Zyngier	invalid_vector	el2t_sync_invalid
1302b28162cSMarc Zyngier	invalid_vector	el2t_irq_invalid
1312b28162cSMarc Zyngier	invalid_vector	el2t_fiq_invalid
1322b28162cSMarc Zyngier	invalid_vector	el2t_error_invalid
1332b28162cSMarc Zyngier	invalid_vector	el2h_irq_invalid
1342b28162cSMarc Zyngier	invalid_vector	el2h_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
182*74501499SMarc Zyngier	valid_vect	el1_fiq			// 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
187*74501499SMarc Zyngier	valid_vect	el1_fiq			// FIQ 32-bit EL1
1887e80f637SMarc Zyngier	valid_vect	el1_error		// Error 32-bit EL1
189617a2f39SMark BrownSYM_CODE_END(__kvm_hyp_vector)
190e8b22d0fSMarc Zyngier
191b881cdceSWill Deacon.macro spectrev2_smccc_wa1_smc
192b881cdceSWill Deacon	sub	sp, sp, #(8 * 4)
193b881cdceSWill Deacon	stp	x2, x3, [sp, #(8 * 0)]
194b881cdceSWill Deacon	stp	x0, x1, [sp, #(8 * 2)]
195b881cdceSWill Deacon	mov	w0, #ARM_SMCCC_ARCH_WORKAROUND_1
196b881cdceSWill Deacon	smc	#0
197b881cdceSWill Deacon	ldp	x2, x3, [sp, #(8 * 0)]
198b881cdceSWill Deacon	add	sp, sp, #(8 * 2)
199b881cdceSWill Deacon.endm
200b881cdceSWill Deacon
201b881cdceSWill Deacon.macro hyp_ventry	indirect, spectrev2
202e8b22d0fSMarc Zyngier	.align	7
2030e5b9c08SJames Morse1:	esb
204b881cdceSWill Deacon	.if \spectrev2 != 0
205b881cdceSWill Deacon	spectrev2_smccc_wa1_smc
206b881cdceSWill Deacon	.else
207b881cdceSWill Deacon	stp	x0, x1, [sp, #-16]!
208b881cdceSWill Deacon	.endif
209b881cdceSWill Deacon	.if \indirect != 0
210b881cdceSWill Deacon	alternative_cb  kvm_patch_vector_branch
211e8b22d0fSMarc Zyngier	/*
212c4792b6dSWill Deacon	 * For ARM64_SPECTRE_V3A configurations, these NOPs get replaced with:
213e8b22d0fSMarc Zyngier	 *
214e8b22d0fSMarc Zyngier	 * movz	x0, #(addr & 0xffff)
215e8b22d0fSMarc Zyngier	 * movk	x0, #((addr >> 16) & 0xffff), lsl #16
216e8b22d0fSMarc Zyngier	 * movk	x0, #((addr >> 32) & 0xffff), lsl #32
217e8b22d0fSMarc Zyngier	 * br	x0
218e8b22d0fSMarc Zyngier	 *
2193dbf100bSJames Morse	 * Where:
2203dbf100bSJames Morse	 * addr = kern_hyp_va(__kvm_hyp_vector) + vector-offset + KVM_VECTOR_PREAMBLE.
221e8b22d0fSMarc Zyngier	 * See kvm_patch_vector_branch for details.
222e8b22d0fSMarc Zyngier	 */
223b881cdceSWill Deacon	nop
224e8b22d0fSMarc Zyngier	nop
225e8b22d0fSMarc Zyngier	nop
226e8b22d0fSMarc Zyngier	nop
227e8b22d0fSMarc Zyngier	alternative_cb_end
228b881cdceSWill Deacon	.endif
229b881cdceSWill Deacon	b	__kvm_hyp_vector + (1b - 0b + KVM_VECTOR_PREAMBLE)
230e8b22d0fSMarc Zyngier.endm
231e8b22d0fSMarc Zyngier
232b881cdceSWill Deacon.macro generate_vectors	indirect, spectrev2
233e8b22d0fSMarc Zyngier0:
234e8b22d0fSMarc Zyngier	.rept 16
235b881cdceSWill Deacon	hyp_ventry	\indirect, \spectrev2
236e8b22d0fSMarc Zyngier	.endr
237e8b22d0fSMarc Zyngier	.org 0b + SZ_2K		// Safety measure
238e8b22d0fSMarc Zyngier.endm
239e8b22d0fSMarc Zyngier
240e8b22d0fSMarc Zyngier	.align	11
2416e52aab9SMark BrownSYM_CODE_START(__bp_harden_hyp_vecs)
242b881cdceSWill Deacon	generate_vectors indirect = 0, spectrev2 = 1 // HYP_VECTOR_SPECTRE_DIRECT
243b881cdceSWill Deacon	generate_vectors indirect = 1, spectrev2 = 0 // HYP_VECTOR_INDIRECT
244b881cdceSWill Deacon	generate_vectors indirect = 1, spectrev2 = 1 // HYP_VECTOR_SPECTRE_INDIRECT
2456e52aab9SMark Brown1:	.org __bp_harden_hyp_vecs + __BP_HARDEN_HYP_VECS_SZ
2466e52aab9SMark Brown	.org 1b
2476e52aab9SMark BrownSYM_CODE_END(__bp_harden_hyp_vecs)
248