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