authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-06-22 16:11:52+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-07-29 09:50:41+02:00
log7532a8a584730e9f5ca1237cb015eb1455c46588
treee6d10e673965003444dc35f919c25cb4f2e2944d
parent2d1ee678eb2a9d6713e5b7758c7620ccfe1eb1ff
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.os.linux: Add riscv32 support.


3 files changed, 227 insertions(+), 11 deletions(-)

lib/std/os/linux.zig+25-6
...@@ -39,6 +39,7 @@ const arch_bits = switch (native_arch) {...@@ -39,6 +39,7 @@ const arch_bits = switch (native_arch) {
39 .x86_64 => @import("linux/x86_64.zig"),39 .x86_64 => @import("linux/x86_64.zig"),
40 .aarch64, .aarch64_be => @import("linux/arm64.zig"),40 .aarch64, .aarch64_be => @import("linux/arm64.zig"),
41 .arm, .armeb, .thumb, .thumbeb => @import("linux/arm-eabi.zig"),41 .arm, .armeb, .thumb, .thumbeb => @import("linux/arm-eabi.zig"),
42 .riscv32 => @import("linux/riscv32.zig"),
42 .riscv64 => @import("linux/riscv64.zig"),43 .riscv64 => @import("linux/riscv64.zig"),
43 .sparc64 => @import("linux/sparc64.zig"),44 .sparc64 => @import("linux/sparc64.zig"),
44 .mips, .mipsel => @import("linux/mips.zig"),45 .mips, .mipsel => @import("linux/mips.zig"),
...@@ -104,6 +105,7 @@ pub const SYS = switch (@import("builtin").cpu.arch) {...@@ -104,6 +105,7 @@ pub const SYS = switch (@import("builtin").cpu.arch) {
104 .x86_64 => syscalls.X64,105 .x86_64 => syscalls.X64,
105 .aarch64, .aarch64_be => syscalls.Arm64,106 .aarch64, .aarch64_be => syscalls.Arm64,
106 .arm, .armeb, .thumb, .thumbeb => syscalls.Arm,107 .arm, .armeb, .thumb, .thumbeb => syscalls.Arm,
108 .riscv32 => syscalls.RiscV32,
107 .riscv64 => syscalls.RiscV64,109 .riscv64 => syscalls.RiscV64,
108 .sparc64 => syscalls.Sparc64,110 .sparc64 => syscalls.Sparc64,
109 .mips, .mipsel => syscalls.Mips,111 .mips, .mipsel => syscalls.Mips,
...@@ -163,7 +165,7 @@ pub const MAP = switch (native_arch) {...@@ -163,7 +165,7 @@ pub const MAP = switch (native_arch) {
163 UNINITIALIZED: bool = false,165 UNINITIALIZED: bool = false,
164 _: u5 = 0,166 _: u5 = 0,
165 },167 },
166 .riscv64 => packed struct(u32) {168 .riscv32, .riscv64 => packed struct(u32) {
167 TYPE: MAP_TYPE,169 TYPE: MAP_TYPE,
168 FIXED: bool = false,170 FIXED: bool = false,
169 ANONYMOUS: bool = false,171 ANONYMOUS: bool = false,
...@@ -268,7 +270,7 @@ pub const O = switch (native_arch) {...@@ -268,7 +270,7 @@ pub const O = switch (native_arch) {
268 TMPFILE: bool = false,270 TMPFILE: bool = false,
269 _: u9 = 0,271 _: u9 = 0,
270 },272 },
271 .x86, .riscv64 => packed struct(u32) {273 .x86, .riscv32, .riscv64 => packed struct(u32) {
272 ACCMODE: ACCMODE = .RDONLY,274 ACCMODE: ACCMODE = .RDONLY,
273 _2: u4 = 0,275 _2: u4 = 0,
274 CREAT: bool = false,276 CREAT: bool = false,
...@@ -1840,7 +1842,11 @@ pub fn accept4(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t, flag...@@ -1840,7 +1842,11 @@ pub fn accept4(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t, flag
1840}1842}
18411843
1842pub fn fstat(fd: i32, stat_buf: *Stat) usize {1844pub fn fstat(fd: i32, stat_buf: *Stat) usize {
1843 if (@hasField(SYS, "fstat64")) {1845 if (native_arch == .riscv32) {
1846 // riscv32 has made the interesting decision to not implement some of
1847 // the older stat syscalls, including this one.
1848 @compileError("No fstat syscall on this architecture.");
1849 } else if (@hasField(SYS, "fstat64")) {
1844 return syscall2(.fstat64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf));1850 return syscall2(.fstat64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf));
1845 } else {1851 } else {
1846 return syscall2(.fstat, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf));1852 return syscall2(.fstat, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf));
...@@ -1848,7 +1854,11 @@ pub fn fstat(fd: i32, stat_buf: *Stat) usize {...@@ -1848,7 +1854,11 @@ pub fn fstat(fd: i32, stat_buf: *Stat) usize {
1848}1854}
18491855
1850pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize {1856pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize {
1851 if (@hasField(SYS, "stat64")) {1857 if (native_arch == .riscv32) {
1858 // riscv32 has made the interesting decision to not implement some of
1859 // the older stat syscalls, including this one.
1860 @compileError("No stat syscall on this architecture.");
1861 } else if (@hasField(SYS, "stat64")) {
1852 return syscall2(.stat64, @intFromPtr(pathname), @intFromPtr(statbuf));1862 return syscall2(.stat64, @intFromPtr(pathname), @intFromPtr(statbuf));
1853 } else {1863 } else {
1854 return syscall2(.stat, @intFromPtr(pathname), @intFromPtr(statbuf));1864 return syscall2(.stat, @intFromPtr(pathname), @intFromPtr(statbuf));
...@@ -1856,7 +1866,11 @@ pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize {...@@ -1856,7 +1866,11 @@ pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize {
1856}1866}
18571867
1858pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {1868pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {
1859 if (@hasField(SYS, "lstat64")) {1869 if (native_arch == .riscv32) {
1870 // riscv32 has made the interesting decision to not implement some of
1871 // the older stat syscalls, including this one.
1872 @compileError("No lstat syscall on this architecture.");
1873 } else if (@hasField(SYS, "lstat64")) {
1860 return syscall2(.lstat64, @intFromPtr(pathname), @intFromPtr(statbuf));1874 return syscall2(.lstat64, @intFromPtr(pathname), @intFromPtr(statbuf));
1861 } else {1875 } else {
1862 return syscall2(.lstat, @intFromPtr(pathname), @intFromPtr(statbuf));1876 return syscall2(.lstat, @intFromPtr(pathname), @intFromPtr(statbuf));
...@@ -1864,7 +1878,11 @@ pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {...@@ -1864,7 +1878,11 @@ pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {
1864}1878}
18651879
1866pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *Stat, flags: u32) usize {1880pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *Stat, flags: u32) usize {
1867 if (@hasField(SYS, "fstatat64")) {1881 if (native_arch == .riscv32) {
1882 // riscv32 has made the interesting decision to not implement some of
1883 // the older stat syscalls, including this one.
1884 @compileError("No fstatat syscall on this architecture.");
1885 } else if (@hasField(SYS, "fstatat64")) {
1868 return syscall4(.fstatat64, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags);1886 return syscall4(.fstatat64, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags);
1869 } else {1887 } else {
1870 return syscall4(.fstatat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags);1888 return syscall4(.fstatat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags);
...@@ -7352,6 +7370,7 @@ pub const AUDIT = struct {...@@ -7352,6 +7370,7 @@ pub const AUDIT = struct {
7352 .x86_64 => .X86_64,7370 .x86_64 => .X86_64,
7353 .aarch64 => .AARCH64,7371 .aarch64 => .AARCH64,
7354 .arm, .thumb => .ARM,7372 .arm, .thumb => .ARM,
7373 .riscv32 => .RISCV32,
7355 .riscv64 => .RISCV64,7374 .riscv64 => .RISCV64,
7356 .sparc64 => .SPARC64,7375 .sparc64 => .SPARC64,
7357 .mips => .MIPS,7376 .mips => .MIPS,
lib/std/os/linux/riscv32.zig created+197
...@@ -0,0 +1,197 @@
1const std = @import("../../std.zig");
2const iovec = std.posix.iovec;
3const iovec_const = std.posix.iovec_const;
4const linux = std.os.linux;
5const SYS = linux.SYS;
6const uid_t = std.os.linux.uid_t;
7const gid_t = std.os.linux.gid_t;
8const pid_t = std.os.linux.pid_t;
9const sockaddr = linux.sockaddr;
10const socklen_t = linux.socklen_t;
11const timespec = std.os.linux.timespec;
12
13pub fn syscall0(number: SYS) usize {
14 return asm volatile ("ecall"
15 : [ret] "={x10}" (-> usize),
16 : [number] "{x17}" (@intFromEnum(number)),
17 : "memory"
18 );
19}
20
21pub fn syscall1(number: SYS, arg1: usize) usize {
22 return asm volatile ("ecall"
23 : [ret] "={x10}" (-> usize),
24 : [number] "{x17}" (@intFromEnum(number)),
25 [arg1] "{x10}" (arg1),
26 : "memory"
27 );
28}
29
30pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
31 return asm volatile ("ecall"
32 : [ret] "={x10}" (-> usize),
33 : [number] "{x17}" (@intFromEnum(number)),
34 [arg1] "{x10}" (arg1),
35 [arg2] "{x11}" (arg2),
36 : "memory"
37 );
38}
39
40pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
41 return asm volatile ("ecall"
42 : [ret] "={x10}" (-> usize),
43 : [number] "{x17}" (@intFromEnum(number)),
44 [arg1] "{x10}" (arg1),
45 [arg2] "{x11}" (arg2),
46 [arg3] "{x12}" (arg3),
47 : "memory"
48 );
49}
50
51pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
52 return asm volatile ("ecall"
53 : [ret] "={x10}" (-> usize),
54 : [number] "{x17}" (@intFromEnum(number)),
55 [arg1] "{x10}" (arg1),
56 [arg2] "{x11}" (arg2),
57 [arg3] "{x12}" (arg3),
58 [arg4] "{x13}" (arg4),
59 : "memory"
60 );
61}
62
63pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
64 return asm volatile ("ecall"
65 : [ret] "={x10}" (-> usize),
66 : [number] "{x17}" (@intFromEnum(number)),
67 [arg1] "{x10}" (arg1),
68 [arg2] "{x11}" (arg2),
69 [arg3] "{x12}" (arg3),
70 [arg4] "{x13}" (arg4),
71 [arg5] "{x14}" (arg5),
72 : "memory"
73 );
74}
75
76pub fn syscall6(
77 number: SYS,
78 arg1: usize,
79 arg2: usize,
80 arg3: usize,
81 arg4: usize,
82 arg5: usize,
83 arg6: usize,
84) usize {
85 return asm volatile ("ecall"
86 : [ret] "={x10}" (-> usize),
87 : [number] "{x17}" (@intFromEnum(number)),
88 [arg1] "{x10}" (arg1),
89 [arg2] "{x11}" (arg2),
90 [arg3] "{x12}" (arg3),
91 [arg4] "{x13}" (arg4),
92 [arg5] "{x14}" (arg5),
93 [arg6] "{x15}" (arg6),
94 : "memory"
95 );
96}
97
98const CloneFn = *const fn (arg: usize) callconv(.C) u8;
99
100pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
101
102pub const restore = restore_rt;
103
104pub fn restore_rt() callconv(.Naked) noreturn {
105 asm volatile (
106 \\ ecall
107 :
108 : [number] "{x17}" (@intFromEnum(SYS.rt_sigreturn)),
109 : "memory"
110 );
111}
112
113pub const F = struct {
114 pub const DUPFD = 0;
115 pub const GETFD = 1;
116 pub const SETFD = 2;
117 pub const GETFL = 3;
118 pub const SETFL = 4;
119 pub const GETLK = 5;
120 pub const SETLK = 6;
121 pub const SETLKW = 7;
122 pub const SETOWN = 8;
123 pub const GETOWN = 9;
124 pub const SETSIG = 10;
125 pub const GETSIG = 11;
126
127 pub const RDLCK = 0;
128 pub const WRLCK = 1;
129 pub const UNLCK = 2;
130
131 pub const SETOWN_EX = 15;
132 pub const GETOWN_EX = 16;
133
134 pub const GETOWNER_UIDS = 17;
135};
136
137pub const blksize_t = i32;
138pub const nlink_t = u32;
139pub const time_t = i64;
140pub const mode_t = u32;
141pub const off_t = i64;
142pub const ino_t = u64;
143pub const dev_t = u64;
144pub const blkcnt_t = i64;
145
146pub const timeval = extern struct {
147 sec: time_t,
148 usec: i64,
149};
150
151pub const Flock = extern struct {
152 type: i16,
153 whence: i16,
154 start: off_t,
155 len: off_t,
156 pid: pid_t,
157 __unused: [4]u8,
158};
159
160pub const msghdr = extern struct {
161 name: ?*sockaddr,
162 namelen: socklen_t,
163 iov: [*]iovec,
164 iovlen: i32,
165 __pad1: i32 = 0,
166 control: ?*anyopaque,
167 controllen: socklen_t,
168 __pad2: socklen_t = 0,
169 flags: i32,
170};
171
172pub const msghdr_const = extern struct {
173 name: ?*const sockaddr,
174 namelen: socklen_t,
175 iov: [*]const iovec_const,
176 iovlen: i32,
177 __pad1: i32 = 0,
178 control: ?*const anyopaque,
179 controllen: socklen_t,
180 __pad2: socklen_t = 0,
181 flags: i32,
182};
183
184/// No `Stat` structure on this platform, only `Statx`.
185pub const Stat = void;
186
187pub const Elf_Symndx = u32;
188
189pub const MMAP2_UNIT = 4096;
190
191pub const VDSO = struct {};
192
193/// TODO
194pub const ucontext_t = void;
195
196/// TODO
197pub const getcontext = {};
lib/std/os/linux/riscv64.zig+5-5
...@@ -136,12 +136,12 @@ pub const F = struct {...@@ -136,12 +136,12 @@ pub const F = struct {
136136
137pub const blksize_t = i32;137pub const blksize_t = i32;
138pub const nlink_t = u32;138pub const nlink_t = u32;
139pub const time_t = isize;139pub const time_t = i64;
140pub const mode_t = u32;140pub const mode_t = u32;
141pub const off_t = isize;141pub const off_t = i64;
142pub const ino_t = usize;142pub const ino_t = u64;
143pub const dev_t = usize;143pub const dev_t = u64;
144pub const blkcnt_t = isize;144pub const blkcnt_t = i64;
145145
146pub const timeval = extern struct {146pub const timeval = extern struct {
147 sec: time_t,147 sec: time_t,