aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2024-07-29 16:13:35 -0700
committerGitHub <noreply@github.com>2024-07-29 16:13:35 -0700
commit38e0f049c531e83ec2eec80d50b624e6c3b8c486 (patch)
tree76fb3cf957c9963a720e1845667666b0937e4619 /lib
parent73a444766e4d1406c194935b54e8167e747b165f (diff)
parent13945548fcd4fe3aab0879b670db1fe8131d8b0e (diff)
downloadzig-38e0f049c531e83ec2eec80d50b624e6c3b8c486.tar.gz
zig-38e0f049c531e83ec2eec80d50b624e6c3b8c486.zip
Merge pull request #20389 from alexrp/riscv32
Some `riscv32-linux` porting work
Diffstat (limited to 'lib')
-rw-r--r--lib/c.zig34
-rw-r--r--lib/std/Target.zig11
-rw-r--r--lib/std/Thread.zig49
-rw-r--r--lib/std/debug.zig3
-rw-r--r--lib/std/fs/Dir.zig29
-rw-r--r--lib/std/fs/File.zig106
-rw-r--r--lib/std/os/linux.zig98
-rw-r--r--lib/std/os/linux/riscv32.zig197
-rw-r--r--lib/std/os/linux/riscv64.zig10
-rw-r--r--lib/std/os/linux/start_pie.zig4
-rw-r--r--lib/std/os/linux/syscalls.zig370
-rw-r--r--lib/std/os/linux/test.zig4
-rw-r--r--lib/std/os/linux/tls.zig2
-rw-r--r--lib/std/posix.zig36
-rw-r--r--lib/std/posix/test.zig6
-rw-r--r--lib/std/start.zig2
-rw-r--r--lib/std/zig/target.zig2
17 files changed, 792 insertions, 171 deletions
diff --git a/lib/c.zig b/lib/c.zig
index 56ea977bfa..3c153d2f34 100644
--- a/lib/c.zig
+++ b/lib/c.zig
@@ -319,6 +319,40 @@ fn clone() callconv(.Naked) void {
\\3: bx r5
);
},
+ .riscv32 => {
+ // __clone(func, stack, flags, arg, ptid, tls, ctid)
+ // a0, a1, a2, a3, a4, a5, a6
+
+ // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
+ // a7 a0, a1, a2, a3, a4
+ asm volatile (
+ \\ # Save func and arg to stack
+ \\ addi a1, a1, -8
+ \\ sw a0, 0(a1)
+ \\ sw a3, 4(a1)
+ \\
+ \\ # Call SYS_clone
+ \\ mv a0, a2
+ \\ mv a2, a4
+ \\ mv a3, a5
+ \\ mv a4, a6
+ \\ li a7, 220 # SYS_clone
+ \\ ecall
+ \\
+ \\ beqz a0, 1f
+ \\ # Parent
+ \\ ret
+ \\
+ \\ # Child
+ \\1: lw a1, 0(sp)
+ \\ lw a0, 4(sp)
+ \\ jalr a1
+ \\
+ \\ # Exit
+ \\ li a7, 93 # SYS_exit
+ \\ ecall
+ );
+ },
.riscv64 => {
// __clone(func, stack, flags, arg, ptid, tls, ctid)
// a0, a1, a2, a3, a4, a5, a6
diff --git a/lib/std/Target.zig b/lib/std/Target.zig
index 29466ce837..a69038fae4 100644
--- a/lib/std/Target.zig
+++ b/lib/std/Target.zig
@@ -720,7 +720,16 @@ pub const Abi = enum {
pub inline fn isGnu(abi: Abi) bool {
return switch (abi) {
- .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true,
+ .gnu,
+ .gnuabin32,
+ .gnuabi64,
+ .gnueabi,
+ .gnueabihf,
+ .gnuf32,
+ .gnusf,
+ .gnux32,
+ .gnuilp32,
+ => true,
else => false,
};
}
diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig
index e19f473e44..c9c867090d 100644
--- a/lib/std/Thread.zig
+++ b/lib/std/Thread.zig
@@ -1082,11 +1082,11 @@ const LinuxThreadImpl = struct {
fn freeAndExit(self: *ThreadCompletion) noreturn {
switch (target.cpu.arch) {
.x86 => asm volatile (
- \\ movl $91, %%eax
+ \\ movl $91, %%eax # SYS_munmap
\\ movl %[ptr], %%ebx
\\ movl %[len], %%ecx
\\ int $128
- \\ movl $1, %%eax
+ \\ movl $1, %%eax # SYS_exit
\\ movl $0, %%ebx
\\ int $128
:
@@ -1095,9 +1095,9 @@ const LinuxThreadImpl = struct {
: "memory"
),
.x86_64 => asm volatile (
- \\ movq $11, %%rax
+ \\ movq $11, %%rax # SYS_munmap
\\ syscall
- \\ movq $60, %%rax
+ \\ movq $60, %%rax # SYS_exit
\\ movq $1, %%rdi
\\ syscall
:
@@ -1105,11 +1105,11 @@ const LinuxThreadImpl = struct {
[len] "{rsi}" (self.mapped.len),
),
.arm, .armeb, .thumb, .thumbeb => asm volatile (
- \\ mov r7, #91
+ \\ mov r7, #91 // SYS_munmap
\\ mov r0, %[ptr]
\\ mov r1, %[len]
\\ svc 0
- \\ mov r7, #1
+ \\ mov r7, #1 // SYS_exit
\\ mov r0, #0
\\ svc 0
:
@@ -1118,11 +1118,11 @@ const LinuxThreadImpl = struct {
: "memory"
),
.aarch64, .aarch64_be => asm volatile (
- \\ mov x8, #215
+ \\ mov x8, #215 // SYS_munmap
\\ mov x0, %[ptr]
\\ mov x1, %[len]
\\ svc 0
- \\ mov x8, #93
+ \\ mov x8, #93 // SYS_exit
\\ mov x0, #0
\\ svc 0
:
@@ -1132,11 +1132,11 @@ const LinuxThreadImpl = struct {
),
.mips, .mipsel => asm volatile (
\\ move $sp, $25
- \\ li $2, 4091
+ \\ li $2, 4091 # SYS_munmap
\\ move $4, %[ptr]
\\ move $5, %[len]
\\ syscall
- \\ li $2, 4001
+ \\ li $2, 4001 # SYS_exit
\\ li $4, 0
\\ syscall
:
@@ -1145,11 +1145,11 @@ const LinuxThreadImpl = struct {
: "memory"
),
.mips64, .mips64el => asm volatile (
- \\ li $2, 4091
+ \\ li $2, 4091 # SYS_munmap
\\ move $4, %[ptr]
\\ move $5, %[len]
\\ syscall
- \\ li $2, 4001
+ \\ li $2, 4001 # SYS_exit
\\ li $4, 0
\\ syscall
:
@@ -1158,11 +1158,11 @@ const LinuxThreadImpl = struct {
: "memory"
),
.powerpc, .powerpcle, .powerpc64, .powerpc64le => asm volatile (
- \\ li 0, 91
+ \\ li 0, 91 # SYS_munmap
\\ mr %[ptr], 3
\\ mr %[len], 4
\\ sc
- \\ li 0, 1
+ \\ li 0, 1 # SYS_exit
\\ li 3, 0
\\ sc
\\ blr
@@ -1171,12 +1171,25 @@ const LinuxThreadImpl = struct {
[len] "r" (self.mapped.len),
: "memory"
),
+ .riscv32 => asm volatile (
+ \\ li a7, 215 # SYS_munmap
+ \\ mv a0, %[ptr]
+ \\ mv a1, %[len]
+ \\ ecall
+ \\ li a7, 93 # SYS_exit
+ \\ mv a0, zero
+ \\ ecall
+ :
+ : [ptr] "r" (@intFromPtr(self.mapped.ptr)),
+ [len] "r" (self.mapped.len),
+ : "memory"
+ ),
.riscv64 => asm volatile (
- \\ li a7, 215
+ \\ li a7, 215 # SYS_munmap
\\ mv a0, %[ptr]
\\ mv a1, %[len]
\\ ecall
- \\ li a7, 93
+ \\ li a7, 93 # SYS_exit
\\ mv a0, zero
\\ ecall
:
@@ -1196,14 +1209,14 @@ const LinuxThreadImpl = struct {
\\ ba 1b
\\ restore
\\ 2:
- \\ mov 73, %%g1
+ \\ mov 73, %%g1 # SYS_munmap
\\ mov %[ptr], %%o0
\\ mov %[len], %%o1
\\ # Flush register window contents to prevent background
\\ # memory access before unmapping the stack.
\\ flushw
\\ t 0x6d
- \\ mov 1, %%g1
+ \\ mov 1, %%g1 # SYS_exit
\\ mov 1, %%o0
\\ t 0x6d
:
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index 31321d62fd..be8b030769 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -747,7 +747,8 @@ pub const StackIterator = struct {
.SUCCESS => return bytes_read == buf.len,
.FAULT => return false,
.INVAL, .PERM, .SRCH => unreachable, // own pid is always valid
- .NOMEM, .NOSYS => {},
+ .NOMEM => {},
+ .NOSYS => {}, // QEMU is known not to implement this syscall.
else => unreachable, // unexpected
}
var path_buf: [
diff --git a/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig
index 2743f3ed7d..34967301e1 100644
--- a/lib/std/fs/Dir.zig
+++ b/lib/std/fs/Dir.zig
@@ -334,7 +334,6 @@ pub const Iterator = switch (native_os) {
first_iter: bool,
const Self = @This();
- const linux = std.os.linux;
pub const Error = IteratorError;
@@ -2690,8 +2689,33 @@ pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat {
const st = try std.os.fstatat_wasi(self.fd, sub_path, .{ .SYMLINK_FOLLOW = true });
return Stat.fromWasi(st);
}
+ if (native_os == .linux) {
+ const sub_path_c = try posix.toPosixPath(sub_path);
+ var stx = std.mem.zeroes(linux.Statx);
+
+ const rc = linux.statx(
+ self.fd,
+ &sub_path_c,
+ linux.AT.NO_AUTOMOUNT,
+ linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME,
+ &stx,
+ );
+
+ return switch (linux.E.init(rc)) {
+ .SUCCESS => Stat.fromLinux(stx),
+ .ACCES => error.AccessDenied,
+ .BADF => unreachable,
+ .FAULT => unreachable,
+ .INVAL => unreachable,
+ .LOOP => error.SymLinkLoop,
+ .NAMETOOLONG => unreachable, // Handled by posix.toPosixPath() above.
+ .NOENT, .NOTDIR => error.FileNotFound,
+ .NOMEM => error.SystemResources,
+ else => |err| posix.unexpectedErrno(err),
+ };
+ }
const st = try posix.fstatat(self.fd, sub_path, 0);
- return Stat.fromSystem(st);
+ return Stat.fromPosix(st);
}
pub const ChmodError = File.ChmodError;
@@ -2751,6 +2775,7 @@ const path = fs.path;
const fs = std.fs;
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
+const linux = std.os.linux;
const windows = std.os.windows;
const native_os = builtin.os.tag;
const have_flock = @TypeOf(posix.system.flock) != void;
diff --git a/lib/std/fs/File.zig b/lib/std/fs/File.zig
index de113b2aad..36e7999bf7 100644
--- a/lib/std/fs/File.zig
+++ b/lib/std/fs/File.zig
@@ -342,7 +342,7 @@ pub fn seekTo(self: File, offset: u64) SeekError!void {
return posix.lseek_SET(self.handle, offset);
}
-pub const GetSeekPosError = posix.SeekError || posix.FStatError;
+pub const GetSeekPosError = posix.SeekError || StatError;
/// TODO: integrate with async I/O
pub fn getPos(self: File) GetSeekPosError!u64 {
@@ -357,7 +357,7 @@ pub fn getEndPos(self: File) GetSeekPosError!u64 {
return (try self.stat()).size;
}
-pub const ModeError = posix.FStatError;
+pub const ModeError = StatError;
/// TODO: integrate with async I/O
pub fn mode(self: File) ModeError!Mode {
@@ -392,7 +392,7 @@ pub const Stat = struct {
/// Last status/metadata change time in nanoseconds, relative to UTC 1970-01-01.
ctime: i128,
- pub fn fromSystem(st: posix.Stat) Stat {
+ pub fn fromPosix(st: posix.Stat) Stat {
const atime = st.atime();
const mtime = st.mtime();
const ctime = st.ctime();
@@ -426,6 +426,31 @@ pub const Stat = struct {
};
}
+ pub fn fromLinux(stx: linux.Statx) Stat {
+ const atime = stx.atime;
+ const mtime = stx.mtime;
+ const ctime = stx.ctime;
+
+ return .{
+ .inode = stx.ino,
+ .size = stx.size,
+ .mode = stx.mode,
+ .kind = switch (stx.mode & linux.S.IFMT) {
+ linux.S.IFDIR => .directory,
+ linux.S.IFCHR => .character_device,
+ linux.S.IFBLK => .block_device,
+ linux.S.IFREG => .file,
+ linux.S.IFIFO => .named_pipe,
+ linux.S.IFLNK => .sym_link,
+ linux.S.IFSOCK => .unix_domain_socket,
+ else => .unknown,
+ },
+ .atime = @as(i128, atime.sec) * std.time.ns_per_s + atime.nsec,
+ .mtime = @as(i128, mtime.sec) * std.time.ns_per_s + mtime.nsec,
+ .ctime = @as(i128, ctime.sec) * std.time.ns_per_s + ctime.nsec,
+ };
+ }
+
pub fn fromWasi(st: std.os.wasi.filestat_t) Stat {
return .{
.inode = st.ino,
@@ -502,8 +527,34 @@ pub fn stat(self: File) StatError!Stat {
return Stat.fromWasi(st);
}
+ if (builtin.os.tag == .linux) {
+ var stx = std.mem.zeroes(linux.Statx);
+
+ const rc = linux.statx(
+ self.handle,
+ "",
+ linux.AT.EMPTY_PATH,
+ linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME,
+ &stx,
+ );
+
+ return switch (linux.E.init(rc)) {
+ .SUCCESS => Stat.fromLinux(stx),
+ .ACCES => unreachable,
+ .BADF => unreachable,
+ .FAULT => unreachable,
+ .INVAL => unreachable,
+ .LOOP => unreachable,
+ .NAMETOOLONG => unreachable,
+ .NOENT => unreachable,
+ .NOMEM => error.SystemResources,
+ .NOTDIR => unreachable,
+ else => |err| posix.unexpectedErrno(err),
+ };
+ }
+
const st = try posix.fstat(self.handle);
- return Stat.fromSystem(st);
+ return Stat.fromPosix(st);
}
pub const ChmodError = posix.FChmodError;
@@ -731,7 +782,7 @@ pub const Metadata = struct {
/// Returns the time the file was created in nanoseconds since UTC 1970-01-01
/// On Windows, this cannot return null
- /// On Linux, this returns null if the filesystem does not support creation times, or if the kernel is older than 4.11
+ /// On Linux, this returns null if the filesystem does not support creation times
/// On Unices, this returns null if the filesystem or OS does not support creation times
/// 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
pub fn created(self: Self) ?i128 {
@@ -822,7 +873,6 @@ pub const MetadataUnix = struct {
};
/// `MetadataUnix`, but using Linux's `statx` syscall.
-/// On Linux versions below 4.11, `statx` will be filled with data from stat.
pub const MetadataLinux = struct {
statx: std.os.linux.Statx,
@@ -1010,34 +1060,29 @@ pub fn metadata(self: File) MetadataError!Metadata {
};
},
.linux => blk: {
- const l = std.os.linux;
- var stx = std.mem.zeroes(l.Statx);
- const rcx = l.statx(self.handle, "\x00", l.AT.EMPTY_PATH, l.STATX_TYPE |
- l.STATX_MODE | l.STATX_ATIME | l.STATX_MTIME | l.STATX_BTIME, &stx);
-
- switch (posix.errno(rcx)) {
+ var stx = std.mem.zeroes(linux.Statx);
+
+ // We are gathering information for Metadata, which is meant to contain all the
+ // native OS information about the file, so use all known flags.
+ const rc = linux.statx(
+ self.handle,
+ "",
+ linux.AT.EMPTY_PATH,
+ linux.STATX_BASIC_STATS | linux.STATX_BTIME,
+ &stx,
+ );
+
+ switch (posix.errno(rc)) {
.SUCCESS => {},
- // NOSYS happens when `statx` is unsupported, which is the case on kernel versions before 4.11
- // Here, we call `fstat` and fill `stx` with the data we need
- .NOSYS => {
- const st = try posix.fstat(self.handle);
-
- stx.mode = @as(u16, @intCast(st.mode));
-
- // Hacky conversion from timespec to statx_timestamp
- stx.atime = std.mem.zeroes(l.statx_timestamp);
- stx.atime.sec = st.atim.sec;
- stx.atime.nsec = @as(u32, @intCast(st.atim.nsec)); // Guaranteed to succeed (nsec is always below 10^9)
-
- stx.mtime = std.mem.zeroes(l.statx_timestamp);
- stx.mtime.sec = st.mtim.sec;
- stx.mtime.nsec = @as(u32, @intCast(st.mtim.nsec));
-
- stx.mask = l.STATX_BASIC_STATS | l.STATX_MTIME;
- },
+ .ACCES => unreachable,
.BADF => unreachable,
.FAULT => unreachable,
+ .INVAL => unreachable,
+ .LOOP => unreachable,
+ .NAMETOOLONG => unreachable,
+ .NOENT => unreachable,
.NOMEM => return error.SystemResources,
+ .NOTDIR => unreachable,
else => |err| return posix.unexpectedErrno(err),
}
@@ -1731,6 +1776,7 @@ const posix = std.posix;
const io = std.io;
const math = std.math;
const assert = std.debug.assert;
+const linux = std.os.linux;
const windows = std.os.windows;
const Os = std.builtin.Os;
const maxInt = std.math.maxInt;
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index 12083bd5da..4f3db110b2 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -39,6 +39,7 @@ const arch_bits = switch (native_arch) {
.x86_64 => @import("linux/x86_64.zig"),
.aarch64, .aarch64_be => @import("linux/arm64.zig"),
.arm, .armeb, .thumb, .thumbeb => @import("linux/arm-eabi.zig"),
+ .riscv32 => @import("linux/riscv32.zig"),
.riscv64 => @import("linux/riscv64.zig"),
.sparc64 => @import("linux/sparc64.zig"),
.mips, .mipsel => @import("linux/mips.zig"),
@@ -104,6 +105,7 @@ pub const SYS = switch (@import("builtin").cpu.arch) {
.x86_64 => syscalls.X64,
.aarch64, .aarch64_be => syscalls.Arm64,
.arm, .armeb, .thumb, .thumbeb => syscalls.Arm,
+ .riscv32 => syscalls.RiscV32,
.riscv64 => syscalls.RiscV64,
.sparc64 => syscalls.Sparc64,
.mips, .mipsel => syscalls.Mips,
@@ -163,7 +165,7 @@ pub const MAP = switch (native_arch) {
UNINITIALIZED: bool = false,
_: u5 = 0,
},
- .riscv64 => packed struct(u32) {
+ .riscv32, .riscv64 => packed struct(u32) {
TYPE: MAP_TYPE,
FIXED: bool = false,
ANONYMOUS: bool = false,
@@ -268,7 +270,7 @@ pub const O = switch (native_arch) {
TMPFILE: bool = false,
_: u9 = 0,
},
- .x86, .riscv64 => packed struct(u32) {
+ .x86, .riscv32, .riscv64 => packed struct(u32) {
ACCMODE: ACCMODE = .RDONLY,
_2: u4 = 0,
CREAT: bool = false,
@@ -474,7 +476,7 @@ pub fn dup2(old: i32, new: i32) usize {
} else {
if (old == new) {
if (std.debug.runtime_safety) {
- const rc = syscall2(.fcntl, @as(usize, @bitCast(@as(isize, old))), F.GETFD);
+ const rc = fcntl(F.GETFD, @as(fd_t, old), 0);
if (@as(isize, @bitCast(rc)) < 0) return rc;
}
return @as(usize, @intCast(old));
@@ -1211,7 +1213,7 @@ pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize {
// NOTE: The offset parameter splitting is independent from the target
// endianness.
return syscall5(
- ._llseek,
+ .llseek,
@as(usize, @bitCast(@as(isize, fd))),
@as(usize, @truncate(offset >> 32)),
@as(usize, @truncate(offset)),
@@ -1370,7 +1372,11 @@ pub fn waitid(id_type: P, id: i32, infop: *siginfo_t, flags: u32) usize {
}
pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) usize {
- return syscall3(.fcntl, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg);
+ if (@hasField(SYS, "fcntl64")) {
+ return syscall3(.fcntl64, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg);
+ } else {
+ return syscall3(.fcntl, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg);
+ }
}
pub 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
}
pub fn fstat(fd: i32, stat_buf: *Stat) usize {
- if (@hasField(SYS, "fstat64")) {
+ if (native_arch == .riscv32) {
+ // riscv32 has made the interesting decision to not implement some of
+ // the older stat syscalls, including this one.
+ @compileError("No fstat syscall on this architecture.");
+ } else if (@hasField(SYS, "fstat64")) {
return syscall2(.fstat64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf));
} else {
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 {
}
pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize {
- if (@hasField(SYS, "stat64")) {
+ if (native_arch == .riscv32) {
+ // riscv32 has made the interesting decision to not implement some of
+ // the older stat syscalls, including this one.
+ @compileError("No stat syscall on this architecture.");
+ } else if (@hasField(SYS, "stat64")) {
return syscall2(.stat64, @intFromPtr(pathname), @intFromPtr(statbuf));
} else {
return syscall2(.stat, @intFromPtr(pathname), @intFromPtr(statbuf));
@@ -1852,7 +1866,11 @@ pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize {
}
pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {
- if (@hasField(SYS, "lstat64")) {
+ if (native_arch == .riscv32) {
+ // riscv32 has made the interesting decision to not implement some of
+ // the older stat syscalls, including this one.
+ @compileError("No lstat syscall on this architecture.");
+ } else if (@hasField(SYS, "lstat64")) {
return syscall2(.lstat64, @intFromPtr(pathname), @intFromPtr(statbuf));
} else {
return syscall2(.lstat, @intFromPtr(pathname), @intFromPtr(statbuf));
@@ -1860,7 +1878,11 @@ pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {
}
pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *Stat, flags: u32) usize {
- if (@hasField(SYS, "fstatat64")) {
+ if (native_arch == .riscv32) {
+ // riscv32 has made the interesting decision to not implement some of
+ // the older stat syscalls, including this one.
+ @compileError("No fstatat syscall on this architecture.");
+ } else if (@hasField(SYS, "fstatat64")) {
return syscall4(.fstatat64, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags);
} else {
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
}
pub fn statx(dirfd: i32, path: [*:0]const u8, flags: u32, mask: u32, statx_buf: *Statx) usize {
- if (@hasField(SYS, "statx")) {
- return syscall5(
- .statx,
- @as(usize, @bitCast(@as(isize, dirfd))),
- @intFromPtr(path),
- flags,
- mask,
- @intFromPtr(statx_buf),
- );
- }
- return @as(usize, @bitCast(-@as(isize, @intFromEnum(E.NOSYS))));
+ return syscall5(
+ .statx,
+ @as(usize, @bitCast(@as(isize, dirfd))),
+ @intFromPtr(path),
+ flags,
+ mask,
+ @intFromPtr(statx_buf),
+ );
}
pub 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
}
pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize {
- if (comptime builtin.cpu.arch.isMIPS()) {
- // MIPS requires a 7 argument syscall
+ if (comptime native_arch.isARM() or native_arch.isPPC()) {
+ // These architectures reorder the arguments so that a register is not skipped to align the
+ // register number that `offset` is passed in.
const offset_halves = splitValue64(offset);
const length_halves = splitValue64(len);
- return syscall7(
- .fadvise64,
+ return syscall6(
+ .fadvise64_64,
@as(usize, @bitCast(@as(isize, fd))),
- 0,
+ advice,
offset_halves[0],
offset_halves[1],
length_halves[0],
length_halves[1],
- advice,
);
- } else if (comptime builtin.cpu.arch.isARM()) {
- // ARM reorders the arguments
+ } else if (comptime native_arch == .mips or native_arch == .mipsel) {
+ // MIPS O32 does not deal with the register alignment issue, so pass a dummy value.
const offset_halves = splitValue64(offset);
const length_halves = splitValue64(len);
- return syscall6(
- .fadvise64_64,
+ return syscall7(
+ .fadvise64,
@as(usize, @bitCast(@as(isize, fd))),
- advice,
+ 0,
offset_halves[0],
offset_halves[1],
length_halves[0],
length_halves[1],
+ advice,
);
- } else if (@hasField(SYS, "fadvise64_64") and usize_bits != 64) {
- // The extra usize check is needed to avoid SPARC64 because it provides both
- // fadvise64 and fadvise64_64 but the latter behaves differently than other platforms.
+ } else if (comptime usize_bits < 64) {
+ // Other 32-bit architectures do not require register alignment.
const offset_halves = splitValue64(offset);
const length_halves = splitValue64(len);
@@ -2246,8 +2265,11 @@ pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize {
advice,
);
} else {
+ // On 64-bit architectures, fadvise64_64 and fadvise64 are the same. Generally, older ports
+ // call it fadvise64 (x86, PowerPC, etc), while newer ports call it fadvise64_64 (RISC-V,
+ // LoongArch, etc). SPARC is the odd one out because it has both.
return syscall4(
- .fadvise64,
+ if (@hasField(SYS, "fadvise64_64")) .fadvise64_64 else .fadvise64,
@as(usize, @bitCast(@as(isize, fd))),
@as(usize, @bitCast(offset)),
@as(usize, @bitCast(len)),
@@ -6295,12 +6317,13 @@ pub const POSIX_FADV = switch (native_arch) {
};
/// The timespec struct used by the kernel.
-pub const kernel_timespec = if (@sizeOf(usize) >= 8) timespec else extern struct {
+pub const kernel_timespec = extern struct {
sec: i64,
nsec: i64,
};
-pub const timespec = extern struct {
+// https://github.com/ziglang/zig/issues/4726#issuecomment-2190337877
+pub const timespec = if (!builtin.link_libc and native_arch == .riscv32) kernel_timespec else extern struct {
sec: isize,
nsec: isize,
};
@@ -7338,6 +7361,7 @@ pub const AUDIT = struct {
.x86_64 => .X86_64,
.aarch64 => .AARCH64,
.arm, .thumb => .ARM,
+ .riscv32 => .RISCV32,
.riscv64 => .RISCV64,
.sparc64 => .SPARC64,
.mips => .MIPS,
diff --git a/lib/std/os/linux/riscv32.zig b/lib/std/os/linux/riscv32.zig
new file mode 100644
index 0000000000..219eb5cc19
--- /dev/null
+++ b/lib/std/os/linux/riscv32.zig
@@ -0,0 +1,197 @@
+const std = @import("../../std.zig");
+const iovec = std.posix.iovec;
+const iovec_const = std.posix.iovec_const;
+const linux = std.os.linux;
+const SYS = linux.SYS;
+const uid_t = std.os.linux.uid_t;
+const gid_t = std.os.linux.gid_t;
+const pid_t = std.os.linux.pid_t;
+const sockaddr = linux.sockaddr;
+const socklen_t = linux.socklen_t;
+const timespec = std.os.linux.timespec;
+
+pub fn syscall0(number: SYS) usize {
+ return asm volatile ("ecall"
+ : [ret] "={x10}" (-> usize),
+ : [number] "{x17}" (@intFromEnum(number)),
+ : "memory"
+ );
+}
+
+pub fn syscall1(number: SYS, arg1: usize) usize {
+ return asm volatile ("ecall"
+ : [ret] "={x10}" (-> usize),
+ : [number] "{x17}" (@intFromEnum(number)),
+ [arg1] "{x10}" (arg1),
+ : "memory"
+ );
+}
+
+pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
+ return asm volatile ("ecall"
+ : [ret] "={x10}" (-> usize),
+ : [number] "{x17}" (@intFromEnum(number)),
+ [arg1] "{x10}" (arg1),
+ [arg2] "{x11}" (arg2),
+ : "memory"
+ );
+}
+
+pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
+ return asm volatile ("ecall"
+ : [ret] "={x10}" (-> usize),
+ : [number] "{x17}" (@intFromEnum(number)),
+ [arg1] "{x10}" (arg1),
+ [arg2] "{x11}" (arg2),
+ [arg3] "{x12}" (arg3),
+ : "memory"
+ );
+}
+
+pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
+ return asm volatile ("ecall"
+ : [ret] "={x10}" (-> usize),
+ : [number] "{x17}" (@intFromEnum(number)),
+ [arg1] "{x10}" (arg1),
+ [arg2] "{x11}" (arg2),
+ [arg3] "{x12}" (arg3),
+ [arg4] "{x13}" (arg4),
+ : "memory"
+ );
+}
+
+pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
+ return asm volatile ("ecall"
+ : [ret] "={x10}" (-> usize),
+ : [number] "{x17}" (@intFromEnum(number)),
+ [arg1] "{x10}" (arg1),
+ [arg2] "{x11}" (arg2),
+ [arg3] "{x12}" (arg3),
+ [arg4] "{x13}" (arg4),
+ [arg5] "{x14}" (arg5),
+ : "memory"
+ );
+}
+
+pub fn syscall6(
+ number: SYS,
+ arg1: usize,
+ arg2: usize,
+ arg3: usize,
+ arg4: usize,
+ arg5: usize,
+ arg6: usize,
+) usize {
+ return asm volatile ("ecall"
+ : [ret] "={x10}" (-> usize),
+ : [number] "{x17}" (@intFromEnum(number)),
+ [arg1] "{x10}" (arg1),
+ [arg2] "{x11}" (arg2),
+ [arg3] "{x12}" (arg3),
+ [arg4] "{x13}" (arg4),
+ [arg5] "{x14}" (arg5),
+ [arg6] "{x15}" (arg6),
+ : "memory"
+ );
+}
+
+const CloneFn = *const fn (arg: usize) callconv(.C) u8;
+
+pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
+
+pub const restore = restore_rt;
+
+pub fn restore_rt() callconv(.Naked) noreturn {
+ asm volatile (
+ \\ ecall
+ :
+ : [number] "{x17}" (@intFromEnum(SYS.rt_sigreturn)),
+ : "memory"
+ );
+}
+
+pub const F = struct {
+ pub const DUPFD = 0;
+ pub const GETFD = 1;
+ pub const SETFD = 2;
+ pub const GETFL = 3;
+ pub const SETFL = 4;
+ pub const GETLK = 5;
+ pub const SETLK = 6;
+ pub const SETLKW = 7;
+ pub const SETOWN = 8;
+ pub const GETOWN = 9;
+ pub const SETSIG = 10;
+ pub const GETSIG = 11;
+
+ pub const RDLCK = 0;
+ pub const WRLCK = 1;
+ pub const UNLCK = 2;
+
+ pub const SETOWN_EX = 15;
+ pub const GETOWN_EX = 16;
+
+ pub const GETOWNER_UIDS = 17;
+};
+
+pub const blksize_t = i32;
+pub const nlink_t = u32;
+pub const time_t = i64;
+pub const mode_t = u32;
+pub const off_t = i64;
+pub const ino_t = u64;
+pub const dev_t = u64;
+pub const blkcnt_t = i64;
+
+pub const timeval = extern struct {
+ sec: time_t,
+ usec: i64,
+};
+
+pub const Flock = extern struct {
+ type: i16,
+ whence: i16,
+ start: off_t,
+ len: off_t,
+ pid: pid_t,
+ __unused: [4]u8,
+};
+
+pub const msghdr = extern struct {
+ name: ?*sockaddr,
+ namelen: socklen_t,
+ iov: [*]iovec,
+ iovlen: i32,
+ __pad1: i32 = 0,
+ control: ?*anyopaque,
+ controllen: socklen_t,
+ __pad2: socklen_t = 0,
+ flags: i32,
+};
+
+pub const msghdr_const = extern struct {
+ name: ?*const sockaddr,
+ namelen: socklen_t,
+ iov: [*]const iovec_const,
+ iovlen: i32,
+ __pad1: i32 = 0,
+ control: ?*const anyopaque,
+ controllen: socklen_t,
+ __pad2: socklen_t = 0,
+ flags: i32,
+};
+
+/// No `Stat` structure on this platform, only `Statx`.
+pub const Stat = void;
+
+pub const Elf_Symndx = u32;
+
+pub const MMAP2_UNIT = 4096;
+
+pub const VDSO = struct {};
+
+/// TODO
+pub const ucontext_t = void;
+
+/// TODO
+pub const getcontext = {};
diff --git a/lib/std/os/linux/riscv64.zig b/lib/std/os/linux/riscv64.zig
index 6c590348f4..fc0893d5c1 100644
--- a/lib/std/os/linux/riscv64.zig
+++ b/lib/std/os/linux/riscv64.zig
@@ -136,12 +136,12 @@ pub const F = struct {
pub const blksize_t = i32;
pub const nlink_t = u32;
-pub const time_t = isize;
+pub const time_t = i64;
pub const mode_t = u32;
-pub const off_t = isize;
-pub const ino_t = usize;
-pub const dev_t = usize;
-pub const blkcnt_t = isize;
+pub const off_t = i64;
+pub const ino_t = u64;
+pub const dev_t = u64;
+pub const blkcnt_t = i64;
pub const timeval = extern struct {
sec: time_t,
diff --git a/lib/std/os/linux/start_pie.zig b/lib/std/os/linux/start_pie.zig
index 19b6c332f7..5c35262bc8 100644
--- a/lib/std/os/linux/start_pie.zig
+++ b/lib/std/os/linux/start_pie.zig
@@ -26,7 +26,7 @@ const R_RELATIVE = switch (builtin.cpu.arch) {
.hexagon => R_HEXAGON_RELATIVE,
.loongarch32, .loongarch64 => R_LARCH_RELATIVE,
.m68k => R_68K_RELATIVE,
- .riscv64 => R_RISCV_RELATIVE,
+ .riscv32, .riscv64 => R_RISCV_RELATIVE,
.s390x => R_390_RELATIVE,
else => @compileError("Missing R_RELATIVE definition for this target"),
};
@@ -111,7 +111,7 @@ fn getDynamicSymbol() [*]elf.Dyn {
\\ lea (%[ret], %%pc), %[ret]
: [ret] "=r" (-> [*]elf.Dyn),
),
- .riscv64 => asm volatile (
+ .riscv32, .riscv64 => asm volatile (
\\ .weak _DYNAMIC
\\ .hidden _DYNAMIC
\\ lla %[ret], _DYNAMIC
diff --git a/lib/std/os/linux/syscalls.zig b/lib/std/os/linux/syscalls.zig
index 55f0cebe56..1ede5ac620 100644
--- a/lib/std/os/linux/syscalls.zig
+++ b/lib/std/os/linux/syscalls.zig
@@ -142,16 +142,16 @@ pub const X86 = enum(usize) {
afs_syscall = 137,
setfsuid = 138,
setfsgid = 139,
- _llseek = 140,
+ llseek = 140,
getdents = 141,
- _newselect = 142,
+ newselect = 142,
flock = 143,
msync = 144,
readv = 145,
writev = 146,
getsid = 147,
fdatasync = 148,
- _sysctl = 149,
+ sysctl = 149,
mlock = 150,
munlock = 151,
mlockall = 152,
@@ -607,7 +607,7 @@ pub const X64 = enum(usize) {
vhangup = 153,
modify_ldt = 154,
pivot_root = 155,
- _sysctl = 156,
+ sysctl = 156,
prctl = 157,
arch_prctl = 158,
adjtimex = 159,
@@ -927,16 +927,16 @@ pub const Arm = enum(usize) {
personality = 136,
setfsuid = 138,
setfsgid = 139,
- _llseek = 140,
+ llseek = 140,
getdents = 141,
- _newselect = 142,
+ newselect = 142,
flock = 143,
msync = 144,
readv = 145,
writev = 146,
getsid = 147,
fdatasync = 148,
- _sysctl = 149,
+ sysctl = 149,
mlock = 150,
munlock = 151,
mlockall = 152,
@@ -1454,12 +1454,12 @@ pub const Sparc64 = enum(usize) {
afs_syscall = 227,
setfsuid = 228,
setfsgid = 229,
- _newselect = 230,
+ newselect = 230,
splice = 232,
stime = 233,
statfs64 = 234,
fstatfs64 = 235,
- _llseek = 236,
+ llseek = 236,
mlock = 237,
munlock = 238,
mlockall = 239,
@@ -1474,7 +1474,7 @@ pub const Sparc64 = enum(usize) {
sched_rr_get_interval = 248,
nanosleep = 249,
mremap = 250,
- _sysctl = 251,
+ sysctl = 251,
getsid = 252,
fdatasync = 253,
nfsservctl = 254,
@@ -1771,9 +1771,9 @@ pub const Mips = enum(usize) {
afs_syscall = Linux + 137,
setfsuid = Linux + 138,
setfsgid = Linux + 139,
- _llseek = Linux + 140,
+ llseek = Linux + 140,
getdents = Linux + 141,
- _newselect = Linux + 142,
+ newselect = Linux + 142,
flock = Linux + 143,
msync = Linux + 144,
readv = Linux + 145,
@@ -1783,7 +1783,7 @@ pub const Mips = enum(usize) {
sysmips = Linux + 149,
getsid = Linux + 151,
fdatasync = Linux + 152,
- _sysctl = Linux + 153,
+ sysctl = Linux + 153,
mlock = Linux + 154,
munlock = Linux + 155,
mlockall = Linux + 156,
@@ -2087,7 +2087,7 @@ pub const Mips64 = enum(usize) {
writev = Linux + 19,
access = Linux + 20,
pipe = Linux + 21,
- _newselect = Linux + 22,
+ newselect = Linux + 22,
sched_yield = Linux + 23,
mremap = Linux + 24,
msync = Linux + 25,
@@ -2217,7 +2217,7 @@ pub const Mips64 = enum(usize) {
munlockall = Linux + 149,
vhangup = Linux + 150,
pivot_root = Linux + 151,
- _sysctl = Linux + 152,
+ sysctl = Linux + 152,
prctl = Linux + 153,
adjtimex = Linux + 154,
setrlimit = Linux + 155,
@@ -2568,16 +2568,16 @@ pub const PowerPC = enum(usize) {
afs_syscall = 137,
setfsuid = 138,
setfsgid = 139,
- _llseek = 140,
+ llseek = 140,
getdents = 141,
- _newselect = 142,
+ newselect = 142,
flock = 143,
msync = 144,
readv = 145,
writev = 146,
getsid = 147,
fdatasync = 148,
- _sysctl = 149,
+ sysctl = 149,
mlock = 150,
munlock = 151,
mlockall = 152,
@@ -3008,16 +3008,16 @@ pub const PowerPC64 = enum(usize) {
afs_syscall = 137,
setfsuid = 138,
setfsgid = 139,
- _llseek = 140,
+ llseek = 140,
getdents = 141,
- _newselect = 142,
+ newselect = 142,
flock = 143,
msync = 144,
readv = 145,
writev = 146,
getsid = 147,
fdatasync = 148,
- _sysctl = 149,
+ sysctl = 149,
mlock = 150,
munlock = 151,
mlockall = 152,
@@ -3351,7 +3351,7 @@ pub const Arm64 = enum(usize) {
pwrite64 = 68,
preadv = 69,
pwritev = 70,
- sendfile = 71,
+ sendfile64 = 71,
pselect6 = 72,
ppoll = 73,
signalfd4 = 74,
@@ -3359,8 +3359,8 @@ pub const Arm64 = enum(usize) {
splice = 76,
tee = 77,
readlinkat = 78,
- fstatat = 79,
- fstat = 80,
+ fstatat64 = 79,
+ fstat64 = 80,
sync = 81,
fsync = 82,
fdatasync = 83,
@@ -3503,7 +3503,7 @@ pub const Arm64 = enum(usize) {
clone = 220,
execve = 221,
mmap = 222,
- fadvise64 = 223,
+ fadvise64_64 = 223,
swapon = 224,
swapoff = 225,
mprotect = 226,
@@ -3594,9 +3594,313 @@ pub const Arm64 = enum(usize) {
futex_requeue = 456,
};
-pub const RiscV64 = enum(usize) {
- pub const arch_specific_syscall = 244;
+pub const RiscV32 = enum(usize) {
+ io_setup = 0,
+ io_destroy = 1,
+ io_submit = 2,
+ io_cancel = 3,
+ setxattr = 5,
+ lsetxattr = 6,
+ fsetxattr = 7,
+ getxattr = 8,
+ lgetxattr = 9,
+ fgetxattr = 10,
+ listxattr = 11,
+ llistxattr = 12,
+ flistxattr = 13,
+ removexattr = 14,
+ lremovexattr = 15,
+ fremovexattr = 16,
+ getcwd = 17,
+ lookup_dcookie = 18,
+ eventfd2 = 19,
+ epoll_create1 = 20,
+ epoll_ctl = 21,
+ epoll_pwait = 22,
+ dup = 23,
+ dup3 = 24,
+ fcntl64 = 25,
+ inotify_init1 = 26,
+ inotify_add_watch = 27,
+ inotify_rm_watch = 28,
+ ioctl = 29,
+ ioprio_set = 30,
+ ioprio_get = 31,
+ flock = 32,
+ mknodat = 33,
+ mkdirat = 34,
+ unlinkat = 35,
+ symlinkat = 36,
+ linkat = 37,
+ umount2 = 39,
+ mount = 40,
+ pivot_root = 41,
+ nfsservctl = 42,
+ statfs64 = 43,
+ fstatfs64 = 44,
+ truncate64 = 45,
+ ftruncate64 = 46,
+ fallocate = 47,
+ faccessat = 48,
+ chdir = 49,
+ fchdir = 50,
+ chroot = 51,
+ fchmod = 52,
+ fchmodat = 53,
+ fchownat = 54,
+ fchown = 55,
+ openat = 56,
+ close = 57,
+ vhangup = 58,
+ pipe2 = 59,
+ quotactl = 60,
+ getdents64 = 61,
+ llseek = 62,
+ read = 63,
+ write = 64,
+ readv = 65,
+ writev = 66,
+ pread64 = 67,
+ pwrite64 = 68,
+ preadv = 69,
+ pwritev = 70,
+ sendfile64 = 71,
+ signalfd4 = 74,
+ vmsplice = 75,
+ splice = 76,
+ tee = 77,
+ readlinkat = 78,
+ sync = 81,
+ fsync = 82,
+ fdatasync = 83,
+ sync_file_range = 84,
+ timerfd_create = 85,
+ acct = 89,
+ capget = 90,
+ capset = 91,
+ personality = 92,
+ exit = 93,
+ exit_group = 94,
+ waitid = 95,
+ set_tid_address = 96,
+ unshare = 97,
+ set_robust_list = 99,
+ get_robust_list = 100,
+ getitimer = 102,
+ setitimer = 103,
+ kexec_load = 104,
+ init_module = 105,
+ delete_module = 106,
+ timer_create = 107,
+ timer_getoverrun = 109,
+ timer_delete = 111,
+ syslog = 116,
+ ptrace = 117,
+ sched_setparam = 118,
+ sched_setscheduler = 119,
+ sched_getscheduler = 120,
+ sched_getparam = 121,
+ sched_setaffinity = 122,
+ sched_getaffinity = 123,
+ sched_yield = 124,
+ sched_get_priority_max = 125,
+ sched_get_priority_min = 126,
+ restart_syscall = 128,
+ kill = 129,
+ tkill = 130,
+ tgkill = 131,
+ sigaltstack = 132,
+ rt_sigsuspend = 133,
+ rt_sigaction = 134,
+ rt_sigprocmask = 135,
+ rt_sigpending = 136,
+ rt_sigqueueinfo = 138,
+ rt_sigreturn = 139,
+ setpriority = 140,
+ getpriority = 141,
+ reboot = 142,
+ setregid = 143,
+ setgid = 144,
+ setreuid = 145,
+ setuid = 146,
+ setresuid = 147,
+ getresuid = 148,
+ setresgid = 149,
+ getresgid = 150,
+ setfsuid = 151,
+ setfsgid = 152,
+ times = 153,
+ setpgid = 154,
+ getpgid = 155,
+ getsid = 156,
+ setsid = 157,
+ getgroups = 158,
+ setgroups = 159,
+ uname = 160,
+ sethostname = 161,
+ setdomainname = 162,
+ getrusage = 165,
+ umask = 166,
+ prctl = 167,
+ getcpu = 168,
+ getpid = 172,
+ getppid = 173,
+ getuid = 174,
+ geteuid = 175,
+ getgid = 176,
+ getegid = 177,
+ gettid = 178,
+ sysinfo = 179,
+ mq_open = 180,
+ mq_unlink = 181,
+ mq_notify = 184,
+ mq_getsetattr = 185,
+ msgget = 186,
+ msgctl = 187,
+ msgrcv = 188,
+ msgsnd = 189,
+ semget = 190,
+ semctl = 191,
+ semop = 193,
+ shmget = 194,
+ shmctl = 195,
+ shmat = 196,
+ shmdt = 197,
+ socket = 198,
+ socketpair = 199,
+ bind = 200,
+ listen = 201,
+ accept = 202,
+ connect = 203,
+ getsockname = 204,
+ getpeername = 205,
+ sendto = 206,
+ recvfrom = 207,
+ setsockopt = 208,
+ getsockopt = 209,
+ shutdown = 210,
+ sendmsg = 211,
+ recvmsg = 212,
+ readahead = 213,
+ brk = 214,
+ munmap = 215,
+ mremap = 216,
+ add_key = 217,
+ request_key = 218,
+ keyctl = 219,
+ clone = 220,
+ execve = 221,
+ mmap2 = 222,
+ fadvise64_64 = 223,
+ swapon = 224,
+ swapoff = 225,
+ mprotect = 226,
+ msync = 227,
+ mlock = 228,
+ munlock = 229,
+ mlockall = 230,
+ munlockall = 231,
+ mincore = 232,
+ madvise = 233,
+ remap_file_pages = 234,
+ mbind = 235,
+ get_mempolicy = 236,
+ set_mempolicy = 237,
+ migrate_pages = 238,
+ move_pages = 239,
+ rt_tgsigqueueinfo = 240,
+ perf_event_open = 241,
+ accept4 = 242,
+ prlimit64 = 261,
+ fanotify_init = 262,
+ fanotify_mark = 263,
+ name_to_handle_at = 264,
+ open_by_handle_at = 265,
+ syncfs = 267,
+ setns = 268,
+ sendmmsg = 269,
+ process_vm_readv = 270,
+ process_vm_writev = 271,
+ kcmp = 272,
+ finit_module = 273,
+ sched_setattr = 274,
+ sched_getattr = 275,
+ renameat2 = 276,
+ seccomp = 277,
+ getrandom = 278,
+ memfd_create = 279,
+ bpf = 280,
+ execveat = 281,
+ userfaultfd = 282,
+ membarrier = 283,
+ mlock2 = 284,
+ copy_file_range = 285,
+ preadv2 = 286,
+ pwritev2 = 287,
+ pkey_mprotect = 288,
+ pkey_alloc = 289,
+ pkey_free = 290,
+ statx = 291,
+ rseq = 293,
+ kexec_file_load = 294,
+ clock_gettime = 403,
+ clock_settime = 404,
+ clock_adjtime = 405,
+ clock_getres = 406,
+ clock_nanosleep = 407,
+ timer_gettime = 408,
+ timer_settime = 409,
+ timerfd_gettime = 410,
+ timerfd_settime = 411,
+ utimensat = 412,
+ pselect6 = 413,
+ ppoll = 414,
+ io_pgetevents = 416,
+ recvmmsg = 417,
+ mq_timedsend = 418,
+ mq_timedreceive = 419,
+ semtimedop = 420,
+ rt_sigtimedwait = 421,
+ futex = 422,
+ sched_rr_get_interval = 423,
+ pidfd_send_signal = 424,
+ io_uring_setup = 425,
+ io_uring_enter = 426,
+ io_uring_register = 427,
+ open_tree = 428,
+ move_mount = 429,
+ fsopen = 430,
+ fsconfig = 431,
+ fsmount = 432,
+ fspick = 433,
+ pidfd_open = 434,
+ clone3 = 435,
+ close_range = 436,
+ openat2 = 437,
+ pidfd_getfd = 438,
+ faccessat2 = 439,
+ process_madvise = 440,
+ epoll_pwait2 = 441,
+ mount_setattr = 442,
+ quotactl_fd = 443,
+ landlock_create_ruleset = 444,
+ landlock_add_rule = 445,
+ landlock_restrict_self = 446,
+ memfd_secret = 447,
+ process_mrelease = 448,
+ futex_waitv = 449,
+ set_mempolicy_home_node = 450,
+ cachestat = 451,
+ fchmodat2 = 452,
+ map_shadow_stack = 453,
+ futex_wake = 454,
+ futex_wait = 455,
+ futex_requeue = 456,
+ riscv_flush_icache = (244 + 15),
+ riscv_hwprobe = (244 + 14),
+};
+pub const RiscV64 = enum(usize) {
io_setup = 0,
io_destroy = 1,
io_submit = 2,
@@ -3667,7 +3971,7 @@ pub const RiscV64 = enum(usize) {
pwrite64 = 68,
preadv = 69,
pwritev = 70,
- sendfile = 71,
+ sendfile64 = 71,
pselect6 = 72,
ppoll = 73,
signalfd4 = 74,
@@ -3675,8 +3979,8 @@ pub const RiscV64 = enum(usize) {
splice = 76,
tee = 77,
readlinkat = 78,
- fstatat = 79,
- fstat = 80,
+ fstatat64 = 79,
+ fstat64 = 80,
sync = 81,
fsync = 82,
fdatasync = 83,
@@ -3819,7 +4123,7 @@ pub const RiscV64 = enum(usize) {
clone = 220,
execve = 221,
mmap = 222,
- fadvise64 = 223,
+ fadvise64_64 = 223,
swapon = 224,
swapoff = 225,
mprotect = 226,
@@ -3908,8 +4212,8 @@ pub const RiscV64 = enum(usize) {
futex_wake = 454,
futex_wait = 455,
futex_requeue = 456,
-
- riscv_flush_icache = arch_specific_syscall + 15,
+ riscv_flush_icache = (244 + 15),
+ riscv_hwprobe = (244 + 14),
};
pub const LoongArch64 = enum(usize) {
diff --git a/lib/std/os/linux/test.zig b/lib/std/os/linux/test.zig
index 0f1349af20..b3c02803f3 100644
--- a/lib/std/os/linux/test.zig
+++ b/lib/std/os/linux/test.zig
@@ -79,11 +79,11 @@ test "statx" {
var statx_buf: linux.Statx = undefined;
switch (linux.E.init(linux.statx(file.handle, "", linux.AT.EMPTY_PATH, linux.STATX_BASIC_STATS, &statx_buf))) {
.SUCCESS => {},
- // The statx syscall was only introduced in linux 4.11
- .NOSYS => return error.SkipZigTest,
else => unreachable,
}
+ if (builtin.cpu.arch == .riscv32) return error.SkipZigTest; // No fstatat, so the rest of the test is meaningless.
+
var stat_buf: linux.Stat = undefined;
switch (linux.E.init(linux.fstatat(file.handle, "", &stat_buf, linux.AT.EMPTY_PATH))) {
.SUCCESS => {},
diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig
index 2611e9a05c..f6aef8aa91 100644
--- a/lib/std/os/linux/tls.zig
+++ b/lib/std/os/linux/tls.zig
@@ -170,7 +170,7 @@ pub fn setThreadPointer(addr: usize) void {
const rc = @call(.always_inline, linux.syscall1, .{ .set_tls, addr });
assert(rc == 0);
},
- .riscv64 => {
+ .riscv32, .riscv64 => {
asm volatile (
\\ mv tp, %[addr]
:
diff --git a/lib/std/posix.zig b/lib/std/posix.zig
index 955987b036..e04efbbcc0 100644
--- a/lib/std/posix.zig
+++ b/lib/std/posix.zig
@@ -615,7 +615,6 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {
.INVAL => unreachable,
.FAULT => unreachable,
.INTR => continue,
- .NOSYS => return getRandomBytesDevURandom(buf),
else => return unexpectedErrno(err),
}
}
@@ -4534,7 +4533,6 @@ pub const FanotifyInitError = error{
ProcessFdQuotaExceeded,
SystemFdQuotaExceeded,
SystemResources,
- OperationNotSupported,
PermissionDenied,
} || UnexpectedError;
@@ -4546,7 +4544,6 @@ pub fn fanotify_init(flags: std.os.linux.fanotify.InitFlags, event_f_flags: u32)
.MFILE => return error.ProcessFdQuotaExceeded,
.NFILE => return error.SystemFdQuotaExceeded,
.NOMEM => return error.SystemResources,
- .NOSYS => return error.OperationNotSupported,
.PERM => return error.PermissionDenied,
else => |err| return unexpectedErrno(err),
}
@@ -4559,7 +4556,6 @@ pub const FanotifyMarkError = error{
FileNotFound,
SystemResources,
UserMarkQuotaExceeded,
- NotImplemented,
NotDir,
OperationNotSupported,
PermissionDenied,
@@ -4600,7 +4596,6 @@ pub fn fanotify_markZ(
.NOENT => return error.FileNotFound,
.NOMEM => return error.SystemResources,
.NOSPC => return error.UserMarkQuotaExceeded,
- .NOSYS => return error.NotImplemented,
.NOTDIR => return error.NotDir,
.OPNOTSUPP => return error.OperationNotSupported,
.PERM => return error.PermissionDenied,
@@ -6183,13 +6178,6 @@ pub fn sendfile(
switch (native_os) {
.linux => sf: {
- // sendfile() first appeared in Linux 2.2, glibc 2.1.
- const call_sf = comptime if (builtin.link_libc)
- std.c.versionCheck(.{ .major = 2, .minor = 1, .patch = 0 })
- else
- builtin.os.version_range.linux.range.max.order(.{ .major = 2, .minor = 2, .patch = 0 }) != .lt;
- if (!call_sf) break :sf;
-
if (headers.len != 0) {
const amt = try writev(out_fd, headers);
total_written += amt;
@@ -6223,14 +6211,14 @@ pub fn sendfile(
.OVERFLOW => unreachable, // We avoid passing too large of a `count`.
.NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket
- .INVAL, .NOSYS => {
+ .INVAL => {
// EINVAL could be any of the following situations:
// * Descriptor is not valid or locked
// * an mmap(2)-like operation is not available for in_fd
// * count is negative
// * out_fd has the APPEND flag set
// Because of the "mmap(2)-like operation" possibility, we fall back to doing read/write
- // manually, the same as ENOSYS.
+ // manually.
break :sf;
},
.AGAIN => return error.WouldBlock,
@@ -6456,21 +6444,15 @@ pub const CopyFileRangeError = error{
/// `flags` has different meanings per operating system; refer to the respective man pages.
///
/// These systems support in-kernel data copying:
-/// * Linux 4.5 (cross-filesystem 5.3)
+/// * Linux (cross-filesystem from version 5.3)
/// * FreeBSD 13.0
///
/// Other systems fall back to calling `pread` / `pwrite`.
///
/// Maximum offsets on Linux and FreeBSD are `maxInt(i64)`.
pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize {
- const global = struct {
- var has_copy_file_range = true;
- };
-
if ((comptime builtin.os.isAtLeast(.freebsd, .{ .major = 13, .minor = 0, .patch = 0 }) orelse false) or
- ((comptime builtin.os.isAtLeast(.linux, .{ .major = 4, .minor = 5, .patch = 0 }) orelse false and
- std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 })) and
- @atomicLoad(bool, &global.has_copy_file_range, .monotonic)))
+ (comptime builtin.os.tag == .linux and std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 })))
{
var off_in_copy: i64 = @bitCast(off_in);
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
.PERM => return error.PermissionDenied,
.TXTBSY => return error.SwapFile,
.XDEV => break, // support for cross-filesystem copy added in Linux 5.3, use fallback
- .NOSYS => {
- @atomicStore(bool, &global.has_copy_file_range, false, .monotonic);
- break;
- },
else => |err| return unexpectedErrno(err),
}
}
@@ -6775,10 +6753,6 @@ pub const MemFdCreateError = error{
OutOfMemory,
/// Either the name provided exceeded `NAME_MAX`, or invalid flags were passed.
NameTooLong,
-
- /// memfd_create is available in Linux 3.17 and later. This error is returned
- /// for older kernel versions.
- SystemOutdated,
} || UnexpectedError;
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 {
.NFILE => return error.SystemFdQuotaExceeded,
.MFILE => return error.ProcessFdQuotaExceeded,
.NOMEM => return error.OutOfMemory,
- .NOSYS => return error.SystemOutdated,
else => |err| return unexpectedErrno(err),
}
},
@@ -6915,7 +6888,6 @@ pub fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) !fd_t {
.NOMEM => return error.SystemResources,
.MFILE => return error.ProcessResources,
.NODEV => return error.InodeMountFail,
- .NOSYS => return error.SystemOutdated,
else => |err| return unexpectedErrno(err),
}
}
diff --git a/lib/std/posix/test.zig b/lib/std/posix/test.zig
index 7db9c3f805..11b01a7266 100644
--- a/lib/std/posix/test.zig
+++ b/lib/std/posix/test.zig
@@ -580,11 +580,7 @@ test "memfd_create" {
else => return error.SkipZigTest,
}
- const fd = posix.memfd_create("test", 0) catch |err| switch (err) {
- // Related: https://github.com/ziglang/zig/issues/4019
- error.SystemOutdated => return error.SkipZigTest,
- else => |e| return e,
- };
+ const fd = try posix.memfd_create("test", 0);
defer posix.close(fd);
try expect((try posix.write(fd, "test")) == 4);
try posix.lseek_SET(fd, 0);
diff --git a/lib/std/start.zig b/lib/std/start.zig
index 45c224d392..2a61be46e4 100644
--- a/lib/std/start.zig
+++ b/lib/std/start.zig
@@ -272,7 +272,7 @@ fn _start() callconv(.Naked) noreturn {
\\ bstrins.d $sp, $zero, 3, 0
\\ b %[posixCallMainAndExit]
,
- .riscv64 =>
+ .riscv32, .riscv64 =>
\\ li s0, 0
\\ li ra, 0
\\ mv a0, sp
diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig
index 7022aee1e1..d86d47ba59 100644
--- a/lib/std/zig/target.zig
+++ b/lib/std/zig/target.zig
@@ -56,7 +56,7 @@ pub const available_libcs = [_]ArchOsAbi{
.{ .arch = .powerpc, .os = .linux, .abi = .gnueabi },
.{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf },
.{ .arch = .powerpc, .os = .linux, .abi = .musl },
- .{ .arch = .riscv32, .os = .linux, .abi = .gnuilp32, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 } },
+ .{ .arch = .riscv32, .os = .linux, .abi = .gnuilp32, .glibc_min = .{ .major = 2, .minor = 33, .patch = 0 } },
.{ .arch = .riscv32, .os = .linux, .abi = .musl },
.{ .arch = .riscv64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 } },
.{ .arch = .riscv64, .os = .linux, .abi = .musl },