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