mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
Merge pull request #20389 from alexrp/riscv32
Some `riscv32-linux` porting work
This commit is contained in:
commit
38e0f049c5
21 changed files with 920 additions and 229 deletions
34
lib/c.zig
34
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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
),
|
||||
.riscv64 => asm volatile (
|
||||
\\ li a7, 215
|
||||
.riscv32 => asm volatile (
|
||||
\\ li a7, 215 # SYS_munmap
|
||||
\\ mv a0, %[ptr]
|
||||
\\ mv a1, %[len]
|
||||
\\ ecall
|
||||
\\ li a7, 93
|
||||
\\ 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 # SYS_munmap
|
||||
\\ mv a0, %[ptr]
|
||||
\\ mv a1, %[len]
|
||||
\\ ecall
|
||||
\\ 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
|
||||
:
|
||||
|
|
|
|||
|
|
@ -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: [
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
var stx = std.mem.zeroes(linux.Statx);
|
||||
|
||||
switch (posix.errno(rcx)) {
|
||||
// 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;
|
||||
|
|
|
|||
|
|
@ -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,8 +2217,24 @@ 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 syscall6(
|
||||
.fadvise64_64,
|
||||
@as(usize, @bitCast(@as(isize, fd))),
|
||||
advice,
|
||||
offset_halves[0],
|
||||
offset_halves[1],
|
||||
length_halves[0],
|
||||
length_halves[1],
|
||||
);
|
||||
} 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);
|
||||
|
|
@ -2214,24 +2249,8 @@ pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize {
|
|||
length_halves[1],
|
||||
advice,
|
||||
);
|
||||
} else if (comptime builtin.cpu.arch.isARM()) {
|
||||
// ARM reorders the arguments
|
||||
|
||||
const offset_halves = splitValue64(offset);
|
||||
const length_halves = splitValue64(len);
|
||||
|
||||
return syscall6(
|
||||
.fadvise64_64,
|
||||
@as(usize, @bitCast(@as(isize, fd))),
|
||||
advice,
|
||||
offset_halves[0],
|
||||
offset_halves[1],
|
||||
length_halves[0],
|
||||
length_halves[1],
|
||||
);
|
||||
} 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,
|
||||
|
|
|
|||
197
lib/std/os/linux/riscv32.zig
Normal file
197
lib/std/os/linux/riscv32.zig
Normal file
|
|
@ -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 = {};
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 => {},
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
:
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -3150,7 +3150,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
|
|||
}
|
||||
}
|
||||
|
||||
if (self.getTarget().cpu.arch == .riscv64 and self.isEffectivelyDynLib()) {
|
||||
if (self.getTarget().cpu.arch.isRISCV() and self.isEffectivelyDynLib()) {
|
||||
self.global_pointer_index = try linker_defined.addGlobal("__global_pointer$", self);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -301,6 +301,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: std.Progre
|
|||
pub fn needsCrtiCrtn(target: std.Target) bool {
|
||||
// zig fmt: off
|
||||
return switch (target.cpu.arch) {
|
||||
.riscv32,
|
||||
.riscv64,
|
||||
.wasm32, .wasm64 => return false,
|
||||
else => true,
|
||||
|
|
|
|||
|
|
@ -2,13 +2,14 @@
|
|||
//! ./gen_stubs /path/to/musl/build-all >libc.S
|
||||
//!
|
||||
//! The directory 'build-all' is expected to contain these subdirectories:
|
||||
//! arm x86 mips mips64 powerpc powerpc64 riscv64 x86_64
|
||||
//! arm x86 mips mips64 powerpc powerpc64 riscv32 riscv64 x86_64
|
||||
//!
|
||||
//! ...each with 'lib/libc.so' inside of them.
|
||||
//!
|
||||
//! When building the resulting libc.S file, these defines are required:
|
||||
//! * `-DPTR64`: when the architecture is 64-bit
|
||||
//! * One of the following, corresponding to the CPU architecture:
|
||||
//! - `-DARCH_riscv32`
|
||||
//! - `-DARCH_riscv64`
|
||||
//! - `-DARCH_mips`
|
||||
//! - `-DARCH_mips64`
|
||||
|
|
@ -68,7 +69,8 @@ const MultiSym = struct {
|
|||
}
|
||||
|
||||
fn is32Only(ms: MultiSym) bool {
|
||||
return ms.present[archIndex(.riscv64)] == false and
|
||||
return ms.present[archIndex(.riscv32)] == true and
|
||||
ms.present[archIndex(.riscv64)] == false and
|
||||
ms.present[archIndex(.mips)] == true and
|
||||
ms.present[archIndex(.mips64)] == false and
|
||||
ms.present[archIndex(.x86)] == true and
|
||||
|
|
@ -110,6 +112,7 @@ const MultiSym = struct {
|
|||
|
||||
fn isPtrSize(ms: MultiSym) bool {
|
||||
const map = .{
|
||||
.{ .riscv32, 4 },
|
||||
.{ .riscv64, 8 },
|
||||
.{ .mips, 4 },
|
||||
.{ .mips64, 8 },
|
||||
|
|
@ -132,6 +135,7 @@ const MultiSym = struct {
|
|||
|
||||
fn isPtr2Size(ms: MultiSym) bool {
|
||||
const map = .{
|
||||
.{ .riscv32, 8 },
|
||||
.{ .riscv64, 16 },
|
||||
.{ .mips, 8 },
|
||||
.{ .mips64, 16 },
|
||||
|
|
@ -154,6 +158,7 @@ const MultiSym = struct {
|
|||
|
||||
fn isWeak64(ms: MultiSym) bool {
|
||||
const map = .{
|
||||
.{ .riscv32, 1 },
|
||||
.{ .riscv64, 2 },
|
||||
.{ .mips, 1 },
|
||||
.{ .mips64, 2 },
|
||||
|
|
|
|||
|
|
@ -10,7 +10,12 @@ const zig = std.zig;
|
|||
const fs = std.fs;
|
||||
|
||||
const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{
|
||||
// Remove underscore prefix.
|
||||
.{ "_llseek", "llseek" },
|
||||
.{ "_newselect", "newselect" },
|
||||
.{ "_sysctl", "sysctl" },
|
||||
// Most 64-bit archs.
|
||||
.{ "newfstat", "fstat64" },
|
||||
.{ "newfstatat", "fstatat64" },
|
||||
// POWER.
|
||||
.{ "sync_file_range2", "sync_file_range" },
|
||||
|
|
@ -19,6 +24,24 @@ const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{
|
|||
.{ "arm_fadvise64_64", "fadvise64_64" },
|
||||
});
|
||||
|
||||
// Only for newer architectures where we use the C preprocessor.
|
||||
const stdlib_renames_new = std.StaticStringMap([]const u8).initComptime(.{
|
||||
.{ "newuname", "uname" },
|
||||
.{ "umount", "umount2" },
|
||||
});
|
||||
|
||||
// We use this to deal with the fact that multiple syscalls can be mapped to sys_ni_syscall.
|
||||
// Thankfully it's only 2 well-known syscalls in newer kernel ports at the moment.
|
||||
fn getOverridenNameNew(value: []const u8) ?[]const u8 {
|
||||
if (mem.eql(u8, value, "18")) {
|
||||
return "sys_lookup_dcookie";
|
||||
} else if (mem.eql(u8, value, "42")) {
|
||||
return "sys_nfsservctl";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
|
|
@ -60,8 +83,9 @@ pub fn main() !void {
|
|||
// abi is always i386
|
||||
_ = fields.next() orelse return error.Incomplete;
|
||||
const name = fields.next() orelse return error.Incomplete;
|
||||
const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
|
||||
|
||||
try writer.print(" {p} = {s},\n", .{ zig.fmtId(name), number });
|
||||
try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
|
||||
}
|
||||
|
||||
try writer.writeAll("};\n\n");
|
||||
|
|
@ -80,8 +104,8 @@ pub fn main() !void {
|
|||
// The x32 abi syscalls are always at the end.
|
||||
if (mem.eql(u8, abi, "x32")) break;
|
||||
const name = fields.next() orelse return error.Incomplete;
|
||||
|
||||
const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
|
||||
|
||||
try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
|
||||
}
|
||||
|
||||
|
|
@ -105,8 +129,8 @@ pub fn main() !void {
|
|||
const abi = fields.next() orelse return error.Incomplete;
|
||||
if (mem.eql(u8, abi, "oabi")) continue;
|
||||
const name = fields.next() orelse return error.Incomplete;
|
||||
|
||||
const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
|
||||
|
||||
try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
|
||||
}
|
||||
|
||||
|
|
@ -136,8 +160,9 @@ pub fn main() !void {
|
|||
const abi = fields.next() orelse return error.Incomplete;
|
||||
if (mem.eql(u8, abi, "32")) continue;
|
||||
const name = fields.next() orelse return error.Incomplete;
|
||||
const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
|
||||
|
||||
try writer.print(" {p} = {s},\n", .{ zig.fmtId(name), number });
|
||||
try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
|
||||
}
|
||||
|
||||
try writer.writeAll("};\n\n");
|
||||
|
|
@ -161,8 +186,9 @@ pub fn main() !void {
|
|||
_ = fields.next() orelse return error.Incomplete;
|
||||
const name = fields.next() orelse return error.Incomplete;
|
||||
if (mem.startsWith(u8, name, "unused")) continue;
|
||||
const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
|
||||
|
||||
try writer.print(" {p} = Linux + {s},\n", .{ zig.fmtId(name), number });
|
||||
try writer.print(" {p} = Linux + {s},\n", .{ zig.fmtId(fixed_name), number });
|
||||
}
|
||||
|
||||
try writer.writeAll("};\n\n");
|
||||
|
|
@ -232,11 +258,6 @@ pub fn main() !void {
|
|||
// Newer architectures (starting with aarch64 c. 2012) now use the same C
|
||||
// header file for their syscall numbers. Arch-specific headers are used to
|
||||
// define pre-proc. vars that add additional (usually obsolete) syscalls.
|
||||
//
|
||||
// TODO:
|
||||
// - It would be better to use libclang/translate-c directly to extract the definitions.
|
||||
// - The `-dD` option only does minimal pre-processing and doesn't resolve addition,
|
||||
// so arch specific syscalls are dealt with manually.
|
||||
{
|
||||
try writer.writeAll("pub const Arm64 = enum(usize) {\n");
|
||||
|
||||
|
|
@ -254,6 +275,8 @@ pub fn main() !void {
|
|||
// Using -I=[dir] includes the zig linux headers, which we don't want.
|
||||
"-Iinclude",
|
||||
"-Iinclude/uapi",
|
||||
// Output the syscall in a format we can easily recognize.
|
||||
"-D __SYSCALL(nr, nm)=zigsyscall nm nr",
|
||||
"arch/arm64/include/uapi/asm/unistd.h",
|
||||
};
|
||||
|
||||
|
|
@ -277,44 +300,38 @@ pub fn main() !void {
|
|||
};
|
||||
|
||||
var lines = mem.tokenizeScalar(u8, defines, '\n');
|
||||
loop: while (lines.next()) |line| {
|
||||
var fields = mem.tokenizeAny(u8, line, " \t");
|
||||
const cmd = fields.next() orelse return error.Incomplete;
|
||||
if (!mem.eql(u8, cmd, "#define")) continue;
|
||||
const define = fields.next() orelse return error.Incomplete;
|
||||
const number = fields.next() orelse continue;
|
||||
while (lines.next()) |line| {
|
||||
var fields = mem.tokenizeAny(u8, line, " ");
|
||||
const prefix = fields.next() orelse return error.Incomplete;
|
||||
|
||||
if (!std.ascii.isDigit(number[0])) continue;
|
||||
if (!mem.startsWith(u8, define, "__NR")) continue;
|
||||
const name = mem.trimLeft(u8, mem.trimLeft(u8, define, "__NR3264_"), "__NR_");
|
||||
if (mem.eql(u8, name, "arch_specific_syscall")) continue;
|
||||
if (mem.eql(u8, name, "syscalls")) break :loop;
|
||||
if (!mem.eql(u8, prefix, "zigsyscall")) continue;
|
||||
|
||||
const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
|
||||
try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
|
||||
const sys_name = fields.next() orelse return error.Incomplete;
|
||||
const value = fields.rest();
|
||||
const name = (getOverridenNameNew(value) orelse sys_name)["sys_".len..];
|
||||
const fixed_name = if (stdlib_renames_new.get(name)) |f| f else if (stdlib_renames.get(name)) |f| f else name;
|
||||
|
||||
try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), value });
|
||||
}
|
||||
|
||||
try writer.writeAll("};\n\n");
|
||||
}
|
||||
{
|
||||
try writer.writeAll(
|
||||
\\pub const RiscV64 = enum(usize) {
|
||||
\\ pub const arch_specific_syscall = 244;
|
||||
\\
|
||||
\\
|
||||
);
|
||||
try writer.writeAll("pub const RiscV32 = enum(usize) {\n");
|
||||
|
||||
const child_args = [_][]const u8{
|
||||
zig_exe,
|
||||
"cc",
|
||||
"-target",
|
||||
"riscv64-linux-gnu",
|
||||
"riscv32-linux-gnuilp32",
|
||||
"-E",
|
||||
"-dD",
|
||||
"-P",
|
||||
"-nostdinc",
|
||||
"-Iinclude",
|
||||
"-Iinclude/uapi",
|
||||
"-Iarch/riscv/include/uapi",
|
||||
"-D __SYSCALL(nr, nm)=zigsyscall nm nr",
|
||||
"arch/riscv/include/uapi/asm/unistd.h",
|
||||
};
|
||||
|
||||
|
|
@ -338,29 +355,76 @@ pub fn main() !void {
|
|||
};
|
||||
|
||||
var lines = mem.tokenizeScalar(u8, defines, '\n');
|
||||
loop: while (lines.next()) |line| {
|
||||
var fields = mem.tokenizeAny(u8, line, " \t");
|
||||
const cmd = fields.next() orelse return error.Incomplete;
|
||||
if (!mem.eql(u8, cmd, "#define")) continue;
|
||||
const define = fields.next() orelse return error.Incomplete;
|
||||
const number = fields.next() orelse continue;
|
||||
while (lines.next()) |line| {
|
||||
var fields = mem.tokenizeAny(u8, line, " ");
|
||||
const prefix = fields.next() orelse return error.Incomplete;
|
||||
|
||||
if (!std.ascii.isDigit(number[0])) continue;
|
||||
if (!mem.startsWith(u8, define, "__NR")) continue;
|
||||
const name = mem.trimLeft(u8, mem.trimLeft(u8, define, "__NR3264_"), "__NR_");
|
||||
if (mem.eql(u8, name, "arch_specific_syscall")) continue;
|
||||
if (mem.eql(u8, name, "syscalls")) break :loop;
|
||||
if (!mem.eql(u8, prefix, "zigsyscall")) continue;
|
||||
|
||||
const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
|
||||
try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
|
||||
const sys_name = fields.next() orelse return error.Incomplete;
|
||||
const value = fields.rest();
|
||||
const name = (getOverridenNameNew(value) orelse sys_name)["sys_".len..];
|
||||
const fixed_name = if (stdlib_renames_new.get(name)) |f| f else if (stdlib_renames.get(name)) |f| f else name;
|
||||
|
||||
try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), value });
|
||||
}
|
||||
|
||||
try writer.writeAll(
|
||||
\\
|
||||
\\ riscv_flush_icache = arch_specific_syscall + 15,
|
||||
\\};
|
||||
\\
|
||||
);
|
||||
try writer.writeAll("};\n\n");
|
||||
}
|
||||
{
|
||||
try writer.writeAll("pub const RiscV64 = enum(usize) {\n");
|
||||
|
||||
const child_args = [_][]const u8{
|
||||
zig_exe,
|
||||
"cc",
|
||||
"-target",
|
||||
"riscv64-linux-gnu",
|
||||
"-E",
|
||||
"-dD",
|
||||
"-P",
|
||||
"-nostdinc",
|
||||
"-Iinclude",
|
||||
"-Iinclude/uapi",
|
||||
"-Iarch/riscv/include/uapi",
|
||||
"-D __SYSCALL(nr, nm)=zigsyscall nm nr",
|
||||
"arch/riscv/include/uapi/asm/unistd.h",
|
||||
};
|
||||
|
||||
const child_result = try std.process.Child.run(.{
|
||||
.allocator = allocator,
|
||||
.argv = &child_args,
|
||||
.cwd = linux_path,
|
||||
.cwd_dir = linux_dir,
|
||||
});
|
||||
if (child_result.stderr.len > 0) std.debug.print("{s}\n", .{child_result.stderr});
|
||||
|
||||
const defines = switch (child_result.term) {
|
||||
.Exited => |code| if (code == 0) child_result.stdout else {
|
||||
std.debug.print("zig cc exited with code {d}\n", .{code});
|
||||
std.process.exit(1);
|
||||
},
|
||||
else => {
|
||||
std.debug.print("zig cc crashed\n", .{});
|
||||
std.process.exit(1);
|
||||
},
|
||||
};
|
||||
|
||||
var lines = mem.tokenizeScalar(u8, defines, '\n');
|
||||
while (lines.next()) |line| {
|
||||
var fields = mem.tokenizeAny(u8, line, " ");
|
||||
const prefix = fields.next() orelse return error.Incomplete;
|
||||
|
||||
if (!mem.eql(u8, prefix, "zigsyscall")) continue;
|
||||
|
||||
const sys_name = fields.next() orelse return error.Incomplete;
|
||||
const value = fields.rest();
|
||||
const name = (getOverridenNameNew(value) orelse sys_name)["sys_".len..];
|
||||
const fixed_name = if (stdlib_renames_new.get(name)) |f| f else if (stdlib_renames.get(name)) |f| f else name;
|
||||
|
||||
try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), value });
|
||||
}
|
||||
|
||||
try writer.writeAll("};\n\n");
|
||||
}
|
||||
{
|
||||
try writer.writeAll(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue