xref: /openbmc/linux/arch/arm64/kvm/hyp/nvhe/host.S (revision 6e3bfbb2)
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (C) 2020 - Google Inc
4 * Author: Andrew Scull <ascull@google.com>
5 */
6
7#include <linux/linkage.h>
8
9#include <asm/assembler.h>
10#include <asm/kvm_asm.h>
11#include <asm/kvm_mmu.h>
12
13	.text
14
15SYM_FUNC_START(__hyp_do_panic)
16	mov	lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
17		      PSR_MODE_EL1h)
18	msr	spsr_el2, lr
19	ldr	lr, =panic
20	msr	elr_el2, lr
21	eret
22	sb
23SYM_FUNC_END(__hyp_do_panic)
24
25.macro host_el1_sync_vect
26	.align 7
27.L__vect_start\@:
28	esb
29	stp	x0, x1, [sp, #-16]!
30	mrs	x0, esr_el2
31	lsr	x0, x0, #ESR_ELx_EC_SHIFT
32	cmp	x0, #ESR_ELx_EC_HVC64
33	ldp	x0, x1, [sp], #16
34	b.ne	hyp_panic
35
36	/* Check for a stub HVC call */
37	cmp	x0, #HVC_STUB_HCALL_NR
38	b.hs	1f
39
40	/*
41	 * Compute the idmap address of __kvm_handle_stub_hvc and
42	 * jump there. Since we use kimage_voffset, do not use the
43	 * HYP VA for __kvm_handle_stub_hvc, but the kernel VA instead
44	 * (by loading it from the constant pool).
45	 *
46	 * Preserve x0-x4, which may contain stub parameters.
47	 */
48	ldr	x5, =__kvm_handle_stub_hvc
49	ldr_l	x6, kimage_voffset
50
51	/* x5 = __pa(x5) */
52	sub	x5, x5, x6
53	br	x5
54
551:
56	/*
57	 * Shuffle the parameters before calling the function
58	 * pointed to in x0. Assumes parameters in x[1,2,3].
59	 */
60	kern_hyp_va	x0
61	str	lr, [sp, #-16]!
62	mov	lr, x0
63	mov	x0, x1
64	mov	x1, x2
65	mov	x2, x3
66	blr	lr
67	ldr	lr, [sp], #16
68
69	eret
70	sb
71.L__vect_end\@:
72.if ((.L__vect_end\@ - .L__vect_start\@) > 0x80)
73	.error "host_el1_sync_vect larger than vector entry"
74.endif
75.endm
76
77.macro invalid_host_vect
78	.align 7
79	b	hyp_panic
80.endm
81
82/*
83 * CONFIG_KVM_INDIRECT_VECTORS is not applied to the host vectors because the
84 * host knows about the EL2 vectors already, and there is no point in hiding
85 * them.
86 */
87	.align 11
88SYM_CODE_START(__kvm_hyp_host_vector)
89	invalid_host_vect			// Synchronous EL2t
90	invalid_host_vect			// IRQ EL2t
91	invalid_host_vect			// FIQ EL2t
92	invalid_host_vect			// Error EL2t
93
94	invalid_host_vect			// Synchronous EL2h
95	invalid_host_vect			// IRQ EL2h
96	invalid_host_vect			// FIQ EL2h
97	invalid_host_vect			// Error EL2h
98
99	host_el1_sync_vect			// Synchronous 64-bit EL1
100	invalid_host_vect			// IRQ 64-bit EL1
101	invalid_host_vect			// FIQ 64-bit EL1
102	invalid_host_vect			// Error 64-bit EL1
103
104	invalid_host_vect			// Synchronous 32-bit EL1
105	invalid_host_vect			// IRQ 32-bit EL1
106	invalid_host_vect			// FIQ 32-bit EL1
107	invalid_host_vect			// Error 32-bit EL1
108SYM_CODE_END(__kvm_hyp_host_vector)
109