1/*
2 * Copyright (c) 2020 Carlo Caione <ccaione@baylibre.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#include <zephyr/toolchain.h>
8#include <zephyr/linker/sections.h>
9#include <offsets_short.h>
10#include <zephyr/arch/cpu.h>
11#include <zephyr/syscall.h>
12#include <zephyr/arch/arm64/mm.h>
13#include "macro_priv.inc"
14
15_ASM_FILE_PROLOGUE
16
17/*
18 * size_t arch_user_string_nlen(const char *s, size_t maxsize, int *err_arg)
19 */
20
21GTEXT(z_arm64_user_string_nlen_fault_start)
22GTEXT(z_arm64_user_string_nlen_fault_end)
23GTEXT(z_arm64_user_string_nlen_fixup)
24
25GTEXT(arch_user_string_nlen)
26SECTION_FUNC(TEXT, arch_user_string_nlen)
27
28	mov	x3, x0
29	mov	x0, #0
30	mov	x4, #0
31
32strlen_loop:
33
34	cmp	x0, x1
35	beq	strlen_done
36
37z_arm64_user_string_nlen_fault_start:
38	ldrb	w5, [x3, x0]
39z_arm64_user_string_nlen_fault_end:
40	cbz	x5, strlen_done
41
42	add	x0, x0, #1
43	b	strlen_loop
44
45z_arm64_user_string_nlen_fixup:
46	mov	x4, #-1
47	mov	x0, #0
48
49strlen_done:
50	str	w4, [x2]
51	ret
52
53/*
54 * int arch_buffer_validate(const void *addr, size_t size, int write)
55 */
56
57GTEXT(arch_buffer_validate)
58SECTION_FUNC(TEXT, arch_buffer_validate)
59
60	add	x1, x1, x0
61	mrs	x3, DAIF
62	msr	DAIFSET, #DAIFSET_IRQ_BIT
63
64abv_loop:
65	cbnz	w2, 1f
66	at	S1E0R, x0
67	b	2f
681:	at	S1E0W, x0
69
702:	orr	x0, x0, #(MEM_DOMAIN_ALIGN_AND_SIZE - 1)
71	add	x0, x0, #1
72
73	isb
74	mrs	x4, PAR_EL1
75	tbnz	x4, #0, abv_fail
76
77	cmp	x0, x1
78	blo	abv_loop
79
80	msr	DAIF, x3
81	mov	x0, #0
82	ret
83
84abv_fail:
85	msr	DAIF, x3
86	mov	x0, #-1
87	ret
88
89/*
90 * System call entry point.
91 */
92
93GTEXT(z_arm64_do_syscall)
94SECTION_FUNC(TEXT, z_arm64_do_syscall)
95	/* Recover the syscall parameters from the ESF */
96	ldp	x0, x1, [sp, ___esf_t_x0_x1_OFFSET]
97	ldp	x2, x3, [sp, ___esf_t_x2_x3_OFFSET]
98	ldp	x4, x5, [sp, ___esf_t_x4_x5_OFFSET]
99
100	/* Use the ESF as SSF */
101	mov	x6, sp
102
103	/* Recover the syscall ID */
104	ldr	x8, [sp, ___esf_t_x8_x9_OFFSET]
105
106	/* Check whether the ID is valid */
107	ldr	x9, =K_SYSCALL_LIMIT
108	cmp	x8, x9
109	blo	valid_syscall_id
110
111	/* Save the bad ID for handler_bad_syscall() */
112	mov	x0, x8
113	ldr	x8, =K_SYSCALL_BAD
114
115valid_syscall_id:
116	ldr	x9, =_k_syscall_table
117	ldr	x9, [x9, x8, lsl #3]
118
119	/* Jump into the syscall */
120	msr	daifclr, #(DAIFSET_IRQ_BIT)
121	blr	x9
122	msr	daifset, #(DAIFSET_IRQ_BIT)
123
124	/* Save the return value into the ESF */
125	str	x0, [sp, ___esf_t_x0_x1_OFFSET]
126
127	/* Return from exception */
128	b	z_arm64_exit_exc
129