Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/include/nolibc/arch-s390.h
50920 views
1
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2
/*
3
* s390 specific definitions for NOLIBC
4
*/
5
6
#ifndef _NOLIBC_ARCH_S390_H
7
#define _NOLIBC_ARCH_S390_H
8
9
#include "types.h"
10
11
#include <linux/sched.h>
12
#include <linux/signal.h>
13
#include <linux/unistd.h>
14
15
#include "compiler.h"
16
#include "crt.h"
17
#include "std.h"
18
19
/* Syscalls for s390:
20
* - registers are 64-bit
21
* - syscall number is passed in r1
22
* - arguments are in r2-r7
23
* - the system call is performed by calling the svc instruction
24
* - syscall return value is in r2
25
* - r1 and r2 are clobbered, others are preserved.
26
*
27
* Link s390 ABI: https://github.com/IBM/s390x-abi
28
*
29
*/
30
31
#define my_syscall0(num) \
32
({ \
33
register long _num __asm__ ("1") = (num); \
34
register long _rc __asm__ ("2"); \
35
\
36
__asm__ volatile ( \
37
"svc 0\n" \
38
: "=d"(_rc) \
39
: "d"(_num) \
40
: "memory", "cc" \
41
); \
42
_rc; \
43
})
44
45
#define my_syscall1(num, arg1) \
46
({ \
47
register long _num __asm__ ("1") = (num); \
48
register long _arg1 __asm__ ("2") = (long)(arg1); \
49
\
50
__asm__ volatile ( \
51
"svc 0\n" \
52
: "+d"(_arg1) \
53
: "d"(_num) \
54
: "memory", "cc" \
55
); \
56
_arg1; \
57
})
58
59
#define my_syscall2(num, arg1, arg2) \
60
({ \
61
register long _num __asm__ ("1") = (num); \
62
register long _arg1 __asm__ ("2") = (long)(arg1); \
63
register long _arg2 __asm__ ("3") = (long)(arg2); \
64
\
65
__asm__ volatile ( \
66
"svc 0\n" \
67
: "+d"(_arg1) \
68
: "d"(_arg2), "d"(_num) \
69
: "memory", "cc" \
70
); \
71
_arg1; \
72
})
73
74
#define my_syscall3(num, arg1, arg2, arg3) \
75
({ \
76
register long _num __asm__ ("1") = (num); \
77
register long _arg1 __asm__ ("2") = (long)(arg1); \
78
register long _arg2 __asm__ ("3") = (long)(arg2); \
79
register long _arg3 __asm__ ("4") = (long)(arg3); \
80
\
81
__asm__ volatile ( \
82
"svc 0\n" \
83
: "+d"(_arg1) \
84
: "d"(_arg2), "d"(_arg3), "d"(_num) \
85
: "memory", "cc" \
86
); \
87
_arg1; \
88
})
89
90
#define my_syscall4(num, arg1, arg2, arg3, arg4) \
91
({ \
92
register long _num __asm__ ("1") = (num); \
93
register long _arg1 __asm__ ("2") = (long)(arg1); \
94
register long _arg2 __asm__ ("3") = (long)(arg2); \
95
register long _arg3 __asm__ ("4") = (long)(arg3); \
96
register long _arg4 __asm__ ("5") = (long)(arg4); \
97
\
98
__asm__ volatile ( \
99
"svc 0\n" \
100
: "+d"(_arg1) \
101
: "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_num) \
102
: "memory", "cc" \
103
); \
104
_arg1; \
105
})
106
107
#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
108
({ \
109
register long _num __asm__ ("1") = (num); \
110
register long _arg1 __asm__ ("2") = (long)(arg1); \
111
register long _arg2 __asm__ ("3") = (long)(arg2); \
112
register long _arg3 __asm__ ("4") = (long)(arg3); \
113
register long _arg4 __asm__ ("5") = (long)(arg4); \
114
register long _arg5 __asm__ ("6") = (long)(arg5); \
115
\
116
__asm__ volatile ( \
117
"svc 0\n" \
118
: "+d"(_arg1) \
119
: "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_arg5), \
120
"d"(_num) \
121
: "memory", "cc" \
122
); \
123
_arg1; \
124
})
125
126
#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
127
({ \
128
register long _num __asm__ ("1") = (num); \
129
register long _arg1 __asm__ ("2") = (long)(arg1); \
130
register long _arg2 __asm__ ("3") = (long)(arg2); \
131
register long _arg3 __asm__ ("4") = (long)(arg3); \
132
register long _arg4 __asm__ ("5") = (long)(arg4); \
133
register long _arg5 __asm__ ("6") = (long)(arg5); \
134
register long _arg6 __asm__ ("7") = (long)(arg6); \
135
\
136
__asm__ volatile ( \
137
"svc 0\n" \
138
: "+d"(_arg1) \
139
: "d"(_arg2), "d"(_arg3), "d"(_arg4), "d"(_arg5), \
140
"d"(_arg6), "d"(_num) \
141
: "memory", "cc" \
142
); \
143
_arg1; \
144
})
145
146
#ifndef NOLIBC_NO_RUNTIME
147
/* startup code */
148
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
149
{
150
__asm__ volatile (
151
"lgr %r2, %r15\n" /* save stack pointer to %r2, as arg1 of _start_c */
152
"aghi %r15, -160\n" /* allocate new stackframe */
153
"xc 0(8,%r15), 0(%r15)\n" /* clear backchain */
154
"brasl %r14, _start_c\n" /* transfer to c runtime */
155
);
156
__nolibc_entrypoint_epilogue();
157
}
158
#endif /* NOLIBC_NO_RUNTIME */
159
160
struct s390_mmap_arg_struct {
161
unsigned long addr;
162
unsigned long len;
163
unsigned long prot;
164
unsigned long flags;
165
unsigned long fd;
166
unsigned long offset;
167
};
168
169
static __attribute__((unused))
170
void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd,
171
off_t offset)
172
{
173
struct s390_mmap_arg_struct args = {
174
.addr = (unsigned long)addr,
175
.len = (unsigned long)length,
176
.prot = prot,
177
.flags = flags,
178
.fd = fd,
179
.offset = (unsigned long)offset
180
};
181
182
return (void *)my_syscall1(__NR_mmap, &args);
183
}
184
#define sys_mmap sys_mmap
185
186
static __attribute__((unused))
187
pid_t sys_fork(void)
188
{
189
return my_syscall5(__NR_clone, 0, SIGCHLD, 0, 0, 0);
190
}
191
#define sys_fork sys_fork
192
193
static __attribute__((unused))
194
pid_t sys_vfork(void)
195
{
196
return my_syscall5(__NR_clone, 0, CLONE_VM | CLONE_VFORK | SIGCHLD, 0, 0, 0);
197
}
198
#define sys_vfork sys_vfork
199
200
#endif /* _NOLIBC_ARCH_S390_H */
201
202