authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-29 16:13:35-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-07-29 16:13:35-07:00
log38e0f049c531e83ec2eec80d50b624e6c3b8c486
tree76fb3cf957c9963a720e1845667666b0937e4619
parent73a444766e4d1406c194935b54e8167e747b165f
parent13945548fcd4fe3aab0879b670db1fe8131d8b0e
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20389 from alexrp/riscv32

Some `riscv32-linux` porting work

21 files changed, 913 insertions(+), 222 deletions(-)

lib/c.zig+34
...@@ -319,6 +319,40 @@ fn clone() callconv(.Naked) void {...@@ -319,6 +319,40 @@ fn clone() callconv(.Naked) void {
319 \\3: bx r5319 \\3: bx r5
320 );320 );
321 },321 },
322 .riscv32 => {
323 // __clone(func, stack, flags, arg, ptid, tls, ctid)
324 // a0, a1, a2, a3, a4, a5, a6
325
326 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
327 // a7 a0, a1, a2, a3, a4
328 asm volatile (
329 \\ # Save func and arg to stack
330 \\ addi a1, a1, -8
331 \\ sw a0, 0(a1)
332 \\ sw a3, 4(a1)
333 \\
334 \\ # Call SYS_clone
335 \\ mv a0, a2
336 \\ mv a2, a4
337 \\ mv a3, a5
338 \\ mv a4, a6
339 \\ li a7, 220 # SYS_clone
340 \\ ecall
341 \\
342 \\ beqz a0, 1f
343 \\ # Parent
344 \\ ret
345 \\
346 \\ # Child
347 \\1: lw a1, 0(sp)
348 \\ lw a0, 4(sp)
349 \\ jalr a1
350 \\
351 \\ # Exit
352 \\ li a7, 93 # SYS_exit
353 \\ ecall
354 );
355 },
322 .riscv64 => {356 .riscv64 => {
323 // __clone(func, stack, flags, arg, ptid, tls, ctid)357 // __clone(func, stack, flags, arg, ptid, tls, ctid)
324 // a0, a1, a2, a3, a4, a5, a6358 // a0, a1, a2, a3, a4, a5, a6
lib/std/Target.zig+10-1
...@@ -720,7 +720,16 @@ pub const Abi = enum {...@@ -720,7 +720,16 @@ pub const Abi = enum {
720720
721 pub inline fn isGnu(abi: Abi) bool {721 pub inline fn isGnu(abi: Abi) bool {
722 return switch (abi) {722 return switch (abi) {
723 .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true,723 .gnu,
724 .gnuabin32,
725 .gnuabi64,
726 .gnueabi,
727 .gnueabihf,
728 .gnuf32,
729 .gnusf,
730 .gnux32,
731 .gnuilp32,
732 => true,
724 else => false,733 else => false,
725 };734 };
726 }735 }
lib/std/Thread.zig+31-18
...@@ -1082,11 +1082,11 @@ const LinuxThreadImpl = struct {...@@ -1082,11 +1082,11 @@ const LinuxThreadImpl = struct {
1082 fn freeAndExit(self: *ThreadCompletion) noreturn {1082 fn freeAndExit(self: *ThreadCompletion) noreturn {
1083 switch (target.cpu.arch) {1083 switch (target.cpu.arch) {
1084 .x86 => asm volatile (1084 .x86 => asm volatile (
1085 \\ movl $91, %%eax1085 \\ movl $91, %%eax # SYS_munmap
1086 \\ movl %[ptr], %%ebx1086 \\ movl %[ptr], %%ebx
1087 \\ movl %[len], %%ecx1087 \\ movl %[len], %%ecx
1088 \\ int $1281088 \\ int $128
1089 \\ movl $1, %%eax1089 \\ movl $1, %%eax # SYS_exit
1090 \\ movl $0, %%ebx1090 \\ movl $0, %%ebx
1091 \\ int $1281091 \\ int $128
1092 :1092 :
...@@ -1095,9 +1095,9 @@ const LinuxThreadImpl = struct {...@@ -1095,9 +1095,9 @@ const LinuxThreadImpl = struct {
1095 : "memory"1095 : "memory"
1096 ),1096 ),
1097 .x86_64 => asm volatile (1097 .x86_64 => asm volatile (
1098 \\ movq $11, %%rax1098 \\ movq $11, %%rax # SYS_munmap
1099 \\ syscall1099 \\ syscall
1100 \\ movq $60, %%rax1100 \\ movq $60, %%rax # SYS_exit
1101 \\ movq $1, %%rdi1101 \\ movq $1, %%rdi
1102 \\ syscall1102 \\ syscall
1103 :1103 :
...@@ -1105,11 +1105,11 @@ const LinuxThreadImpl = struct {...@@ -1105,11 +1105,11 @@ const LinuxThreadImpl = struct {
1105 [len] "{rsi}" (self.mapped.len),1105 [len] "{rsi}" (self.mapped.len),
1106 ),1106 ),
1107 .arm, .armeb, .thumb, .thumbeb => asm volatile (1107 .arm, .armeb, .thumb, .thumbeb => asm volatile (
1108 \\ mov r7, #911108 \\ mov r7, #91 // SYS_munmap
1109 \\ mov r0, %[ptr]1109 \\ mov r0, %[ptr]
1110 \\ mov r1, %[len]1110 \\ mov r1, %[len]
1111 \\ svc 01111 \\ svc 0
1112 \\ mov r7, #11112 \\ mov r7, #1 // SYS_exit
1113 \\ mov r0, #01113 \\ mov r0, #0
1114 \\ svc 01114 \\ svc 0
1115 :1115 :
...@@ -1118,11 +1118,11 @@ const LinuxThreadImpl = struct {...@@ -1118,11 +1118,11 @@ const LinuxThreadImpl = struct {
1118 : "memory"1118 : "memory"
1119 ),1119 ),
1120 .aarch64, .aarch64_be => asm volatile (1120 .aarch64, .aarch64_be => asm volatile (
1121 \\ mov x8, #2151121 \\ mov x8, #215 // SYS_munmap
1122 \\ mov x0, %[ptr]1122 \\ mov x0, %[ptr]
1123 \\ mov x1, %[len]1123 \\ mov x1, %[len]
1124 \\ svc 01124 \\ svc 0
1125 \\ mov x8, #931125 \\ mov x8, #93 // SYS_exit
1126 \\ mov x0, #01126 \\ mov x0, #0
1127 \\ svc 01127 \\ svc 0
1128 :1128 :
...@@ -1132,11 +1132,11 @@ const LinuxThreadImpl = struct {...@@ -1132,11 +1132,11 @@ const LinuxThreadImpl = struct {
1132 ),1132 ),
1133 .mips, .mipsel => asm volatile (1133 .mips, .mipsel => asm volatile (
1134 \\ move $sp, $251134 \\ move $sp, $25
1135 \\ li $2, 40911135 \\ li $2, 4091 # SYS_munmap
1136 \\ move $4, %[ptr]1136 \\ move $4, %[ptr]
1137 \\ move $5, %[len]1137 \\ move $5, %[len]
1138 \\ syscall1138 \\ syscall
1139 \\ li $2, 40011139 \\ li $2, 4001 # SYS_exit
1140 \\ li $4, 01140 \\ li $4, 0
1141 \\ syscall1141 \\ syscall
1142 :1142 :
...@@ -1145,11 +1145,11 @@ const LinuxThreadImpl = struct {...@@ -1145,11 +1145,11 @@ const LinuxThreadImpl = struct {
1145 : "memory"1145 : "memory"
1146 ),1146 ),
1147 .mips64, .mips64el => asm volatile (1147 .mips64, .mips64el => asm volatile (
1148 \\ li $2, 40911148 \\ li $2, 4091 # SYS_munmap
1149 \\ move $4, %[ptr]1149 \\ move $4, %[ptr]
1150 \\ move $5, %[len]1150 \\ move $5, %[len]
1151 \\ syscall1151 \\ syscall
1152 \\ li $2, 40011152 \\ li $2, 4001 # SYS_exit
1153 \\ li $4, 01153 \\ li $4, 0
1154 \\ syscall1154 \\ syscall
1155 :1155 :
...@@ -1158,11 +1158,11 @@ const LinuxThreadImpl = struct {...@@ -1158,11 +1158,11 @@ const LinuxThreadImpl = struct {
1158 : "memory"1158 : "memory"
1159 ),1159 ),
1160 .powerpc, .powerpcle, .powerpc64, .powerpc64le => asm volatile (1160 .powerpc, .powerpcle, .powerpc64, .powerpc64le => asm volatile (
1161 \\ li 0, 911161 \\ li 0, 91 # SYS_munmap
1162 \\ mr %[ptr], 31162 \\ mr %[ptr], 3
1163 \\ mr %[len], 41163 \\ mr %[len], 4
1164 \\ sc1164 \\ sc
1165 \\ li 0, 11165 \\ li 0, 1 # SYS_exit
1166 \\ li 3, 01166 \\ li 3, 0
1167 \\ sc1167 \\ sc
1168 \\ blr1168 \\ blr
...@@ -1171,12 +1171,25 @@ const LinuxThreadImpl = struct {...@@ -1171,12 +1171,25 @@ const LinuxThreadImpl = struct {
1171 [len] "r" (self.mapped.len),1171 [len] "r" (self.mapped.len),
1172 : "memory"1172 : "memory"
1173 ),1173 ),
1174 .riscv32 => asm volatile (
1175 \\ li a7, 215 # SYS_munmap
1176 \\ mv a0, %[ptr]
1177 \\ mv a1, %[len]
1178 \\ ecall
1179 \\ li a7, 93 # SYS_exit
1180 \\ mv a0, zero
1181 \\ ecall
1182 :
1183 : [ptr] "r" (@intFromPtr(self.mapped.ptr)),
1184 [len] "r" (self.mapped.len),
1185 : "memory"
1186 ),
1174 .riscv64 => asm volatile (1187 .riscv64 => asm volatile (
1175 \\ li a7, 2151188 \\ li a7, 215 # SYS_munmap
1176 \\ mv a0, %[ptr]1189 \\ mv a0, %[ptr]
1177 \\ mv a1, %[len]1190 \\ mv a1, %[len]
1178 \\ ecall1191 \\ ecall
1179 \\ li a7, 931192 \\ li a7, 93 # SYS_exit
1180 \\ mv a0, zero1193 \\ mv a0, zero
1181 \\ ecall1194 \\ ecall
1182 :1195 :
...@@ -1196,14 +1209,14 @@ const LinuxThreadImpl = struct {...@@ -1196,14 +1209,14 @@ const LinuxThreadImpl = struct {
1196 \\ ba 1b1209 \\ ba 1b
1197 \\ restore1210 \\ restore
1198 \\ 2:1211 \\ 2:
1199 \\ mov 73, %%g11212 \\ mov 73, %%g1 # SYS_munmap
1200 \\ mov %[ptr], %%o01213 \\ mov %[ptr], %%o0
1201 \\ mov %[len], %%o11214 \\ mov %[len], %%o1
1202 \\ # Flush register window contents to prevent background1215 \\ # Flush register window contents to prevent background
1203 \\ # memory access before unmapping the stack.1216 \\ # memory access before unmapping the stack.
1204 \\ flushw1217 \\ flushw
1205 \\ t 0x6d1218 \\ t 0x6d
1206 \\ mov 1, %%g11219 \\ mov 1, %%g1 # SYS_exit
1207 \\ mov 1, %%o01220 \\ mov 1, %%o0
1208 \\ t 0x6d1221 \\ t 0x6d
1209 :1222 :
lib/std/debug.zig+2-1
...@@ -747,7 +747,8 @@ pub const StackIterator = struct {...@@ -747,7 +747,8 @@ pub const StackIterator = struct {
747 .SUCCESS => return bytes_read == buf.len,747 .SUCCESS => return bytes_read == buf.len,
748 .FAULT => return false,748 .FAULT => return false,
749 .INVAL, .PERM, .SRCH => unreachable, // own pid is always valid749 .INVAL, .PERM, .SRCH => unreachable, // own pid is always valid
750 .NOMEM, .NOSYS => {},750 .NOMEM => {},
751 .NOSYS => {}, // QEMU is known not to implement this syscall.
751 else => unreachable, // unexpected752 else => unreachable, // unexpected
752 }753 }
753 var path_buf: [754 var path_buf: [
lib/std/fs/Dir.zig+27-2
...@@ -334,7 +334,6 @@ pub const Iterator = switch (native_os) {...@@ -334,7 +334,6 @@ pub const Iterator = switch (native_os) {
334 first_iter: bool,334 first_iter: bool,
335335
336 const Self = @This();336 const Self = @This();
337 const linux = std.os.linux;
338337
339 pub const Error = IteratorError;338 pub const Error = IteratorError;
340339
...@@ -2690,8 +2689,33 @@ pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat {...@@ -2690,8 +2689,33 @@ pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat {
2690 const st = try std.os.fstatat_wasi(self.fd, sub_path, .{ .SYMLINK_FOLLOW = true });2689 const st = try std.os.fstatat_wasi(self.fd, sub_path, .{ .SYMLINK_FOLLOW = true });
2691 return Stat.fromWasi(st);2690 return Stat.fromWasi(st);
2692 }2691 }
2692 if (native_os == .linux) {
2693 const sub_path_c = try posix.toPosixPath(sub_path);
2694 var stx = std.mem.zeroes(linux.Statx);
2695
2696 const rc = linux.statx(
2697 self.fd,
2698 &sub_path_c,
2699 linux.AT.NO_AUTOMOUNT,
2700 linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME,
2701 &stx,
2702 );
2703
2704 return switch (linux.E.init(rc)) {
2705 .SUCCESS => Stat.fromLinux(stx),
2706 .ACCES => error.AccessDenied,
2707 .BADF => unreachable,
2708 .FAULT => unreachable,
2709 .INVAL => unreachable,
2710 .LOOP => error.SymLinkLoop,
2711 .NAMETOOLONG => unreachable, // Handled by posix.toPosixPath() above.
2712 .NOENT, .NOTDIR => error.FileNotFound,
2713 .NOMEM => error.SystemResources,
2714 else => |err| posix.unexpectedErrno(err),
2715 };
2716 }
2693 const st = try posix.fstatat(self.fd, sub_path, 0);2717 const st = try posix.fstatat(self.fd, sub_path, 0);
2694 return Stat.fromSystem(st);2718 return Stat.fromPosix(st);
2695}2719}
26962720
2697pub const ChmodError = File.ChmodError;2721pub const ChmodError = File.ChmodError;
...@@ -2751,6 +2775,7 @@ const path = fs.path;...@@ -2751,6 +2775,7 @@ const path = fs.path;
2751const fs = std.fs;2775const fs = std.fs;
2752const Allocator = std.mem.Allocator;2776const Allocator = std.mem.Allocator;
2753const assert = std.debug.assert;2777const assert = std.debug.assert;
2778const linux = std.os.linux;
2754const windows = std.os.windows;2779const windows = std.os.windows;
2755const native_os = builtin.os.tag;2780const native_os = builtin.os.tag;
2756const have_flock = @TypeOf(posix.system.flock) != void;2781const have_flock = @TypeOf(posix.system.flock) != void;
lib/std/fs/File.zig+76-30
...@@ -342,7 +342,7 @@ pub fn seekTo(self: File, offset: u64) SeekError!void {...@@ -342,7 +342,7 @@ pub fn seekTo(self: File, offset: u64) SeekError!void {
342 return posix.lseek_SET(self.handle, offset);342 return posix.lseek_SET(self.handle, offset);
343}343}
344344
345pub const GetSeekPosError = posix.SeekError || posix.FStatError;345pub const GetSeekPosError = posix.SeekError || StatError;
346346
347/// TODO: integrate with async I/O347/// TODO: integrate with async I/O
348pub fn getPos(self: File) GetSeekPosError!u64 {348pub fn getPos(self: File) GetSeekPosError!u64 {
...@@ -357,7 +357,7 @@ pub fn getEndPos(self: File) GetSeekPosError!u64 {...@@ -357,7 +357,7 @@ pub fn getEndPos(self: File) GetSeekPosError!u64 {
357 return (try self.stat()).size;357 return (try self.stat()).size;
358}358}
359359
360pub const ModeError = posix.FStatError;360pub const ModeError = StatError;
361361
362/// TODO: integrate with async I/O362/// TODO: integrate with async I/O
363pub fn mode(self: File) ModeError!Mode {363pub fn mode(self: File) ModeError!Mode {
...@@ -392,7 +392,7 @@ pub const Stat = struct {...@@ -392,7 +392,7 @@ pub const Stat = struct {
392 /// Last status/metadata change time in nanoseconds, relative to UTC 1970-01-01.392 /// Last status/metadata change time in nanoseconds, relative to UTC 1970-01-01.
393 ctime: i128,393 ctime: i128,
394394
395 pub fn fromSystem(st: posix.Stat) Stat {395 pub fn fromPosix(st: posix.Stat) Stat {
396 const atime = st.atime();396 const atime = st.atime();
397 const mtime = st.mtime();397 const mtime = st.mtime();
398 const ctime = st.ctime();398 const ctime = st.ctime();
...@@ -426,6 +426,31 @@ pub const Stat = struct {...@@ -426,6 +426,31 @@ pub const Stat = struct {
426 };426 };
427 }427 }
428428
429 pub fn fromLinux(stx: linux.Statx) Stat {
430 const atime = stx.atime;
431 const mtime = stx.mtime;
432 const ctime = stx.ctime;
433
434 return .{
435 .inode = stx.ino,
436 .size = stx.size,
437 .mode = stx.mode,
438 .kind = switch (stx.mode & linux.S.IFMT) {
439 linux.S.IFDIR => .directory,
440 linux.S.IFCHR => .character_device,
441 linux.S.IFBLK => .block_device,
442 linux.S.IFREG => .file,
443 linux.S.IFIFO => .named_pipe,
444 linux.S.IFLNK => .sym_link,
445 linux.S.IFSOCK => .unix_domain_socket,
446 else => .unknown,
447 },
448 .atime = @as(i128, atime.sec) * std.time.ns_per_s + atime.nsec,
449 .mtime = @as(i128, mtime.sec) * std.time.ns_per_s + mtime.nsec,
450 .ctime = @as(i128, ctime.sec) * std.time.ns_per_s + ctime.nsec,
451 };
452 }
453
429 pub fn fromWasi(st: std.os.wasi.filestat_t) Stat {454 pub fn fromWasi(st: std.os.wasi.filestat_t) Stat {
430 return .{455 return .{
431 .inode = st.ino,456 .inode = st.ino,
...@@ -502,8 +527,34 @@ pub fn stat(self: File) StatError!Stat {...@@ -502,8 +527,34 @@ pub fn stat(self: File) StatError!Stat {
502 return Stat.fromWasi(st);527 return Stat.fromWasi(st);
503 }528 }
504529
530 if (builtin.os.tag == .linux) {
531 var stx = std.mem.zeroes(linux.Statx);
532
533 const rc = linux.statx(
534 self.handle,
535 "",
536 linux.AT.EMPTY_PATH,
537 linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME,
538 &stx,
539 );
540
541 return switch (linux.E.init(rc)) {
542 .SUCCESS => Stat.fromLinux(stx),
543 .ACCES => unreachable,
544 .BADF => unreachable,
545 .FAULT => unreachable,
546 .INVAL => unreachable,
547 .LOOP => unreachable,
548 .NAMETOOLONG => unreachable,
549 .NOENT => unreachable,
550 .NOMEM => error.SystemResources,
551 .NOTDIR => unreachable,
552 else => |err| posix.unexpectedErrno(err),
553 };
554 }
555
505 const st = try posix.fstat(self.handle);556 const st = try posix.fstat(self.handle);
506 return Stat.fromSystem(st);557 return Stat.fromPosix(st);
507}558}
508559
509pub const ChmodError = posix.FChmodError;560pub const ChmodError = posix.FChmodError;
...@@ -731,7 +782,7 @@ pub const Metadata = struct {...@@ -731,7 +782,7 @@ pub const Metadata = struct {
731782
732 /// Returns the time the file was created in nanoseconds since UTC 1970-01-01783 /// Returns the time the file was created in nanoseconds since UTC 1970-01-01
733 /// On Windows, this cannot return null784 /// On Windows, this cannot return null
734 /// On Linux, this returns null if the filesystem does not support creation times, or if the kernel is older than 4.11785 /// On Linux, this returns null if the filesystem does not support creation times
735 /// On Unices, this returns null if the filesystem or OS does not support creation times786 /// On Unices, this returns null if the filesystem or OS does not support creation times
736 /// On MacOS, this returns the ctime if the filesystem does not support creation times; this is insanity, and yet another reason to hate on Apple787 /// On MacOS, this returns the ctime if the filesystem does not support creation times; this is insanity, and yet another reason to hate on Apple
737 pub fn created(self: Self) ?i128 {788 pub fn created(self: Self) ?i128 {
...@@ -822,7 +873,6 @@ pub const MetadataUnix = struct {...@@ -822,7 +873,6 @@ pub const MetadataUnix = struct {
822};873};
823874
824/// `MetadataUnix`, but using Linux's `statx` syscall.875/// `MetadataUnix`, but using Linux's `statx` syscall.
825/// On Linux versions below 4.11, `statx` will be filled with data from stat.
826pub const MetadataLinux = struct {876pub const MetadataLinux = struct {
827 statx: std.os.linux.Statx,877 statx: std.os.linux.Statx,
828878
...@@ -1010,34 +1060,29 @@ pub fn metadata(self: File) MetadataError!Metadata {...@@ -1010,34 +1060,29 @@ pub fn metadata(self: File) MetadataError!Metadata {
1010 };1060 };
1011 },1061 },
1012 .linux => blk: {1062 .linux => blk: {
1013 const l = std.os.linux;1063 var stx = std.mem.zeroes(linux.Statx);
1014 var stx = std.mem.zeroes(l.Statx);1064
1015 const rcx = l.statx(self.handle, "\x00", l.AT.EMPTY_PATH, l.STATX_TYPE |1065 // We are gathering information for Metadata, which is meant to contain all the
1016 l.STATX_MODE | l.STATX_ATIME | l.STATX_MTIME | l.STATX_BTIME, &stx);1066 // native OS information about the file, so use all known flags.
10171067 const rc = linux.statx(
1018 switch (posix.errno(rcx)) {1068 self.handle,
1069 "",
1070 linux.AT.EMPTY_PATH,
1071 linux.STATX_BASIC_STATS | linux.STATX_BTIME,
1072 &stx,
1073 );
1074
1075 switch (posix.errno(rc)) {
1019 .SUCCESS => {},1076 .SUCCESS => {},
1020 // NOSYS happens when `statx` is unsupported, which is the case on kernel versions before 4.111077 .ACCES => unreachable,
1021 // Here, we call `fstat` and fill `stx` with the data we need
1022 .NOSYS => {
1023 const st = try posix.fstat(self.handle);
1024
1025 stx.mode = @as(u16, @intCast(st.mode));
1026
1027 // Hacky conversion from timespec to statx_timestamp
1028 stx.atime = std.mem.zeroes(l.statx_timestamp);
1029 stx.atime.sec = st.atim.sec;
1030 stx.atime.nsec = @as(u32, @intCast(st.atim.nsec)); // Guaranteed to succeed (nsec is always below 10^9)
1031
1032 stx.mtime = std.mem.zeroes(l.statx_timestamp);
1033 stx.mtime.sec = st.mtim.sec;
1034 stx.mtime.nsec = @as(u32, @intCast(st.mtim.nsec));
1035
1036 stx.mask = l.STATX_BASIC_STATS | l.STATX_MTIME;
1037 },
1038 .BADF => unreachable,1078 .BADF => unreachable,
1039 .FAULT => unreachable,1079 .FAULT => unreachable,
1080 .INVAL => unreachable,
1081 .LOOP => unreachable,
1082 .NAMETOOLONG => unreachable,
1083 .NOENT => unreachable,
1040 .NOMEM => return error.SystemResources,1084 .NOMEM => return error.SystemResources,
1085 .NOTDIR => unreachable,
1041 else => |err| return posix.unexpectedErrno(err),1086 else => |err| return posix.unexpectedErrno(err),
1042 }1087 }
10431088
...@@ -1731,6 +1776,7 @@ const posix = std.posix;...@@ -1731,6 +1776,7 @@ const posix = std.posix;
1731const io = std.io;1776const io = std.io;
1732const math = std.math;1777const math = std.math;
1733const assert = std.debug.assert;1778const assert = std.debug.assert;
1779const linux = std.os.linux;
1734const windows = std.os.windows;1780const windows = std.os.windows;
1735const Os = std.builtin.Os;1781const Os = std.builtin.Os;
1736const maxInt = std.math.maxInt;1782const maxInt = std.math.maxInt;
lib/std/os/linux.zig+61-37
...@@ -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,
...@@ -474,7 +476,7 @@ pub fn dup2(old: i32, new: i32) usize {...@@ -474,7 +476,7 @@ pub fn dup2(old: i32, new: i32) usize {
474 } else {476 } else {
475 if (old == new) {477 if (old == new) {
476 if (std.debug.runtime_safety) {478 if (std.debug.runtime_safety) {
477 const rc = syscall2(.fcntl, @as(usize, @bitCast(@as(isize, old))), F.GETFD);479 const rc = fcntl(F.GETFD, @as(fd_t, old), 0);
478 if (@as(isize, @bitCast(rc)) < 0) return rc;480 if (@as(isize, @bitCast(rc)) < 0) return rc;
479 }481 }
480 return @as(usize, @intCast(old));482 return @as(usize, @intCast(old));
...@@ -1211,7 +1213,7 @@ pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize {...@@ -1211,7 +1213,7 @@ pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize {
1211 // NOTE: The offset parameter splitting is independent from the target1213 // NOTE: The offset parameter splitting is independent from the target
1212 // endianness.1214 // endianness.
1213 return syscall5(1215 return syscall5(
1214 ._llseek,1216 .llseek,
1215 @as(usize, @bitCast(@as(isize, fd))),1217 @as(usize, @bitCast(@as(isize, fd))),
1216 @as(usize, @truncate(offset >> 32)),1218 @as(usize, @truncate(offset >> 32)),
1217 @as(usize, @truncate(offset)),1219 @as(usize, @truncate(offset)),
...@@ -1370,7 +1372,11 @@ pub fn waitid(id_type: P, id: i32, infop: *siginfo_t, flags: u32) usize {...@@ -1370,7 +1372,11 @@ pub fn waitid(id_type: P, id: i32, infop: *siginfo_t, flags: u32) usize {
1370}1372}
13711373
1372pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) usize {1374pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) usize {
1373 return syscall3(.fcntl, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg);1375 if (@hasField(SYS, "fcntl64")) {
1376 return syscall3(.fcntl64, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg);
1377 } else {
1378 return syscall3(.fcntl, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg);
1379 }
1374}1380}
13751381
1376pub fn flock(fd: fd_t, operation: i32) usize {1382pub fn flock(fd: fd_t, operation: i32) usize {
...@@ -1836,7 +1842,11 @@ pub fn accept4(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t, flag...@@ -1836,7 +1842,11 @@ pub fn accept4(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t, flag
1836}1842}
18371843
1838pub fn fstat(fd: i32, stat_buf: *Stat) usize {1844pub fn fstat(fd: i32, stat_buf: *Stat) usize {
1839 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")) {
1840 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));
1841 } else {1851 } else {
1842 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));
...@@ -1844,7 +1854,11 @@ pub fn fstat(fd: i32, stat_buf: *Stat) usize {...@@ -1844,7 +1854,11 @@ pub fn fstat(fd: i32, stat_buf: *Stat) usize {
1844}1854}
18451855
1846pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize {1856pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize {
1847 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")) {
1848 return syscall2(.stat64, @intFromPtr(pathname), @intFromPtr(statbuf));1862 return syscall2(.stat64, @intFromPtr(pathname), @intFromPtr(statbuf));
1849 } else {1863 } else {
1850 return syscall2(.stat, @intFromPtr(pathname), @intFromPtr(statbuf));1864 return syscall2(.stat, @intFromPtr(pathname), @intFromPtr(statbuf));
...@@ -1852,7 +1866,11 @@ pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize {...@@ -1852,7 +1866,11 @@ pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize {
1852}1866}
18531867
1854pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {1868pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {
1855 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")) {
1856 return syscall2(.lstat64, @intFromPtr(pathname), @intFromPtr(statbuf));1874 return syscall2(.lstat64, @intFromPtr(pathname), @intFromPtr(statbuf));
1857 } else {1875 } else {
1858 return syscall2(.lstat, @intFromPtr(pathname), @intFromPtr(statbuf));1876 return syscall2(.lstat, @intFromPtr(pathname), @intFromPtr(statbuf));
...@@ -1860,7 +1878,11 @@ pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {...@@ -1860,7 +1878,11 @@ pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {
1860}1878}
18611879
1862pub 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 {
1863 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")) {
1864 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);
1865 } else {1887 } else {
1866 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);
...@@ -1868,17 +1890,14 @@ pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *Stat, flags: u32) usi...@@ -1868,17 +1890,14 @@ pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *Stat, flags: u32) usi
1868}1890}
18691891
1870pub fn statx(dirfd: i32, path: [*:0]const u8, flags: u32, mask: u32, statx_buf: *Statx) usize {1892pub fn statx(dirfd: i32, path: [*:0]const u8, flags: u32, mask: u32, statx_buf: *Statx) usize {
1871 if (@hasField(SYS, "statx")) {1893 return syscall5(
1872 return syscall5(1894 .statx,
1873 .statx,1895 @as(usize, @bitCast(@as(isize, dirfd))),
1874 @as(usize, @bitCast(@as(isize, dirfd))),1896 @intFromPtr(path),
1875 @intFromPtr(path),1897 flags,
1876 flags,1898 mask,
1877 mask,1899 @intFromPtr(statx_buf),
1878 @intFromPtr(statx_buf),1900 );
1879 );
1880 }
1881 return @as(usize, @bitCast(-@as(isize, @intFromEnum(E.NOSYS))));
1882}1901}
18831902
1884pub fn listxattr(path: [*:0]const u8, list: [*]u8, size: usize) usize {1903pub fn listxattr(path: [*:0]const u8, list: [*]u8, size: usize) usize {
...@@ -2198,40 +2217,40 @@ pub fn process_vm_writev(pid: pid_t, local: []const iovec_const, remote: []const...@@ -2198,40 +2217,40 @@ pub fn process_vm_writev(pid: pid_t, local: []const iovec_const, remote: []const
2198}2217}
21992218
2200pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize {2219pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize {
2201 if (comptime builtin.cpu.arch.isMIPS()) {2220 if (comptime native_arch.isARM() or native_arch.isPPC()) {
2202 // MIPS requires a 7 argument syscall2221 // These architectures reorder the arguments so that a register is not skipped to align the
2222 // register number that `offset` is passed in.
22032223
2204 const offset_halves = splitValue64(offset);2224 const offset_halves = splitValue64(offset);
2205 const length_halves = splitValue64(len);2225 const length_halves = splitValue64(len);
22062226
2207 return syscall7(2227 return syscall6(
2208 .fadvise64,2228 .fadvise64_64,
2209 @as(usize, @bitCast(@as(isize, fd))),2229 @as(usize, @bitCast(@as(isize, fd))),
2210 0,2230 advice,
2211 offset_halves[0],2231 offset_halves[0],
2212 offset_halves[1],2232 offset_halves[1],
2213 length_halves[0],2233 length_halves[0],
2214 length_halves[1],2234 length_halves[1],
2215 advice,
2216 );2235 );
2217 } else if (comptime builtin.cpu.arch.isARM()) {2236 } else if (comptime native_arch == .mips or native_arch == .mipsel) {
2218 // ARM reorders the arguments2237 // MIPS O32 does not deal with the register alignment issue, so pass a dummy value.
22192238
2220 const offset_halves = splitValue64(offset);2239 const offset_halves = splitValue64(offset);
2221 const length_halves = splitValue64(len);2240 const length_halves = splitValue64(len);
22222241
2223 return syscall6(2242 return syscall7(
2224 .fadvise64_64,2243 .fadvise64,
2225 @as(usize, @bitCast(@as(isize, fd))),2244 @as(usize, @bitCast(@as(isize, fd))),
2226 advice,2245 0,
2227 offset_halves[0],2246 offset_halves[0],
2228 offset_halves[1],2247 offset_halves[1],
2229 length_halves[0],2248 length_halves[0],
2230 length_halves[1],2249 length_halves[1],
2250 advice,
2231 );2251 );
2232 } else if (@hasField(SYS, "fadvise64_64") and usize_bits != 64) {2252 } else if (comptime usize_bits < 64) {
2233 // The extra usize check is needed to avoid SPARC64 because it provides both2253 // Other 32-bit architectures do not require register alignment.
2234 // fadvise64 and fadvise64_64 but the latter behaves differently than other platforms.
22352254
2236 const offset_halves = splitValue64(offset);2255 const offset_halves = splitValue64(offset);
2237 const length_halves = splitValue64(len);2256 const length_halves = splitValue64(len);
...@@ -2246,8 +2265,11 @@ pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize {...@@ -2246,8 +2265,11 @@ pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize {
2246 advice,2265 advice,
2247 );2266 );
2248 } else {2267 } else {
2268 // On 64-bit architectures, fadvise64_64 and fadvise64 are the same. Generally, older ports
2269 // call it fadvise64 (x86, PowerPC, etc), while newer ports call it fadvise64_64 (RISC-V,
2270 // LoongArch, etc). SPARC is the odd one out because it has both.
2249 return syscall4(2271 return syscall4(
2250 .fadvise64,2272 if (@hasField(SYS, "fadvise64_64")) .fadvise64_64 else .fadvise64,
2251 @as(usize, @bitCast(@as(isize, fd))),2273 @as(usize, @bitCast(@as(isize, fd))),
2252 @as(usize, @bitCast(offset)),2274 @as(usize, @bitCast(offset)),
2253 @as(usize, @bitCast(len)),2275 @as(usize, @bitCast(len)),
...@@ -6295,12 +6317,13 @@ pub const POSIX_FADV = switch (native_arch) {...@@ -6295,12 +6317,13 @@ pub const POSIX_FADV = switch (native_arch) {
6295};6317};
62966318
6297/// The timespec struct used by the kernel.6319/// The timespec struct used by the kernel.
6298pub const kernel_timespec = if (@sizeOf(usize) >= 8) timespec else extern struct {6320pub const kernel_timespec = extern struct {
6299 sec: i64,6321 sec: i64,
6300 nsec: i64,6322 nsec: i64,
6301};6323};
63026324
6303pub const timespec = extern struct {6325// https://github.com/ziglang/zig/issues/4726#issuecomment-2190337877
6326pub const timespec = if (!builtin.link_libc and native_arch == .riscv32) kernel_timespec else extern struct {
6304 sec: isize,6327 sec: isize,
6305 nsec: isize,6328 nsec: isize,
6306};6329};
...@@ -7338,6 +7361,7 @@ pub const AUDIT = struct {...@@ -7338,6 +7361,7 @@ pub const AUDIT = struct {
7338 .x86_64 => .X86_64,7361 .x86_64 => .X86_64,
7339 .aarch64 => .AARCH64,7362 .aarch64 => .AARCH64,
7340 .arm, .thumb => .ARM,7363 .arm, .thumb => .ARM,
7364 .riscv32 => .RISCV32,
7341 .riscv64 => .RISCV64,7365 .riscv64 => .RISCV64,
7342 .sparc64 => .SPARC64,7366 .sparc64 => .SPARC64,
7343 .mips => .MIPS,7367 .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,
lib/std/os/linux/start_pie.zig+2-2
...@@ -26,7 +26,7 @@ const R_RELATIVE = switch (builtin.cpu.arch) {...@@ -26,7 +26,7 @@ const R_RELATIVE = switch (builtin.cpu.arch) {
26 .hexagon => R_HEXAGON_RELATIVE,26 .hexagon => R_HEXAGON_RELATIVE,
27 .loongarch32, .loongarch64 => R_LARCH_RELATIVE,27 .loongarch32, .loongarch64 => R_LARCH_RELATIVE,
28 .m68k => R_68K_RELATIVE,28 .m68k => R_68K_RELATIVE,
29 .riscv64 => R_RISCV_RELATIVE,29 .riscv32, .riscv64 => R_RISCV_RELATIVE,
30 .s390x => R_390_RELATIVE,30 .s390x => R_390_RELATIVE,
31 else => @compileError("Missing R_RELATIVE definition for this target"),31 else => @compileError("Missing R_RELATIVE definition for this target"),
32};32};
...@@ -111,7 +111,7 @@ fn getDynamicSymbol() [*]elf.Dyn {...@@ -111,7 +111,7 @@ fn getDynamicSymbol() [*]elf.Dyn {
111 \\ lea (%[ret], %%pc), %[ret]111 \\ lea (%[ret], %%pc), %[ret]
112 : [ret] "=r" (-> [*]elf.Dyn),112 : [ret] "=r" (-> [*]elf.Dyn),
113 ),113 ),
114 .riscv64 => asm volatile (114 .riscv32, .riscv64 => asm volatile (
115 \\ .weak _DYNAMIC115 \\ .weak _DYNAMIC
116 \\ .hidden _DYNAMIC116 \\ .hidden _DYNAMIC
117 \\ lla %[ret], _DYNAMIC117 \\ lla %[ret], _DYNAMIC
lib/std/os/linux/syscalls.zig+337-33
...@@ -142,16 +142,16 @@ pub const X86 = enum(usize) {...@@ -142,16 +142,16 @@ pub const X86 = enum(usize) {
142 afs_syscall = 137,142 afs_syscall = 137,
143 setfsuid = 138,143 setfsuid = 138,
144 setfsgid = 139,144 setfsgid = 139,
145 _llseek = 140,145 llseek = 140,
146 getdents = 141,146 getdents = 141,
147 _newselect = 142,147 newselect = 142,
148 flock = 143,148 flock = 143,
149 msync = 144,149 msync = 144,
150 readv = 145,150 readv = 145,
151 writev = 146,151 writev = 146,
152 getsid = 147,152 getsid = 147,
153 fdatasync = 148,153 fdatasync = 148,
154 _sysctl = 149,154 sysctl = 149,
155 mlock = 150,155 mlock = 150,
156 munlock = 151,156 munlock = 151,
157 mlockall = 152,157 mlockall = 152,
...@@ -607,7 +607,7 @@ pub const X64 = enum(usize) {...@@ -607,7 +607,7 @@ pub const X64 = enum(usize) {
607 vhangup = 153,607 vhangup = 153,
608 modify_ldt = 154,608 modify_ldt = 154,
609 pivot_root = 155,609 pivot_root = 155,
610 _sysctl = 156,610 sysctl = 156,
611 prctl = 157,611 prctl = 157,
612 arch_prctl = 158,612 arch_prctl = 158,
613 adjtimex = 159,613 adjtimex = 159,
...@@ -927,16 +927,16 @@ pub const Arm = enum(usize) {...@@ -927,16 +927,16 @@ pub const Arm = enum(usize) {
927 personality = 136,927 personality = 136,
928 setfsuid = 138,928 setfsuid = 138,
929 setfsgid = 139,929 setfsgid = 139,
930 _llseek = 140,930 llseek = 140,
931 getdents = 141,931 getdents = 141,
932 _newselect = 142,932 newselect = 142,
933 flock = 143,933 flock = 143,
934 msync = 144,934 msync = 144,
935 readv = 145,935 readv = 145,
936 writev = 146,936 writev = 146,
937 getsid = 147,937 getsid = 147,
938 fdatasync = 148,938 fdatasync = 148,
939 _sysctl = 149,939 sysctl = 149,
940 mlock = 150,940 mlock = 150,
941 munlock = 151,941 munlock = 151,
942 mlockall = 152,942 mlockall = 152,
...@@ -1454,12 +1454,12 @@ pub const Sparc64 = enum(usize) {...@@ -1454,12 +1454,12 @@ pub const Sparc64 = enum(usize) {
1454 afs_syscall = 227,1454 afs_syscall = 227,
1455 setfsuid = 228,1455 setfsuid = 228,
1456 setfsgid = 229,1456 setfsgid = 229,
1457 _newselect = 230,1457 newselect = 230,
1458 splice = 232,1458 splice = 232,
1459 stime = 233,1459 stime = 233,
1460 statfs64 = 234,1460 statfs64 = 234,
1461 fstatfs64 = 235,1461 fstatfs64 = 235,
1462 _llseek = 236,1462 llseek = 236,
1463 mlock = 237,1463 mlock = 237,
1464 munlock = 238,1464 munlock = 238,
1465 mlockall = 239,1465 mlockall = 239,
...@@ -1474,7 +1474,7 @@ pub const Sparc64 = enum(usize) {...@@ -1474,7 +1474,7 @@ pub const Sparc64 = enum(usize) {
1474 sched_rr_get_interval = 248,1474 sched_rr_get_interval = 248,
1475 nanosleep = 249,1475 nanosleep = 249,
1476 mremap = 250,1476 mremap = 250,
1477 _sysctl = 251,1477 sysctl = 251,
1478 getsid = 252,1478 getsid = 252,
1479 fdatasync = 253,1479 fdatasync = 253,
1480 nfsservctl = 254,1480 nfsservctl = 254,
...@@ -1771,9 +1771,9 @@ pub const Mips = enum(usize) {...@@ -1771,9 +1771,9 @@ pub const Mips = enum(usize) {
1771 afs_syscall = Linux + 137,1771 afs_syscall = Linux + 137,
1772 setfsuid = Linux + 138,1772 setfsuid = Linux + 138,
1773 setfsgid = Linux + 139,1773 setfsgid = Linux + 139,
1774 _llseek = Linux + 140,1774 llseek = Linux + 140,
1775 getdents = Linux + 141,1775 getdents = Linux + 141,
1776 _newselect = Linux + 142,1776 newselect = Linux + 142,
1777 flock = Linux + 143,1777 flock = Linux + 143,
1778 msync = Linux + 144,1778 msync = Linux + 144,
1779 readv = Linux + 145,1779 readv = Linux + 145,
...@@ -1783,7 +1783,7 @@ pub const Mips = enum(usize) {...@@ -1783,7 +1783,7 @@ pub const Mips = enum(usize) {
1783 sysmips = Linux + 149,1783 sysmips = Linux + 149,
1784 getsid = Linux + 151,1784 getsid = Linux + 151,
1785 fdatasync = Linux + 152,1785 fdatasync = Linux + 152,
1786 _sysctl = Linux + 153,1786 sysctl = Linux + 153,
1787 mlock = Linux + 154,1787 mlock = Linux + 154,
1788 munlock = Linux + 155,1788 munlock = Linux + 155,
1789 mlockall = Linux + 156,1789 mlockall = Linux + 156,
...@@ -2087,7 +2087,7 @@ pub const Mips64 = enum(usize) {...@@ -2087,7 +2087,7 @@ pub const Mips64 = enum(usize) {
2087 writev = Linux + 19,2087 writev = Linux + 19,
2088 access = Linux + 20,2088 access = Linux + 20,
2089 pipe = Linux + 21,2089 pipe = Linux + 21,
2090 _newselect = Linux + 22,2090 newselect = Linux + 22,
2091 sched_yield = Linux + 23,2091 sched_yield = Linux + 23,
2092 mremap = Linux + 24,2092 mremap = Linux + 24,
2093 msync = Linux + 25,2093 msync = Linux + 25,
...@@ -2217,7 +2217,7 @@ pub const Mips64 = enum(usize) {...@@ -2217,7 +2217,7 @@ pub const Mips64 = enum(usize) {
2217 munlockall = Linux + 149,2217 munlockall = Linux + 149,
2218 vhangup = Linux + 150,2218 vhangup = Linux + 150,
2219 pivot_root = Linux + 151,2219 pivot_root = Linux + 151,
2220 _sysctl = Linux + 152,2220 sysctl = Linux + 152,
2221 prctl = Linux + 153,2221 prctl = Linux + 153,
2222 adjtimex = Linux + 154,2222 adjtimex = Linux + 154,
2223 setrlimit = Linux + 155,2223 setrlimit = Linux + 155,
...@@ -2568,16 +2568,16 @@ pub const PowerPC = enum(usize) {...@@ -2568,16 +2568,16 @@ pub const PowerPC = enum(usize) {
2568 afs_syscall = 137,2568 afs_syscall = 137,
2569 setfsuid = 138,2569 setfsuid = 138,
2570 setfsgid = 139,2570 setfsgid = 139,
2571 _llseek = 140,2571 llseek = 140,
2572 getdents = 141,2572 getdents = 141,
2573 _newselect = 142,2573 newselect = 142,
2574 flock = 143,2574 flock = 143,
2575 msync = 144,2575 msync = 144,
2576 readv = 145,2576 readv = 145,
2577 writev = 146,2577 writev = 146,
2578 getsid = 147,2578 getsid = 147,
2579 fdatasync = 148,2579 fdatasync = 148,
2580 _sysctl = 149,2580 sysctl = 149,
2581 mlock = 150,2581 mlock = 150,
2582 munlock = 151,2582 munlock = 151,
2583 mlockall = 152,2583 mlockall = 152,
...@@ -3008,16 +3008,16 @@ pub const PowerPC64 = enum(usize) {...@@ -3008,16 +3008,16 @@ pub const PowerPC64 = enum(usize) {
3008 afs_syscall = 137,3008 afs_syscall = 137,
3009 setfsuid = 138,3009 setfsuid = 138,
3010 setfsgid = 139,3010 setfsgid = 139,
3011 _llseek = 140,3011 llseek = 140,
3012 getdents = 141,3012 getdents = 141,
3013 _newselect = 142,3013 newselect = 142,
3014 flock = 143,3014 flock = 143,
3015 msync = 144,3015 msync = 144,
3016 readv = 145,3016 readv = 145,
3017 writev = 146,3017 writev = 146,
3018 getsid = 147,3018 getsid = 147,
3019 fdatasync = 148,3019 fdatasync = 148,
3020 _sysctl = 149,3020 sysctl = 149,
3021 mlock = 150,3021 mlock = 150,
3022 munlock = 151,3022 munlock = 151,
3023 mlockall = 152,3023 mlockall = 152,
...@@ -3351,7 +3351,7 @@ pub const Arm64 = enum(usize) {...@@ -3351,7 +3351,7 @@ pub const Arm64 = enum(usize) {
3351 pwrite64 = 68,3351 pwrite64 = 68,
3352 preadv = 69,3352 preadv = 69,
3353 pwritev = 70,3353 pwritev = 70,
3354 sendfile = 71,3354 sendfile64 = 71,
3355 pselect6 = 72,3355 pselect6 = 72,
3356 ppoll = 73,3356 ppoll = 73,
3357 signalfd4 = 74,3357 signalfd4 = 74,
...@@ -3359,8 +3359,8 @@ pub const Arm64 = enum(usize) {...@@ -3359,8 +3359,8 @@ pub const Arm64 = enum(usize) {
3359 splice = 76,3359 splice = 76,
3360 tee = 77,3360 tee = 77,
3361 readlinkat = 78,3361 readlinkat = 78,
3362 fstatat = 79,3362 fstatat64 = 79,
3363 fstat = 80,3363 fstat64 = 80,
3364 sync = 81,3364 sync = 81,
3365 fsync = 82,3365 fsync = 82,
3366 fdatasync = 83,3366 fdatasync = 83,
...@@ -3503,7 +3503,7 @@ pub const Arm64 = enum(usize) {...@@ -3503,7 +3503,7 @@ pub const Arm64 = enum(usize) {
3503 clone = 220,3503 clone = 220,
3504 execve = 221,3504 execve = 221,
3505 mmap = 222,3505 mmap = 222,
3506 fadvise64 = 223,3506 fadvise64_64 = 223,
3507 swapon = 224,3507 swapon = 224,
3508 swapoff = 225,3508 swapoff = 225,
3509 mprotect = 226,3509 mprotect = 226,
...@@ -3594,9 +3594,313 @@ pub const Arm64 = enum(usize) {...@@ -3594,9 +3594,313 @@ pub const Arm64 = enum(usize) {
3594 futex_requeue = 456,3594 futex_requeue = 456,
3595};3595};
35963596
3597pub const RiscV64 = enum(usize) {3597pub const RiscV32 = enum(usize) {
3598 pub const arch_specific_syscall = 244;3598 io_setup = 0,
3599 io_destroy = 1,
3600 io_submit = 2,
3601 io_cancel = 3,
3602 setxattr = 5,
3603 lsetxattr = 6,
3604 fsetxattr = 7,
3605 getxattr = 8,
3606 lgetxattr = 9,
3607 fgetxattr = 10,
3608 listxattr = 11,
3609 llistxattr = 12,
3610 flistxattr = 13,
3611 removexattr = 14,
3612 lremovexattr = 15,
3613 fremovexattr = 16,
3614 getcwd = 17,
3615 lookup_dcookie = 18,
3616 eventfd2 = 19,
3617 epoll_create1 = 20,
3618 epoll_ctl = 21,
3619 epoll_pwait = 22,
3620 dup = 23,
3621 dup3 = 24,
3622 fcntl64 = 25,
3623 inotify_init1 = 26,
3624 inotify_add_watch = 27,
3625 inotify_rm_watch = 28,
3626 ioctl = 29,
3627 ioprio_set = 30,
3628 ioprio_get = 31,
3629 flock = 32,
3630 mknodat = 33,
3631 mkdirat = 34,
3632 unlinkat = 35,
3633 symlinkat = 36,
3634 linkat = 37,
3635 umount2 = 39,
3636 mount = 40,
3637 pivot_root = 41,
3638 nfsservctl = 42,
3639 statfs64 = 43,
3640 fstatfs64 = 44,
3641 truncate64 = 45,
3642 ftruncate64 = 46,
3643 fallocate = 47,
3644 faccessat = 48,
3645 chdir = 49,
3646 fchdir = 50,
3647 chroot = 51,
3648 fchmod = 52,
3649 fchmodat = 53,
3650 fchownat = 54,
3651 fchown = 55,
3652 openat = 56,
3653 close = 57,
3654 vhangup = 58,
3655 pipe2 = 59,
3656 quotactl = 60,
3657 getdents64 = 61,
3658 llseek = 62,
3659 read = 63,
3660 write = 64,
3661 readv = 65,
3662 writev = 66,
3663 pread64 = 67,
3664 pwrite64 = 68,
3665 preadv = 69,
3666 pwritev = 70,
3667 sendfile64 = 71,
3668 signalfd4 = 74,
3669 vmsplice = 75,
3670 splice = 76,
3671 tee = 77,
3672 readlinkat = 78,
3673 sync = 81,
3674 fsync = 82,
3675 fdatasync = 83,
3676 sync_file_range = 84,
3677 timerfd_create = 85,
3678 acct = 89,
3679 capget = 90,
3680 capset = 91,
3681 personality = 92,
3682 exit = 93,
3683 exit_group = 94,
3684 waitid = 95,
3685 set_tid_address = 96,
3686 unshare = 97,
3687 set_robust_list = 99,
3688 get_robust_list = 100,
3689 getitimer = 102,
3690 setitimer = 103,
3691 kexec_load = 104,
3692 init_module = 105,
3693 delete_module = 106,
3694 timer_create = 107,
3695 timer_getoverrun = 109,
3696 timer_delete = 111,
3697 syslog = 116,
3698 ptrace = 117,
3699 sched_setparam = 118,
3700 sched_setscheduler = 119,
3701 sched_getscheduler = 120,
3702 sched_getparam = 121,
3703 sched_setaffinity = 122,
3704 sched_getaffinity = 123,
3705 sched_yield = 124,
3706 sched_get_priority_max = 125,
3707 sched_get_priority_min = 126,
3708 restart_syscall = 128,
3709 kill = 129,
3710 tkill = 130,
3711 tgkill = 131,
3712 sigaltstack = 132,
3713 rt_sigsuspend = 133,
3714 rt_sigaction = 134,
3715 rt_sigprocmask = 135,
3716 rt_sigpending = 136,
3717 rt_sigqueueinfo = 138,
3718 rt_sigreturn = 139,
3719 setpriority = 140,
3720 getpriority = 141,
3721 reboot = 142,
3722 setregid = 143,
3723 setgid = 144,
3724 setreuid = 145,
3725 setuid = 146,
3726 setresuid = 147,
3727 getresuid = 148,
3728 setresgid = 149,
3729 getresgid = 150,
3730 setfsuid = 151,
3731 setfsgid = 152,
3732 times = 153,
3733 setpgid = 154,
3734 getpgid = 155,
3735 getsid = 156,
3736 setsid = 157,
3737 getgroups = 158,
3738 setgroups = 159,
3739 uname = 160,
3740 sethostname = 161,
3741 setdomainname = 162,
3742 getrusage = 165,
3743 umask = 166,
3744 prctl = 167,
3745 getcpu = 168,
3746 getpid = 172,
3747 getppid = 173,
3748 getuid = 174,
3749 geteuid = 175,
3750 getgid = 176,
3751 getegid = 177,
3752 gettid = 178,
3753 sysinfo = 179,
3754 mq_open = 180,
3755 mq_unlink = 181,
3756 mq_notify = 184,
3757 mq_getsetattr = 185,
3758 msgget = 186,
3759 msgctl = 187,
3760 msgrcv = 188,
3761 msgsnd = 189,
3762 semget = 190,
3763 semctl = 191,
3764 semop = 193,
3765 shmget = 194,
3766 shmctl = 195,
3767 shmat = 196,
3768 shmdt = 197,
3769 socket = 198,
3770 socketpair = 199,
3771 bind = 200,
3772 listen = 201,
3773 accept = 202,
3774 connect = 203,
3775 getsockname = 204,
3776 getpeername = 205,
3777 sendto = 206,
3778 recvfrom = 207,
3779 setsockopt = 208,
3780 getsockopt = 209,
3781 shutdown = 210,
3782 sendmsg = 211,
3783 recvmsg = 212,
3784 readahead = 213,
3785 brk = 214,
3786 munmap = 215,
3787 mremap = 216,
3788 add_key = 217,
3789 request_key = 218,
3790 keyctl = 219,
3791 clone = 220,
3792 execve = 221,
3793 mmap2 = 222,
3794 fadvise64_64 = 223,
3795 swapon = 224,
3796 swapoff = 225,
3797 mprotect = 226,
3798 msync = 227,
3799 mlock = 228,
3800 munlock = 229,
3801 mlockall = 230,
3802 munlockall = 231,
3803 mincore = 232,
3804 madvise = 233,
3805 remap_file_pages = 234,
3806 mbind = 235,
3807 get_mempolicy = 236,
3808 set_mempolicy = 237,
3809 migrate_pages = 238,
3810 move_pages = 239,
3811 rt_tgsigqueueinfo = 240,
3812 perf_event_open = 241,
3813 accept4 = 242,
3814 prlimit64 = 261,
3815 fanotify_init = 262,
3816 fanotify_mark = 263,
3817 name_to_handle_at = 264,
3818 open_by_handle_at = 265,
3819 syncfs = 267,
3820 setns = 268,
3821 sendmmsg = 269,
3822 process_vm_readv = 270,
3823 process_vm_writev = 271,
3824 kcmp = 272,
3825 finit_module = 273,
3826 sched_setattr = 274,
3827 sched_getattr = 275,
3828 renameat2 = 276,
3829 seccomp = 277,
3830 getrandom = 278,
3831 memfd_create = 279,
3832 bpf = 280,
3833 execveat = 281,
3834 userfaultfd = 282,
3835 membarrier = 283,
3836 mlock2 = 284,
3837 copy_file_range = 285,
3838 preadv2 = 286,
3839 pwritev2 = 287,
3840 pkey_mprotect = 288,
3841 pkey_alloc = 289,
3842 pkey_free = 290,
3843 statx = 291,
3844 rseq = 293,
3845 kexec_file_load = 294,
3846 clock_gettime = 403,
3847 clock_settime = 404,
3848 clock_adjtime = 405,
3849 clock_getres = 406,
3850 clock_nanosleep = 407,
3851 timer_gettime = 408,
3852 timer_settime = 409,
3853 timerfd_gettime = 410,
3854 timerfd_settime = 411,
3855 utimensat = 412,
3856 pselect6 = 413,
3857 ppoll = 414,
3858 io_pgetevents = 416,
3859 recvmmsg = 417,
3860 mq_timedsend = 418,
3861 mq_timedreceive = 419,
3862 semtimedop = 420,
3863 rt_sigtimedwait = 421,
3864 futex = 422,
3865 sched_rr_get_interval = 423,
3866 pidfd_send_signal = 424,
3867 io_uring_setup = 425,
3868 io_uring_enter = 426,
3869 io_uring_register = 427,
3870 open_tree = 428,
3871 move_mount = 429,
3872 fsopen = 430,
3873 fsconfig = 431,
3874 fsmount = 432,
3875 fspick = 433,
3876 pidfd_open = 434,
3877 clone3 = 435,
3878 close_range = 436,
3879 openat2 = 437,
3880 pidfd_getfd = 438,
3881 faccessat2 = 439,
3882 process_madvise = 440,
3883 epoll_pwait2 = 441,
3884 mount_setattr = 442,
3885 quotactl_fd = 443,
3886 landlock_create_ruleset = 444,
3887 landlock_add_rule = 445,
3888 landlock_restrict_self = 446,
3889 memfd_secret = 447,
3890 process_mrelease = 448,
3891 futex_waitv = 449,
3892 set_mempolicy_home_node = 450,
3893 cachestat = 451,
3894 fchmodat2 = 452,
3895 map_shadow_stack = 453,
3896 futex_wake = 454,
3897 futex_wait = 455,
3898 futex_requeue = 456,
3899 riscv_flush_icache = (244 + 15),
3900 riscv_hwprobe = (244 + 14),
3901};
35993902
3903pub const RiscV64 = enum(usize) {
3600 io_setup = 0,3904 io_setup = 0,
3601 io_destroy = 1,3905 io_destroy = 1,
3602 io_submit = 2,3906 io_submit = 2,
...@@ -3667,7 +3971,7 @@ pub const RiscV64 = enum(usize) {...@@ -3667,7 +3971,7 @@ pub const RiscV64 = enum(usize) {
3667 pwrite64 = 68,3971 pwrite64 = 68,
3668 preadv = 69,3972 preadv = 69,
3669 pwritev = 70,3973 pwritev = 70,
3670 sendfile = 71,3974 sendfile64 = 71,
3671 pselect6 = 72,3975 pselect6 = 72,
3672 ppoll = 73,3976 ppoll = 73,
3673 signalfd4 = 74,3977 signalfd4 = 74,
...@@ -3675,8 +3979,8 @@ pub const RiscV64 = enum(usize) {...@@ -3675,8 +3979,8 @@ pub const RiscV64 = enum(usize) {
3675 splice = 76,3979 splice = 76,
3676 tee = 77,3980 tee = 77,
3677 readlinkat = 78,3981 readlinkat = 78,
3678 fstatat = 79,3982 fstatat64 = 79,
3679 fstat = 80,3983 fstat64 = 80,
3680 sync = 81,3984 sync = 81,
3681 fsync = 82,3985 fsync = 82,
3682 fdatasync = 83,3986 fdatasync = 83,
...@@ -3819,7 +4123,7 @@ pub const RiscV64 = enum(usize) {...@@ -3819,7 +4123,7 @@ pub const RiscV64 = enum(usize) {
3819 clone = 220,4123 clone = 220,
3820 execve = 221,4124 execve = 221,
3821 mmap = 222,4125 mmap = 222,
3822 fadvise64 = 223,4126 fadvise64_64 = 223,
3823 swapon = 224,4127 swapon = 224,
3824 swapoff = 225,4128 swapoff = 225,
3825 mprotect = 226,4129 mprotect = 226,
...@@ -3908,8 +4212,8 @@ pub const RiscV64 = enum(usize) {...@@ -3908,8 +4212,8 @@ pub const RiscV64 = enum(usize) {
3908 futex_wake = 454,4212 futex_wake = 454,
3909 futex_wait = 455,4213 futex_wait = 455,
3910 futex_requeue = 456,4214 futex_requeue = 456,
39114215 riscv_flush_icache = (244 + 15),
3912 riscv_flush_icache = arch_specific_syscall + 15,4216 riscv_hwprobe = (244 + 14),
3913};4217};
39144218
3915pub const LoongArch64 = enum(usize) {4219pub const LoongArch64 = enum(usize) {
lib/std/os/linux/test.zig+2-2
...@@ -79,11 +79,11 @@ test "statx" {...@@ -79,11 +79,11 @@ test "statx" {
79 var statx_buf: linux.Statx = undefined;79 var statx_buf: linux.Statx = undefined;
80 switch (linux.E.init(linux.statx(file.handle, "", linux.AT.EMPTY_PATH, linux.STATX_BASIC_STATS, &statx_buf))) {80 switch (linux.E.init(linux.statx(file.handle, "", linux.AT.EMPTY_PATH, linux.STATX_BASIC_STATS, &statx_buf))) {
81 .SUCCESS => {},81 .SUCCESS => {},
82 // The statx syscall was only introduced in linux 4.11
83 .NOSYS => return error.SkipZigTest,
84 else => unreachable,82 else => unreachable,
85 }83 }
8684
85 if (builtin.cpu.arch == .riscv32) return error.SkipZigTest; // No fstatat, so the rest of the test is meaningless.
86
87 var stat_buf: linux.Stat = undefined;87 var stat_buf: linux.Stat = undefined;
88 switch (linux.E.init(linux.fstatat(file.handle, "", &stat_buf, linux.AT.EMPTY_PATH))) {88 switch (linux.E.init(linux.fstatat(file.handle, "", &stat_buf, linux.AT.EMPTY_PATH))) {
89 .SUCCESS => {},89 .SUCCESS => {},
lib/std/os/linux/tls.zig+1-1
...@@ -170,7 +170,7 @@ pub fn setThreadPointer(addr: usize) void {...@@ -170,7 +170,7 @@ pub fn setThreadPointer(addr: usize) void {
170 const rc = @call(.always_inline, linux.syscall1, .{ .set_tls, addr });170 const rc = @call(.always_inline, linux.syscall1, .{ .set_tls, addr });
171 assert(rc == 0);171 assert(rc == 0);
172 },172 },
173 .riscv64 => {173 .riscv32, .riscv64 => {
174 asm volatile (174 asm volatile (
175 \\ mv tp, %[addr]175 \\ mv tp, %[addr]
176 :176 :
lib/std/posix.zig+4-32
...@@ -615,7 +615,6 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {...@@ -615,7 +615,6 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {
615 .INVAL => unreachable,615 .INVAL => unreachable,
616 .FAULT => unreachable,616 .FAULT => unreachable,
617 .INTR => continue,617 .INTR => continue,
618 .NOSYS => return getRandomBytesDevURandom(buf),
619 else => return unexpectedErrno(err),618 else => return unexpectedErrno(err),
620 }619 }
621 }620 }
...@@ -4534,7 +4533,6 @@ pub const FanotifyInitError = error{...@@ -4534,7 +4533,6 @@ pub const FanotifyInitError = error{
4534 ProcessFdQuotaExceeded,4533 ProcessFdQuotaExceeded,
4535 SystemFdQuotaExceeded,4534 SystemFdQuotaExceeded,
4536 SystemResources,4535 SystemResources,
4537 OperationNotSupported,
4538 PermissionDenied,4536 PermissionDenied,
4539} || UnexpectedError;4537} || UnexpectedError;
45404538
...@@ -4546,7 +4544,6 @@ pub fn fanotify_init(flags: std.os.linux.fanotify.InitFlags, event_f_flags: u32)...@@ -4546,7 +4544,6 @@ pub fn fanotify_init(flags: std.os.linux.fanotify.InitFlags, event_f_flags: u32)
4546 .MFILE => return error.ProcessFdQuotaExceeded,4544 .MFILE => return error.ProcessFdQuotaExceeded,
4547 .NFILE => return error.SystemFdQuotaExceeded,4545 .NFILE => return error.SystemFdQuotaExceeded,
4548 .NOMEM => return error.SystemResources,4546 .NOMEM => return error.SystemResources,
4549 .NOSYS => return error.OperationNotSupported,
4550 .PERM => return error.PermissionDenied,4547 .PERM => return error.PermissionDenied,
4551 else => |err| return unexpectedErrno(err),4548 else => |err| return unexpectedErrno(err),
4552 }4549 }
...@@ -4559,7 +4556,6 @@ pub const FanotifyMarkError = error{...@@ -4559,7 +4556,6 @@ pub const FanotifyMarkError = error{
4559 FileNotFound,4556 FileNotFound,
4560 SystemResources,4557 SystemResources,
4561 UserMarkQuotaExceeded,4558 UserMarkQuotaExceeded,
4562 NotImplemented,
4563 NotDir,4559 NotDir,
4564 OperationNotSupported,4560 OperationNotSupported,
4565 PermissionDenied,4561 PermissionDenied,
...@@ -4600,7 +4596,6 @@ pub fn fanotify_markZ(...@@ -4600,7 +4596,6 @@ pub fn fanotify_markZ(
4600 .NOENT => return error.FileNotFound,4596 .NOENT => return error.FileNotFound,
4601 .NOMEM => return error.SystemResources,4597 .NOMEM => return error.SystemResources,
4602 .NOSPC => return error.UserMarkQuotaExceeded,4598 .NOSPC => return error.UserMarkQuotaExceeded,
4603 .NOSYS => return error.NotImplemented,
4604 .NOTDIR => return error.NotDir,4599 .NOTDIR => return error.NotDir,
4605 .OPNOTSUPP => return error.OperationNotSupported,4600 .OPNOTSUPP => return error.OperationNotSupported,
4606 .PERM => return error.PermissionDenied,4601 .PERM => return error.PermissionDenied,
...@@ -6183,13 +6178,6 @@ pub fn sendfile(...@@ -6183,13 +6178,6 @@ pub fn sendfile(
61836178
6184 switch (native_os) {6179 switch (native_os) {
6185 .linux => sf: {6180 .linux => sf: {
6186 // sendfile() first appeared in Linux 2.2, glibc 2.1.
6187 const call_sf = comptime if (builtin.link_libc)
6188 std.c.versionCheck(.{ .major = 2, .minor = 1, .patch = 0 })
6189 else
6190 builtin.os.version_range.linux.range.max.order(.{ .major = 2, .minor = 2, .patch = 0 }) != .lt;
6191 if (!call_sf) break :sf;
6192
6193 if (headers.len != 0) {6181 if (headers.len != 0) {
6194 const amt = try writev(out_fd, headers);6182 const amt = try writev(out_fd, headers);
6195 total_written += amt;6183 total_written += amt;
...@@ -6223,14 +6211,14 @@ pub fn sendfile(...@@ -6223,14 +6211,14 @@ pub fn sendfile(
6223 .OVERFLOW => unreachable, // We avoid passing too large of a `count`.6211 .OVERFLOW => unreachable, // We avoid passing too large of a `count`.
6224 .NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket6212 .NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket
62256213
6226 .INVAL, .NOSYS => {6214 .INVAL => {
6227 // EINVAL could be any of the following situations:6215 // EINVAL could be any of the following situations:
6228 // * Descriptor is not valid or locked6216 // * Descriptor is not valid or locked
6229 // * an mmap(2)-like operation is not available for in_fd6217 // * an mmap(2)-like operation is not available for in_fd
6230 // * count is negative6218 // * count is negative
6231 // * out_fd has the APPEND flag set6219 // * out_fd has the APPEND flag set
6232 // Because of the "mmap(2)-like operation" possibility, we fall back to doing read/write6220 // Because of the "mmap(2)-like operation" possibility, we fall back to doing read/write
6233 // manually, the same as ENOSYS.6221 // manually.
6234 break :sf;6222 break :sf;
6235 },6223 },
6236 .AGAIN => return error.WouldBlock,6224 .AGAIN => return error.WouldBlock,
...@@ -6456,21 +6444,15 @@ pub const CopyFileRangeError = error{...@@ -6456,21 +6444,15 @@ pub const CopyFileRangeError = error{
6456/// `flags` has different meanings per operating system; refer to the respective man pages.6444/// `flags` has different meanings per operating system; refer to the respective man pages.
6457///6445///
6458/// These systems support in-kernel data copying:6446/// These systems support in-kernel data copying:
6459/// * Linux 4.5 (cross-filesystem 5.3)6447/// * Linux (cross-filesystem from version 5.3)
6460/// * FreeBSD 13.06448/// * FreeBSD 13.0
6461///6449///
6462/// Other systems fall back to calling `pread` / `pwrite`.6450/// Other systems fall back to calling `pread` / `pwrite`.
6463///6451///
6464/// Maximum offsets on Linux and FreeBSD are `maxInt(i64)`.6452/// Maximum offsets on Linux and FreeBSD are `maxInt(i64)`.
6465pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize {6453pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize {
6466 const global = struct {
6467 var has_copy_file_range = true;
6468 };
6469
6470 if ((comptime builtin.os.isAtLeast(.freebsd, .{ .major = 13, .minor = 0, .patch = 0 }) orelse false) or6454 if ((comptime builtin.os.isAtLeast(.freebsd, .{ .major = 13, .minor = 0, .patch = 0 }) orelse false) or
6471 ((comptime builtin.os.isAtLeast(.linux, .{ .major = 4, .minor = 5, .patch = 0 }) orelse false and6455 (comptime builtin.os.tag == .linux and std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 })))
6472 std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 })) and
6473 @atomicLoad(bool, &global.has_copy_file_range, .monotonic)))
6474 {6456 {
6475 var off_in_copy: i64 = @bitCast(off_in);6457 var off_in_copy: i64 = @bitCast(off_in);
6476 var off_out_copy: i64 = @bitCast(off_out);6458 var off_out_copy: i64 = @bitCast(off_out);
...@@ -6504,10 +6486,6 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len...@@ -6504,10 +6486,6 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len
6504 .PERM => return error.PermissionDenied,6486 .PERM => return error.PermissionDenied,
6505 .TXTBSY => return error.SwapFile,6487 .TXTBSY => return error.SwapFile,
6506 .XDEV => break, // support for cross-filesystem copy added in Linux 5.3, use fallback6488 .XDEV => break, // support for cross-filesystem copy added in Linux 5.3, use fallback
6507 .NOSYS => {
6508 @atomicStore(bool, &global.has_copy_file_range, false, .monotonic);
6509 break;
6510 },
6511 else => |err| return unexpectedErrno(err),6489 else => |err| return unexpectedErrno(err),
6512 }6490 }
6513 }6491 }
...@@ -6775,10 +6753,6 @@ pub const MemFdCreateError = error{...@@ -6775,10 +6753,6 @@ pub const MemFdCreateError = error{
6775 OutOfMemory,6753 OutOfMemory,
6776 /// Either the name provided exceeded `NAME_MAX`, or invalid flags were passed.6754 /// Either the name provided exceeded `NAME_MAX`, or invalid flags were passed.
6777 NameTooLong,6755 NameTooLong,
6778
6779 /// memfd_create is available in Linux 3.17 and later. This error is returned
6780 /// for older kernel versions.
6781 SystemOutdated,
6782} || UnexpectedError;6756} || UnexpectedError;
67836757
6784pub fn memfd_createZ(name: [*:0]const u8, flags: u32) MemFdCreateError!fd_t {6758pub fn memfd_createZ(name: [*:0]const u8, flags: u32) MemFdCreateError!fd_t {
...@@ -6795,7 +6769,6 @@ pub fn memfd_createZ(name: [*:0]const u8, flags: u32) MemFdCreateError!fd_t {...@@ -6795,7 +6769,6 @@ pub fn memfd_createZ(name: [*:0]const u8, flags: u32) MemFdCreateError!fd_t {
6795 .NFILE => return error.SystemFdQuotaExceeded,6769 .NFILE => return error.SystemFdQuotaExceeded,
6796 .MFILE => return error.ProcessFdQuotaExceeded,6770 .MFILE => return error.ProcessFdQuotaExceeded,
6797 .NOMEM => return error.OutOfMemory,6771 .NOMEM => return error.OutOfMemory,
6798 .NOSYS => return error.SystemOutdated,
6799 else => |err| return unexpectedErrno(err),6772 else => |err| return unexpectedErrno(err),
6800 }6773 }
6801 },6774 },
...@@ -6915,7 +6888,6 @@ pub fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) !fd_t {...@@ -6915,7 +6888,6 @@ pub fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) !fd_t {
6915 .NOMEM => return error.SystemResources,6888 .NOMEM => return error.SystemResources,
6916 .MFILE => return error.ProcessResources,6889 .MFILE => return error.ProcessResources,
6917 .NODEV => return error.InodeMountFail,6890 .NODEV => return error.InodeMountFail,
6918 .NOSYS => return error.SystemOutdated,
6919 else => |err| return unexpectedErrno(err),6891 else => |err| return unexpectedErrno(err),
6920 }6892 }
6921}6893}
lib/std/posix/test.zig+1-5
...@@ -580,11 +580,7 @@ test "memfd_create" {...@@ -580,11 +580,7 @@ test "memfd_create" {
580 else => return error.SkipZigTest,580 else => return error.SkipZigTest,
581 }581 }
582582
583 const fd = posix.memfd_create("test", 0) catch |err| switch (err) {583 const fd = try posix.memfd_create("test", 0);
584 // Related: https://github.com/ziglang/zig/issues/4019
585 error.SystemOutdated => return error.SkipZigTest,
586 else => |e| return e,
587 };
588 defer posix.close(fd);584 defer posix.close(fd);
589 try expect((try posix.write(fd, "test")) == 4);585 try expect((try posix.write(fd, "test")) == 4);
590 try posix.lseek_SET(fd, 0);586 try posix.lseek_SET(fd, 0);
lib/std/start.zig+1-1
...@@ -272,7 +272,7 @@ fn _start() callconv(.Naked) noreturn {...@@ -272,7 +272,7 @@ fn _start() callconv(.Naked) noreturn {
272 \\ bstrins.d $sp, $zero, 3, 0272 \\ bstrins.d $sp, $zero, 3, 0
273 \\ b %[posixCallMainAndExit]273 \\ b %[posixCallMainAndExit]
274 ,274 ,
275 .riscv64 =>275 .riscv32, .riscv64 =>
276 \\ li s0, 0276 \\ li s0, 0
277 \\ li ra, 0277 \\ li ra, 0
278 \\ mv a0, sp278 \\ mv a0, sp
lib/std/zig/target.zig+1-1
...@@ -56,7 +56,7 @@ pub const available_libcs = [_]ArchOsAbi{...@@ -56,7 +56,7 @@ pub const available_libcs = [_]ArchOsAbi{
56 .{ .arch = .powerpc, .os = .linux, .abi = .gnueabi },56 .{ .arch = .powerpc, .os = .linux, .abi = .gnueabi },
57 .{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf },57 .{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf },
58 .{ .arch = .powerpc, .os = .linux, .abi = .musl },58 .{ .arch = .powerpc, .os = .linux, .abi = .musl },
59 .{ .arch = .riscv32, .os = .linux, .abi = .gnuilp32, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 } },59 .{ .arch = .riscv32, .os = .linux, .abi = .gnuilp32, .glibc_min = .{ .major = 2, .minor = 33, .patch = 0 } },
60 .{ .arch = .riscv32, .os = .linux, .abi = .musl },60 .{ .arch = .riscv32, .os = .linux, .abi = .musl },
61 .{ .arch = .riscv64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 } },61 .{ .arch = .riscv64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 } },
62 .{ .arch = .riscv64, .os = .linux, .abi = .musl },62 .{ .arch = .riscv64, .os = .linux, .abi = .musl },
src/link/Elf.zig+1-1
...@@ -3150,7 +3150,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {...@@ -3150,7 +3150,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
3150 }3150 }
3151 }3151 }
31523152
3153 if (self.getTarget().cpu.arch == .riscv64 and self.isEffectivelyDynLib()) {3153 if (self.getTarget().cpu.arch.isRISCV() and self.isEffectivelyDynLib()) {
3154 self.global_pointer_index = try linker_defined.addGlobal("__global_pointer$", self);3154 self.global_pointer_index = try linker_defined.addGlobal("__global_pointer$", self);
3155 }3155 }
31563156
src/musl.zig+1
...@@ -301,6 +301,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: std.Progre...@@ -301,6 +301,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: std.Progre
301pub fn needsCrtiCrtn(target: std.Target) bool {301pub fn needsCrtiCrtn(target: std.Target) bool {
302 // zig fmt: off302 // zig fmt: off
303 return switch (target.cpu.arch) {303 return switch (target.cpu.arch) {
304 .riscv32,
304 .riscv64,305 .riscv64,
305 .wasm32, .wasm64 => return false,306 .wasm32, .wasm64 => return false,
306 else => true,307 else => true,
tools/gen_stubs.zig+7-2
...@@ -2,13 +2,14 @@...@@ -2,13 +2,14 @@
2//! ./gen_stubs /path/to/musl/build-all >libc.S2//! ./gen_stubs /path/to/musl/build-all >libc.S
3//!3//!
4//! The directory 'build-all' is expected to contain these subdirectories:4//! The directory 'build-all' is expected to contain these subdirectories:
5//! arm x86 mips mips64 powerpc powerpc64 riscv64 x86_645//! arm x86 mips mips64 powerpc powerpc64 riscv32 riscv64 x86_64
6//!6//!
7//! ...each with 'lib/libc.so' inside of them.7//! ...each with 'lib/libc.so' inside of them.
8//!8//!
9//! When building the resulting libc.S file, these defines are required:9//! When building the resulting libc.S file, these defines are required:
10//! * `-DPTR64`: when the architecture is 64-bit10//! * `-DPTR64`: when the architecture is 64-bit
11//! * One of the following, corresponding to the CPU architecture:11//! * One of the following, corresponding to the CPU architecture:
12//! - `-DARCH_riscv32`
12//! - `-DARCH_riscv64`13//! - `-DARCH_riscv64`
13//! - `-DARCH_mips`14//! - `-DARCH_mips`
14//! - `-DARCH_mips64`15//! - `-DARCH_mips64`
...@@ -68,7 +69,8 @@ const MultiSym = struct {...@@ -68,7 +69,8 @@ const MultiSym = struct {
68 }69 }
6970
70 fn is32Only(ms: MultiSym) bool {71 fn is32Only(ms: MultiSym) bool {
71 return ms.present[archIndex(.riscv64)] == false and72 return ms.present[archIndex(.riscv32)] == true and
73 ms.present[archIndex(.riscv64)] == false and
72 ms.present[archIndex(.mips)] == true and74 ms.present[archIndex(.mips)] == true and
73 ms.present[archIndex(.mips64)] == false and75 ms.present[archIndex(.mips64)] == false and
74 ms.present[archIndex(.x86)] == true and76 ms.present[archIndex(.x86)] == true and
...@@ -110,6 +112,7 @@ const MultiSym = struct {...@@ -110,6 +112,7 @@ const MultiSym = struct {
110112
111 fn isPtrSize(ms: MultiSym) bool {113 fn isPtrSize(ms: MultiSym) bool {
112 const map = .{114 const map = .{
115 .{ .riscv32, 4 },
113 .{ .riscv64, 8 },116 .{ .riscv64, 8 },
114 .{ .mips, 4 },117 .{ .mips, 4 },
115 .{ .mips64, 8 },118 .{ .mips64, 8 },
...@@ -132,6 +135,7 @@ const MultiSym = struct {...@@ -132,6 +135,7 @@ const MultiSym = struct {
132135
133 fn isPtr2Size(ms: MultiSym) bool {136 fn isPtr2Size(ms: MultiSym) bool {
134 const map = .{137 const map = .{
138 .{ .riscv32, 8 },
135 .{ .riscv64, 16 },139 .{ .riscv64, 16 },
136 .{ .mips, 8 },140 .{ .mips, 8 },
137 .{ .mips64, 16 },141 .{ .mips64, 16 },
...@@ -154,6 +158,7 @@ const MultiSym = struct {...@@ -154,6 +158,7 @@ const MultiSym = struct {
154158
155 fn isWeak64(ms: MultiSym) bool {159 fn isWeak64(ms: MultiSym) bool {
156 const map = .{160 const map = .{
161 .{ .riscv32, 1 },
157 .{ .riscv64, 2 },162 .{ .riscv64, 2 },
158 .{ .mips, 1 },163 .{ .mips, 1 },
159 .{ .mips64, 2 },164 .{ .mips64, 2 },
tools/generate_linux_syscalls.zig+112-48
...@@ -10,7 +10,12 @@ const zig = std.zig;...@@ -10,7 +10,12 @@ const zig = std.zig;
10const fs = std.fs;10const fs = std.fs;
1111
12const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{12const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{
13 // Remove underscore prefix.
14 .{ "_llseek", "llseek" },
15 .{ "_newselect", "newselect" },
16 .{ "_sysctl", "sysctl" },
13 // Most 64-bit archs.17 // Most 64-bit archs.
18 .{ "newfstat", "fstat64" },
14 .{ "newfstatat", "fstatat64" },19 .{ "newfstatat", "fstatat64" },
15 // POWER.20 // POWER.
16 .{ "sync_file_range2", "sync_file_range" },21 .{ "sync_file_range2", "sync_file_range" },
...@@ -19,6 +24,24 @@ const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{...@@ -19,6 +24,24 @@ const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{
19 .{ "arm_fadvise64_64", "fadvise64_64" },24 .{ "arm_fadvise64_64", "fadvise64_64" },
20});25});
2126
27// Only for newer architectures where we use the C preprocessor.
28const stdlib_renames_new = std.StaticStringMap([]const u8).initComptime(.{
29 .{ "newuname", "uname" },
30 .{ "umount", "umount2" },
31});
32
33// We use this to deal with the fact that multiple syscalls can be mapped to sys_ni_syscall.
34// Thankfully it's only 2 well-known syscalls in newer kernel ports at the moment.
35fn getOverridenNameNew(value: []const u8) ?[]const u8 {
36 if (mem.eql(u8, value, "18")) {
37 return "sys_lookup_dcookie";
38 } else if (mem.eql(u8, value, "42")) {
39 return "sys_nfsservctl";
40 } else {
41 return null;
42 }
43}
44
22pub fn main() !void {45pub fn main() !void {
23 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);46 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
24 defer arena.deinit();47 defer arena.deinit();
...@@ -60,8 +83,9 @@ pub fn main() !void {...@@ -60,8 +83,9 @@ pub fn main() !void {
60 // abi is always i38683 // abi is always i386
61 _ = fields.next() orelse return error.Incomplete;84 _ = fields.next() orelse return error.Incomplete;
62 const name = fields.next() orelse return error.Incomplete;85 const name = fields.next() orelse return error.Incomplete;
86 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
6387
64 try writer.print(" {p} = {s},\n", .{ zig.fmtId(name), number });88 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
65 }89 }
6690
67 try writer.writeAll("};\n\n");91 try writer.writeAll("};\n\n");
...@@ -80,8 +104,8 @@ pub fn main() !void {...@@ -80,8 +104,8 @@ pub fn main() !void {
80 // The x32 abi syscalls are always at the end.104 // The x32 abi syscalls are always at the end.
81 if (mem.eql(u8, abi, "x32")) break;105 if (mem.eql(u8, abi, "x32")) break;
82 const name = fields.next() orelse return error.Incomplete;106 const name = fields.next() orelse return error.Incomplete;
83
84 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;107 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
108
85 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });109 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
86 }110 }
87111
...@@ -105,8 +129,8 @@ pub fn main() !void {...@@ -105,8 +129,8 @@ pub fn main() !void {
105 const abi = fields.next() orelse return error.Incomplete;129 const abi = fields.next() orelse return error.Incomplete;
106 if (mem.eql(u8, abi, "oabi")) continue;130 if (mem.eql(u8, abi, "oabi")) continue;
107 const name = fields.next() orelse return error.Incomplete;131 const name = fields.next() orelse return error.Incomplete;
108
109 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;132 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
133
110 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });134 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
111 }135 }
112136
...@@ -136,8 +160,9 @@ pub fn main() !void {...@@ -136,8 +160,9 @@ pub fn main() !void {
136 const abi = fields.next() orelse return error.Incomplete;160 const abi = fields.next() orelse return error.Incomplete;
137 if (mem.eql(u8, abi, "32")) continue;161 if (mem.eql(u8, abi, "32")) continue;
138 const name = fields.next() orelse return error.Incomplete;162 const name = fields.next() orelse return error.Incomplete;
163 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
139164
140 try writer.print(" {p} = {s},\n", .{ zig.fmtId(name), number });165 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
141 }166 }
142167
143 try writer.writeAll("};\n\n");168 try writer.writeAll("};\n\n");
...@@ -161,8 +186,9 @@ pub fn main() !void {...@@ -161,8 +186,9 @@ pub fn main() !void {
161 _ = fields.next() orelse return error.Incomplete;186 _ = fields.next() orelse return error.Incomplete;
162 const name = fields.next() orelse return error.Incomplete;187 const name = fields.next() orelse return error.Incomplete;
163 if (mem.startsWith(u8, name, "unused")) continue;188 if (mem.startsWith(u8, name, "unused")) continue;
189 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
164190
165 try writer.print(" {p} = Linux + {s},\n", .{ zig.fmtId(name), number });191 try writer.print(" {p} = Linux + {s},\n", .{ zig.fmtId(fixed_name), number });
166 }192 }
167193
168 try writer.writeAll("};\n\n");194 try writer.writeAll("};\n\n");
...@@ -232,11 +258,6 @@ pub fn main() !void {...@@ -232,11 +258,6 @@ pub fn main() !void {
232 // Newer architectures (starting with aarch64 c. 2012) now use the same C258 // Newer architectures (starting with aarch64 c. 2012) now use the same C
233 // header file for their syscall numbers. Arch-specific headers are used to259 // header file for their syscall numbers. Arch-specific headers are used to
234 // define pre-proc. vars that add additional (usually obsolete) syscalls.260 // define pre-proc. vars that add additional (usually obsolete) syscalls.
235 //
236 // TODO:
237 // - It would be better to use libclang/translate-c directly to extract the definitions.
238 // - The `-dD` option only does minimal pre-processing and doesn't resolve addition,
239 // so arch specific syscalls are dealt with manually.
240 {261 {
241 try writer.writeAll("pub const Arm64 = enum(usize) {\n");262 try writer.writeAll("pub const Arm64 = enum(usize) {\n");
242263
...@@ -254,6 +275,8 @@ pub fn main() !void {...@@ -254,6 +275,8 @@ pub fn main() !void {
254 // Using -I=[dir] includes the zig linux headers, which we don't want.275 // Using -I=[dir] includes the zig linux headers, which we don't want.
255 "-Iinclude",276 "-Iinclude",
256 "-Iinclude/uapi",277 "-Iinclude/uapi",
278 // Output the syscall in a format we can easily recognize.
279 "-D __SYSCALL(nr, nm)=zigsyscall nm nr",
257 "arch/arm64/include/uapi/asm/unistd.h",280 "arch/arm64/include/uapi/asm/unistd.h",
258 };281 };
259282
...@@ -277,32 +300,79 @@ pub fn main() !void {...@@ -277,32 +300,79 @@ pub fn main() !void {
277 };300 };
278301
279 var lines = mem.tokenizeScalar(u8, defines, '\n');302 var lines = mem.tokenizeScalar(u8, defines, '\n');
280 loop: while (lines.next()) |line| {303 while (lines.next()) |line| {
281 var fields = mem.tokenizeAny(u8, line, " \t");304 var fields = mem.tokenizeAny(u8, line, " ");
282 const cmd = fields.next() orelse return error.Incomplete;305 const prefix = fields.next() orelse return error.Incomplete;
283 if (!mem.eql(u8, cmd, "#define")) continue;
284 const define = fields.next() orelse return error.Incomplete;
285 const number = fields.next() orelse continue;
286306
287 if (!std.ascii.isDigit(number[0])) continue;307 if (!mem.eql(u8, prefix, "zigsyscall")) continue;
288 if (!mem.startsWith(u8, define, "__NR")) continue;
289 const name = mem.trimLeft(u8, mem.trimLeft(u8, define, "__NR3264_"), "__NR_");
290 if (mem.eql(u8, name, "arch_specific_syscall")) continue;
291 if (mem.eql(u8, name, "syscalls")) break :loop;
292308
293 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;309 const sys_name = fields.next() orelse return error.Incomplete;
294 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });310 const value = fields.rest();
311 const name = (getOverridenNameNew(value) orelse sys_name)["sys_".len..];
312 const fixed_name = if (stdlib_renames_new.get(name)) |f| f else if (stdlib_renames.get(name)) |f| f else name;
313
314 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), value });
295 }315 }
296316
297 try writer.writeAll("};\n\n");317 try writer.writeAll("};\n\n");
298 }318 }
299 {319 {
300 try writer.writeAll(320 try writer.writeAll("pub const RiscV32 = enum(usize) {\n");
301 \\pub const RiscV64 = enum(usize) {321
302 \\ pub const arch_specific_syscall = 244;322 const child_args = [_][]const u8{
303 \\323 zig_exe,
304 \\324 "cc",
305 );325 "-target",
326 "riscv32-linux-gnuilp32",
327 "-E",
328 "-dD",
329 "-P",
330 "-nostdinc",
331 "-Iinclude",
332 "-Iinclude/uapi",
333 "-Iarch/riscv/include/uapi",
334 "-D __SYSCALL(nr, nm)=zigsyscall nm nr",
335 "arch/riscv/include/uapi/asm/unistd.h",
336 };
337
338 const child_result = try std.process.Child.run(.{
339 .allocator = allocator,
340 .argv = &child_args,
341 .cwd = linux_path,
342 .cwd_dir = linux_dir,
343 });
344 if (child_result.stderr.len > 0) std.debug.print("{s}\n", .{child_result.stderr});
345
346 const defines = switch (child_result.term) {
347 .Exited => |code| if (code == 0) child_result.stdout else {
348 std.debug.print("zig cc exited with code {d}\n", .{code});
349 std.process.exit(1);
350 },
351 else => {
352 std.debug.print("zig cc crashed\n", .{});
353 std.process.exit(1);
354 },
355 };
356
357 var lines = mem.tokenizeScalar(u8, defines, '\n');
358 while (lines.next()) |line| {
359 var fields = mem.tokenizeAny(u8, line, " ");
360 const prefix = fields.next() orelse return error.Incomplete;
361
362 if (!mem.eql(u8, prefix, "zigsyscall")) continue;
363
364 const sys_name = fields.next() orelse return error.Incomplete;
365 const value = fields.rest();
366 const name = (getOverridenNameNew(value) orelse sys_name)["sys_".len..];
367 const fixed_name = if (stdlib_renames_new.get(name)) |f| f else if (stdlib_renames.get(name)) |f| f else name;
368
369 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), value });
370 }
371
372 try writer.writeAll("};\n\n");
373 }
374 {
375 try writer.writeAll("pub const RiscV64 = enum(usize) {\n");
306376
307 const child_args = [_][]const u8{377 const child_args = [_][]const u8{
308 zig_exe,378 zig_exe,
...@@ -315,6 +385,8 @@ pub fn main() !void {...@@ -315,6 +385,8 @@ pub fn main() !void {
315 "-nostdinc",385 "-nostdinc",
316 "-Iinclude",386 "-Iinclude",
317 "-Iinclude/uapi",387 "-Iinclude/uapi",
388 "-Iarch/riscv/include/uapi",
389 "-D __SYSCALL(nr, nm)=zigsyscall nm nr",
318 "arch/riscv/include/uapi/asm/unistd.h",390 "arch/riscv/include/uapi/asm/unistd.h",
319 };391 };
320392
...@@ -338,29 +410,21 @@ pub fn main() !void {...@@ -338,29 +410,21 @@ pub fn main() !void {
338 };410 };
339411
340 var lines = mem.tokenizeScalar(u8, defines, '\n');412 var lines = mem.tokenizeScalar(u8, defines, '\n');
341 loop: while (lines.next()) |line| {413 while (lines.next()) |line| {
342 var fields = mem.tokenizeAny(u8, line, " \t");414 var fields = mem.tokenizeAny(u8, line, " ");
343 const cmd = fields.next() orelse return error.Incomplete;415 const prefix = fields.next() orelse return error.Incomplete;
344 if (!mem.eql(u8, cmd, "#define")) continue;
345 const define = fields.next() orelse return error.Incomplete;
346 const number = fields.next() orelse continue;
347416
348 if (!std.ascii.isDigit(number[0])) continue;417 if (!mem.eql(u8, prefix, "zigsyscall")) continue;
349 if (!mem.startsWith(u8, define, "__NR")) continue;
350 const name = mem.trimLeft(u8, mem.trimLeft(u8, define, "__NR3264_"), "__NR_");
351 if (mem.eql(u8, name, "arch_specific_syscall")) continue;
352 if (mem.eql(u8, name, "syscalls")) break :loop;
353418
354 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;419 const sys_name = fields.next() orelse return error.Incomplete;
355 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });420 const value = fields.rest();
421 const name = (getOverridenNameNew(value) orelse sys_name)["sys_".len..];
422 const fixed_name = if (stdlib_renames_new.get(name)) |f| f else if (stdlib_renames.get(name)) |f| f else name;
423
424 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), value });
356 }425 }
357426
358 try writer.writeAll(427 try writer.writeAll("};\n\n");
359 \\
360 \\ riscv_flush_icache = arch_specific_syscall + 15,
361 \\};
362 \\
363 );
364 }428 }
365 {429 {
366 try writer.writeAll(430 try writer.writeAll(