1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright (C) 2018 Linaro Ltd <ard.biesheuvel@linaro.org>
4 */
5
6#include <linux/linkage.h>
7
8SYM_FUNC_START(__efi_rt_asm_wrapper)
9	stp	x29, x30, [sp, #-112]!
10	mov	x29, sp
11
12	/*
13	 * Register x18 is designated as the 'platform' register by the AAPCS,
14	 * which means firmware running at the same exception level as the OS
15	 * (such as UEFI) should never touch it.
16	 */
17	stp	x1, x18, [sp, #16]
18
19	/*
20	 * Preserve all callee saved registers and record the stack pointer
21	 * value in a per-CPU variable so we can recover from synchronous
22	 * exceptions occurring while running the firmware routines.
23	 */
24	stp	x19, x20, [sp, #32]
25	stp	x21, x22, [sp, #48]
26	stp	x23, x24, [sp, #64]
27	stp	x25, x26, [sp, #80]
28	stp	x27, x28, [sp, #96]
29
30	adr_this_cpu	x8, __efi_rt_asm_recover_sp, x9
31	str		x29, [x8]
32
33	/*
34	 * We are lucky enough that no EFI runtime services take more than
35	 * 5 arguments, so all are passed in registers rather than via the
36	 * stack.
37	 */
38	mov	x8, x0
39	mov	x0, x2
40	mov	x1, x3
41	mov	x2, x4
42	mov	x3, x5
43	mov	x4, x6
44	blr	x8
45
46	ldp	x1, x2, [sp, #16]
47	cmp	x2, x18
48	ldp	x29, x30, [sp], #112
49	b.ne	0f
50	ret
510:
52	/*
53	 * With CONFIG_SHADOW_CALL_STACK, the kernel uses x18 to store a
54	 * shadow stack pointer, which we need to restore before returning to
55	 * potentially instrumented code. This is safe because the wrapper is
56	 * called with preemption disabled and a separate shadow stack is used
57	 * for interrupts.
58	 */
59	mov	x18, x2
60	b	efi_handle_corrupted_x18	// tail call
61SYM_FUNC_END(__efi_rt_asm_wrapper)
62
63SYM_FUNC_START(__efi_rt_asm_recover)
64	ldr_this_cpu	x8, __efi_rt_asm_recover_sp, x9
65	mov		sp, x8
66
67	ldp	x0,  x18, [sp, #16]
68	ldp	x19, x20, [sp, #32]
69	ldp	x21, x22, [sp, #48]
70	ldp	x23, x24, [sp, #64]
71	ldp	x25, x26, [sp, #80]
72	ldp	x27, x28, [sp, #96]
73	ldp	x29, x30, [sp], #112
74
75	b	efi_handle_runtime_exception
76SYM_FUNC_END(__efi_rt_asm_recover)
77