xref: /linux/tools/testing/selftests/kvm/lib/arm64/handlers.S (revision 1260ed77798502de9c98020040d2995008de10cc)
1*67730e6cSSean Christopherson/* SPDX-License-Identifier: GPL-2.0 */
2*67730e6cSSean Christopherson.macro save_registers
3*67730e6cSSean Christopherson	add	sp, sp, #-16 * 17
4*67730e6cSSean Christopherson
5*67730e6cSSean Christopherson	stp	x0, x1, [sp, #16 * 0]
6*67730e6cSSean Christopherson	stp	x2, x3, [sp, #16 * 1]
7*67730e6cSSean Christopherson	stp	x4, x5, [sp, #16 * 2]
8*67730e6cSSean Christopherson	stp	x6, x7, [sp, #16 * 3]
9*67730e6cSSean Christopherson	stp	x8, x9, [sp, #16 * 4]
10*67730e6cSSean Christopherson	stp	x10, x11, [sp, #16 * 5]
11*67730e6cSSean Christopherson	stp	x12, x13, [sp, #16 * 6]
12*67730e6cSSean Christopherson	stp	x14, x15, [sp, #16 * 7]
13*67730e6cSSean Christopherson	stp	x16, x17, [sp, #16 * 8]
14*67730e6cSSean Christopherson	stp	x18, x19, [sp, #16 * 9]
15*67730e6cSSean Christopherson	stp	x20, x21, [sp, #16 * 10]
16*67730e6cSSean Christopherson	stp	x22, x23, [sp, #16 * 11]
17*67730e6cSSean Christopherson	stp	x24, x25, [sp, #16 * 12]
18*67730e6cSSean Christopherson	stp	x26, x27, [sp, #16 * 13]
19*67730e6cSSean Christopherson	stp	x28, x29, [sp, #16 * 14]
20*67730e6cSSean Christopherson
21*67730e6cSSean Christopherson	/*
22*67730e6cSSean Christopherson	 * This stores sp_el1 into ex_regs.sp so exception handlers can "look"
23*67730e6cSSean Christopherson	 * at it. It will _not_ be used to restore the sp on return from the
24*67730e6cSSean Christopherson	 * exception so handlers can not update it.
25*67730e6cSSean Christopherson	 */
26*67730e6cSSean Christopherson	add	x1, sp, #16 * 17
27*67730e6cSSean Christopherson	stp	x30, x1, [sp, #16 * 15] /* x30, SP */
28*67730e6cSSean Christopherson
29*67730e6cSSean Christopherson	mrs	x1, elr_el1
30*67730e6cSSean Christopherson	mrs	x2, spsr_el1
31*67730e6cSSean Christopherson	stp	x1, x2, [sp, #16 * 16] /* PC, PSTATE */
32*67730e6cSSean Christopherson.endm
33*67730e6cSSean Christopherson
34*67730e6cSSean Christopherson.macro restore_registers
35*67730e6cSSean Christopherson	ldp	x1, x2, [sp, #16 * 16] /* PC, PSTATE */
36*67730e6cSSean Christopherson	msr	elr_el1, x1
37*67730e6cSSean Christopherson	msr	spsr_el1, x2
38*67730e6cSSean Christopherson
39*67730e6cSSean Christopherson	/* sp is not restored */
40*67730e6cSSean Christopherson	ldp	x30, xzr, [sp, #16 * 15] /* x30, SP */
41*67730e6cSSean Christopherson
42*67730e6cSSean Christopherson	ldp	x28, x29, [sp, #16 * 14]
43*67730e6cSSean Christopherson	ldp	x26, x27, [sp, #16 * 13]
44*67730e6cSSean Christopherson	ldp	x24, x25, [sp, #16 * 12]
45*67730e6cSSean Christopherson	ldp	x22, x23, [sp, #16 * 11]
46*67730e6cSSean Christopherson	ldp	x20, x21, [sp, #16 * 10]
47*67730e6cSSean Christopherson	ldp	x18, x19, [sp, #16 * 9]
48*67730e6cSSean Christopherson	ldp	x16, x17, [sp, #16 * 8]
49*67730e6cSSean Christopherson	ldp	x14, x15, [sp, #16 * 7]
50*67730e6cSSean Christopherson	ldp	x12, x13, [sp, #16 * 6]
51*67730e6cSSean Christopherson	ldp	x10, x11, [sp, #16 * 5]
52*67730e6cSSean Christopherson	ldp	x8, x9, [sp, #16 * 4]
53*67730e6cSSean Christopherson	ldp	x6, x7, [sp, #16 * 3]
54*67730e6cSSean Christopherson	ldp	x4, x5, [sp, #16 * 2]
55*67730e6cSSean Christopherson	ldp	x2, x3, [sp, #16 * 1]
56*67730e6cSSean Christopherson	ldp	x0, x1, [sp, #16 * 0]
57*67730e6cSSean Christopherson
58*67730e6cSSean Christopherson	add	sp, sp, #16 * 17
59*67730e6cSSean Christopherson
60*67730e6cSSean Christopherson	eret
61*67730e6cSSean Christopherson.endm
62*67730e6cSSean Christopherson
63*67730e6cSSean Christopherson.pushsection ".entry.text", "ax"
64*67730e6cSSean Christopherson.balign 0x800
65*67730e6cSSean Christopherson.global vectors
66*67730e6cSSean Christophersonvectors:
67*67730e6cSSean Christopherson.popsection
68*67730e6cSSean Christopherson
69*67730e6cSSean Christopherson.set	vector, 0
70*67730e6cSSean Christopherson
71*67730e6cSSean Christopherson/*
72*67730e6cSSean Christopherson * Build an exception handler for vector and append a jump to it into
73*67730e6cSSean Christopherson * vectors (while making sure that it's 0x80 aligned).
74*67730e6cSSean Christopherson */
75*67730e6cSSean Christopherson.macro HANDLER, label
76*67730e6cSSean Christophersonhandler_\label:
77*67730e6cSSean Christopherson	save_registers
78*67730e6cSSean Christopherson	mov	x0, sp
79*67730e6cSSean Christopherson	mov	x1, #vector
80*67730e6cSSean Christopherson	bl	route_exception
81*67730e6cSSean Christopherson	restore_registers
82*67730e6cSSean Christopherson
83*67730e6cSSean Christopherson.pushsection ".entry.text", "ax"
84*67730e6cSSean Christopherson.balign 0x80
85*67730e6cSSean Christopherson	b	handler_\label
86*67730e6cSSean Christopherson.popsection
87*67730e6cSSean Christopherson
88*67730e6cSSean Christopherson.set	vector, vector + 1
89*67730e6cSSean Christopherson.endm
90*67730e6cSSean Christopherson
91*67730e6cSSean Christopherson.macro HANDLER_INVALID
92*67730e6cSSean Christopherson.pushsection ".entry.text", "ax"
93*67730e6cSSean Christopherson.balign 0x80
94*67730e6cSSean Christopherson/* This will abort so no need to save and restore registers. */
95*67730e6cSSean Christopherson	mov	x0, #vector
96*67730e6cSSean Christopherson	mov	x1, #0 /* ec */
97*67730e6cSSean Christopherson	mov	x2, #0 /* valid_ec */
98*67730e6cSSean Christopherson	b	kvm_exit_unexpected_exception
99*67730e6cSSean Christopherson.popsection
100*67730e6cSSean Christopherson
101*67730e6cSSean Christopherson.set	vector, vector + 1
102*67730e6cSSean Christopherson.endm
103*67730e6cSSean Christopherson
104*67730e6cSSean Christopherson/*
105*67730e6cSSean Christopherson * Caution: be sure to not add anything between the declaration of vectors
106*67730e6cSSean Christopherson * above and these macro calls that will build the vectors table below it.
107*67730e6cSSean Christopherson */
108*67730e6cSSean Christopherson	HANDLER_INVALID                         // Synchronous EL1t
109*67730e6cSSean Christopherson	HANDLER_INVALID                         // IRQ EL1t
110*67730e6cSSean Christopherson	HANDLER_INVALID                         // FIQ EL1t
111*67730e6cSSean Christopherson	HANDLER_INVALID                         // Error EL1t
112*67730e6cSSean Christopherson
113*67730e6cSSean Christopherson	HANDLER	el1h_sync                       // Synchronous EL1h
114*67730e6cSSean Christopherson	HANDLER	el1h_irq                        // IRQ EL1h
115*67730e6cSSean Christopherson	HANDLER el1h_fiq                        // FIQ EL1h
116*67730e6cSSean Christopherson	HANDLER	el1h_error                      // Error EL1h
117*67730e6cSSean Christopherson
118*67730e6cSSean Christopherson	HANDLER	el0_sync_64                     // Synchronous 64-bit EL0
119*67730e6cSSean Christopherson	HANDLER	el0_irq_64                      // IRQ 64-bit EL0
120*67730e6cSSean Christopherson	HANDLER	el0_fiq_64                      // FIQ 64-bit EL0
121*67730e6cSSean Christopherson	HANDLER	el0_error_64                    // Error 64-bit EL0
122*67730e6cSSean Christopherson
123*67730e6cSSean Christopherson	HANDLER	el0_sync_32                     // Synchronous 32-bit EL0
124*67730e6cSSean Christopherson	HANDLER	el0_irq_32                      // IRQ 32-bit EL0
125*67730e6cSSean Christopherson	HANDLER	el0_fiq_32                      // FIQ 32-bit EL0
126*67730e6cSSean Christopherson	HANDLER	el0_error_32                    // Error 32-bit EL0
127