xref: /qemu/linux-user/ppc/vdso.S (revision ec6f3fc3)
1/*
2 * PowerPC linux replacement vdso.
3 *
4 * Copyright 2023 Linaro, Ltd.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include <asm/unistd.h>
10#include <asm/errno.h>
11
12#ifndef _ARCH_PPC64
13# define TARGET_ABI32
14#endif
15#include "vdso-asmoffset.h"
16
17
18	.text
19
20.macro endf name
21	.globl	\name
22	.size	\name, .-\name
23	/* For PPC64, functions have special linkage; we export pointers. */
24#ifndef _ARCH_PPC64
25	.type	\name, @function
26#endif
27.endm
28
29.macro raw_syscall nr
30	addi	0, 0, \nr
31	sc
32.endm
33
34.macro vdso_syscall name, nr
35\name:
36	raw_syscall \nr
37	blr
38endf	\name
39.endm
40
41	.cfi_startproc
42
43vdso_syscall __kernel_gettimeofday, __NR_gettimeofday
44vdso_syscall __kernel_clock_gettime, __NR_clock_gettime
45vdso_syscall __kernel_clock_getres, __NR_clock_getres
46vdso_syscall __kernel_getcpu, __NR_getcpu
47vdso_syscall __kernel_time, __NR_time
48
49#ifdef __NR_clock_gettime64
50vdso_syscall __kernel_clock_gettime64, __NR_clock_gettime64
51#endif
52
53__kernel_sync_dicache:
54	/* qemu does not need to flush caches */
55	blr
56endf	__kernel_sync_dicache
57
58	.cfi_endproc
59
60/*
61 * TODO: __kernel_get_tbfreq
62 * This is probably a constant for QEMU.
63 */
64
65/*
66 * Start the unwind info at least one instruction before the signal
67 * trampoline, because the unwinder will assume we are returning
68 * after a call site.
69 */
70
71	.cfi_startproc simple
72	.cfi_signal_frame
73
74#ifdef _ARCH_PPC64
75# define __kernel_sigtramp_rt  __kernel_sigtramp_rt64
76# define sizeof_reg	8
77#else
78# define __kernel_sigtramp_rt  __kernel_sigtramp_rt32
79# define sizeof_reg	4
80#endif
81#define sizeof_freg	8
82#define sizeof_vreg	16
83
84	.cfi_def_cfa	1, SIGNAL_FRAMESIZE + offsetof_rt_sigframe_mcontext
85
86	/* Return address */
87	.cfi_return_column 67
88	.cfi_offset	67, 32 * sizeof_reg		/* nip */
89
90	/* Integer registers */
91	.cfi_offset	0, 0 * sizeof_reg
92	.cfi_offset	1, 1 * sizeof_reg
93	.cfi_offset	2, 2 * sizeof_reg
94	.cfi_offset	3, 3 * sizeof_reg
95	.cfi_offset	4, 4 * sizeof_reg
96	.cfi_offset	5, 5 * sizeof_reg
97	.cfi_offset	6, 6 * sizeof_reg
98	.cfi_offset	7, 7 * sizeof_reg
99	.cfi_offset	8, 8 * sizeof_reg
100	.cfi_offset	9, 9 * sizeof_reg
101	.cfi_offset	10, 10 * sizeof_reg
102	.cfi_offset	11, 11 * sizeof_reg
103	.cfi_offset	12, 12 * sizeof_reg
104	.cfi_offset	13, 13 * sizeof_reg
105	.cfi_offset	14, 14 * sizeof_reg
106	.cfi_offset	15, 15 * sizeof_reg
107	.cfi_offset	16, 16 * sizeof_reg
108	.cfi_offset	17, 17 * sizeof_reg
109	.cfi_offset	18, 18 * sizeof_reg
110	.cfi_offset	19, 19 * sizeof_reg
111	.cfi_offset	20, 20 * sizeof_reg
112	.cfi_offset	21, 21 * sizeof_reg
113	.cfi_offset	22, 22 * sizeof_reg
114	.cfi_offset	23, 23 * sizeof_reg
115	.cfi_offset	24, 24 * sizeof_reg
116	.cfi_offset	25, 25 * sizeof_reg
117	.cfi_offset	26, 26 * sizeof_reg
118	.cfi_offset	27, 27 * sizeof_reg
119	.cfi_offset	28, 28 * sizeof_reg
120	.cfi_offset	29, 29 * sizeof_reg
121	.cfi_offset	30, 30 * sizeof_reg
122	.cfi_offset	31, 31 * sizeof_reg
123	.cfi_offset	65, 36 * sizeof_reg		/* lr */
124	.cfi_offset	70, 38 * sizeof_reg		/* ccr */
125
126	/* Floating point registers */
127	.cfi_offset	32, offsetof_mcontext_fregs
128	.cfi_offset	33, offsetof_mcontext_fregs + 1 * sizeof_freg
129	.cfi_offset	34, offsetof_mcontext_fregs + 2 * sizeof_freg
130	.cfi_offset	35, offsetof_mcontext_fregs + 3 * sizeof_freg
131	.cfi_offset	36, offsetof_mcontext_fregs + 4 * sizeof_freg
132	.cfi_offset	37, offsetof_mcontext_fregs + 5 * sizeof_freg
133	.cfi_offset	38, offsetof_mcontext_fregs + 6 * sizeof_freg
134	.cfi_offset	39, offsetof_mcontext_fregs + 7 * sizeof_freg
135	.cfi_offset	40, offsetof_mcontext_fregs + 8 * sizeof_freg
136	.cfi_offset	41, offsetof_mcontext_fregs + 9 * sizeof_freg
137	.cfi_offset	42, offsetof_mcontext_fregs + 10 * sizeof_freg
138	.cfi_offset	43, offsetof_mcontext_fregs + 11 * sizeof_freg
139	.cfi_offset	44, offsetof_mcontext_fregs + 12 * sizeof_freg
140	.cfi_offset	45, offsetof_mcontext_fregs + 13 * sizeof_freg
141	.cfi_offset	46, offsetof_mcontext_fregs + 14 * sizeof_freg
142	.cfi_offset	47, offsetof_mcontext_fregs + 15 * sizeof_freg
143	.cfi_offset	48, offsetof_mcontext_fregs + 16 * sizeof_freg
144	.cfi_offset	49, offsetof_mcontext_fregs + 17 * sizeof_freg
145	.cfi_offset	50, offsetof_mcontext_fregs + 18 * sizeof_freg
146	.cfi_offset	51, offsetof_mcontext_fregs + 19 * sizeof_freg
147	.cfi_offset	52, offsetof_mcontext_fregs + 20 * sizeof_freg
148	.cfi_offset	53, offsetof_mcontext_fregs + 21 * sizeof_freg
149	.cfi_offset	54, offsetof_mcontext_fregs + 22 * sizeof_freg
150	.cfi_offset	55, offsetof_mcontext_fregs + 23 * sizeof_freg
151	.cfi_offset	56, offsetof_mcontext_fregs + 24 * sizeof_freg
152	.cfi_offset	57, offsetof_mcontext_fregs + 25 * sizeof_freg
153	.cfi_offset	58, offsetof_mcontext_fregs + 26 * sizeof_freg
154	.cfi_offset	59, offsetof_mcontext_fregs + 27 * sizeof_freg
155	.cfi_offset	60, offsetof_mcontext_fregs + 28 * sizeof_freg
156	.cfi_offset	61, offsetof_mcontext_fregs + 29 * sizeof_freg
157	.cfi_offset	62, offsetof_mcontext_fregs + 30 * sizeof_freg
158	.cfi_offset	63, offsetof_mcontext_fregs + 31 * sizeof_freg
159
160	/*
161	 * Unlike the kernel, unconditionally represent the Altivec/VSX regs.
162	 * The space within the stack frame is always available, and most of
163	 * our supported processors have them enabled.  The only complication
164	 * for PPC64 is the misalignment, so that we have to use indirection.
165	 */
166.macro	save_vreg_ofs reg, ofs
167#ifdef _ARCH_PPC64
168	/*
169	 * vreg = *(cfa + offsetof(v_regs)) + ofs
170         *
171         * The CFA is input to the expression on the stack, so:
172	 * DW_CFA_expression reg, length (7),
173         *   DW_OP_plus_uconst (0x23), vreg_ptr, DW_OP_deref (0x06),
174	 *   DW_OP_plus_uconst (0x23), ofs
175	 */
176	.cfi_escape 0x10, 77 + \reg, 7, 0x23, (offsetof_mcontext_vregs_ptr & 0x7f) + 0x80, offsetof_mcontext_vregs_ptr >> 7, 0x06, 0x23, (\ofs & 0x7f) | 0x80, \ofs >> 7
177#else
178	.cfi_offset 77 + \reg, offsetof_mcontext_vregs + \ofs
179#endif
180.endm
181
182.macro	save_vreg reg
183	save_vreg_ofs \reg, (\reg * sizeof_vreg)
184.endm
185
186	save_vreg   0
187	save_vreg   1
188	save_vreg   2
189	save_vreg   3
190	save_vreg   4
191	save_vreg   5
192	save_vreg   6
193	save_vreg   7
194	save_vreg   8
195	save_vreg   9
196	save_vreg  10
197	save_vreg  11
198	save_vreg  12
199	save_vreg  13
200	save_vreg  14
201	save_vreg  15
202	save_vreg  16
203	save_vreg  17
204	save_vreg  18
205	save_vreg  19
206	save_vreg  20
207	save_vreg  21
208	save_vreg  22
209	save_vreg  23
210	save_vreg  24
211	save_vreg  25
212	save_vreg  26
213	save_vreg  27
214	save_vreg  28
215	save_vreg  29
216	save_vreg  30
217	save_vreg  31
218	save_vreg  32
219	save_vreg_ofs 33, (32 * sizeof_vreg + 12)
220
221	nop
222
223__kernel_sigtramp_rt:
224	raw_syscall __NR_rt_sigreturn
225endf	__kernel_sigtramp_rt
226
227#ifndef _ARCH_PPC64
228	/*
229	 * The non-rt sigreturn has the same layout at a different offset.
230	 * Move the CFA and leave all othe other descriptions the same.
231	 */
232	.cfi_def_cfa	1, SIGNAL_FRAMESIZE + offsetof_sigframe_mcontext
233	nop
234__kernel_sigtramp32:
235	raw_syscall __NR_sigreturn
236endf	__kernel_sigtramp32
237#endif
238
239	.cfi_endproc
240