xref: /openbmc/linux/arch/arm64/kvm/hyp/hyp-entry.S (revision 0edbfea5)
1/*
2 * Copyright (C) 2015 - ARM Ltd
3 * Author: Marc Zyngier <marc.zyngier@arm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/linkage.h>
19
20#include <asm/alternative.h>
21#include <asm/assembler.h>
22#include <asm/cpufeature.h>
23#include <asm/kvm_arm.h>
24#include <asm/kvm_asm.h>
25#include <asm/kvm_mmu.h>
26
27	.text
28	.pushsection	.hyp.text, "ax"
29
30.macro	save_x0_to_x3
31	stp	x0, x1, [sp, #-16]!
32	stp	x2, x3, [sp, #-16]!
33.endm
34
35.macro	restore_x0_to_x3
36	ldp	x2, x3, [sp], #16
37	ldp	x0, x1, [sp], #16
38.endm
39
40.macro do_el2_call
41	/*
42	 * Shuffle the parameters before calling the function
43	 * pointed to in x0. Assumes parameters in x[1,2,3].
44	 */
45	mov	lr, x0
46	mov	x0, x1
47	mov	x1, x2
48	mov	x2, x3
49	blr	lr
50.endm
51
52ENTRY(__vhe_hyp_call)
53	str	lr, [sp, #-16]!
54	do_el2_call
55	ldr	lr, [sp], #16
56	/*
57	 * We used to rely on having an exception return to get
58	 * an implicit isb. In the E2H case, we don't have it anymore.
59	 * rather than changing all the leaf functions, just do it here
60	 * before returning to the rest of the kernel.
61	 */
62	isb
63	ret
64ENDPROC(__vhe_hyp_call)
65
66el1_sync:				// Guest trapped into EL2
67	save_x0_to_x3
68
69alternative_if_not ARM64_HAS_VIRT_HOST_EXTN
70	mrs	x1, esr_el2
71alternative_else
72	mrs	x1, esr_el1
73alternative_endif
74	lsr	x2, x1, #ESR_ELx_EC_SHIFT
75
76	cmp	x2, #ESR_ELx_EC_HVC64
77	b.ne	el1_trap
78
79	mrs	x3, vttbr_el2		// If vttbr is valid, the 64bit guest
80	cbnz	x3, el1_trap		// called HVC
81
82	/* Here, we're pretty sure the host called HVC. */
83	restore_x0_to_x3
84
85	cmp	x0, #HVC_GET_VECTORS
86	b.ne	1f
87	mrs	x0, vbar_el2
88	b	2f
89
901:
91	/*
92	 * Perform the EL2 call
93	 */
94	kern_hyp_va	x0
95	do_el2_call
96
972:	eret
98
99el1_trap:
100	/*
101	 * x1: ESR
102	 * x2: ESR_EC
103	 */
104
105	/* Guest accessed VFP/SIMD registers, save host, restore Guest */
106	cmp	x2, #ESR_ELx_EC_FP_ASIMD
107	b.eq	__fpsimd_guest_restore
108
109	mrs	x0, tpidr_el2
110	mov	x1, #ARM_EXCEPTION_TRAP
111	b	__guest_exit
112
113el1_irq:
114	save_x0_to_x3
115	mrs	x0, tpidr_el2
116	mov	x1, #ARM_EXCEPTION_IRQ
117	b	__guest_exit
118
119ENTRY(__hyp_do_panic)
120	mov	lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
121		      PSR_MODE_EL1h)
122	msr	spsr_el2, lr
123	ldr	lr, =panic
124	msr	elr_el2, lr
125	eret
126ENDPROC(__hyp_do_panic)
127
128.macro invalid_vector	label, target = __hyp_panic
129	.align	2
130\label:
131	b \target
132ENDPROC(\label)
133.endm
134
135	/* None of these should ever happen */
136	invalid_vector	el2t_sync_invalid
137	invalid_vector	el2t_irq_invalid
138	invalid_vector	el2t_fiq_invalid
139	invalid_vector	el2t_error_invalid
140	invalid_vector	el2h_sync_invalid
141	invalid_vector	el2h_irq_invalid
142	invalid_vector	el2h_fiq_invalid
143	invalid_vector	el2h_error_invalid
144	invalid_vector	el1_sync_invalid
145	invalid_vector	el1_irq_invalid
146	invalid_vector	el1_fiq_invalid
147	invalid_vector	el1_error_invalid
148
149	.ltorg
150
151	.align 11
152
153ENTRY(__kvm_hyp_vector)
154	ventry	el2t_sync_invalid		// Synchronous EL2t
155	ventry	el2t_irq_invalid		// IRQ EL2t
156	ventry	el2t_fiq_invalid		// FIQ EL2t
157	ventry	el2t_error_invalid		// Error EL2t
158
159	ventry	el2h_sync_invalid		// Synchronous EL2h
160	ventry	el2h_irq_invalid		// IRQ EL2h
161	ventry	el2h_fiq_invalid		// FIQ EL2h
162	ventry	el2h_error_invalid		// Error EL2h
163
164	ventry	el1_sync			// Synchronous 64-bit EL1
165	ventry	el1_irq				// IRQ 64-bit EL1
166	ventry	el1_fiq_invalid			// FIQ 64-bit EL1
167	ventry	el1_error_invalid		// Error 64-bit EL1
168
169	ventry	el1_sync			// Synchronous 32-bit EL1
170	ventry	el1_irq				// IRQ 32-bit EL1
171	ventry	el1_fiq_invalid			// FIQ 32-bit EL1
172	ventry	el1_error_invalid		// Error 32-bit EL1
173ENDPROC(__kvm_hyp_vector)
174