Skip to content

Commit

Permalink
std.os.linux: Move clone() here and stop exporting it.
Browse files Browse the repository at this point in the history
  • Loading branch information
alexrp committed Aug 1, 2024
1 parent 624fa85 commit 4098f26
Show file tree
Hide file tree
Showing 13 changed files with 414 additions and 441 deletions.
402 changes: 0 additions & 402 deletions lib/c.zig

Large diffs are not rendered by default.

22 changes: 21 additions & 1 deletion lib/std/os/linux.zig
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,27 @@ pub const socketcall = syscall_bits.socketcall;
pub const syscall_pipe = syscall_bits.syscall_pipe;
pub const syscall_fork = syscall_bits.syscall_fork;

pub fn clone(
func: *const fn (arg: usize) callconv(.C) u8,
stack: usize,
flags: u32,
arg: usize,
ptid: *i32,
tls_: usize,
ctid: *i32,
) usize {
// Can't directly call a naked function; cast to C calling convention first.
return @as(*const fn (
*const fn (arg: usize) callconv(.C) u8,
usize,
u32,
usize,
*i32,
usize,
*i32,
) callconv(.C) usize, @ptrCast(&syscall_bits.clone))(func, stack, flags, arg, ptid, tls_, ctid);
}

pub const ARCH = arch_bits.ARCH;
pub const Elf_Symndx = arch_bits.Elf_Symndx;
pub const F = arch_bits.F;
Expand All @@ -78,7 +99,6 @@ pub const Stat = arch_bits.Stat;
pub const VDSO = arch_bits.VDSO;
pub const blkcnt_t = arch_bits.blkcnt_t;
pub const blksize_t = arch_bits.blksize_t;
pub const clone = arch_bits.clone;
pub const dev_t = arch_bits.dev_t;
pub const ino_t = arch_bits.ino_t;
pub const mcontext_t = arch_bits.mcontext_t;
Expand Down
34 changes: 30 additions & 4 deletions lib/std/os/linux/arm-eabi.zig
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,36 @@ pub fn syscall6(
);
}

const CloneFn = *const fn (arg: usize) callconv(.C) u8;

/// This matches the libc clone function.
pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
pub fn clone() callconv(.Naked) usize {
// __clone(func, stack, flags, arg, ptid, tls, ctid)
// r0, r1, r2, r3, +0, +4, +8
//
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
// r7 r0, r1, r2, r3, r4
asm volatile (
\\ stmfd sp!,{r4,r5,r6,r7}
\\ mov r7,#120 # SYS_clone
\\ mov r6,r3
\\ mov r5,r0
\\ mov r0,r2
\\ and r1,r1,#-16
\\ ldr r2,[sp,#16]
\\ ldr r3,[sp,#20]
\\ ldr r4,[sp,#24]
\\ svc 0
\\ tst r0,r0
\\ beq 1f
\\ ldmfd sp!,{r4,r5,r6,r7}
\\ bx lr
\\
\\1: mov r0,r6
\\ bl 3f
\\2: mov r7,#1 # SYS_exit
\\ svc 0
\\ b 2b
\\3: bx r5
);
}

pub fn restore() callconv(.Naked) noreturn {
switch (@import("builtin").zig_backend) {
Expand Down
33 changes: 29 additions & 4 deletions lib/std/os/linux/arm64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,35 @@ pub fn syscall6(
);
}

const CloneFn = *const fn (arg: usize) callconv(.C) u8;

/// This matches the libc clone function.
pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
pub fn clone() callconv(.Naked) usize {
// __clone(func, stack, flags, arg, ptid, tls, ctid)
// x0, x1, w2, x3, x4, x5, x6
//
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
// x8, x0, x1, x2, x3, x4
asm volatile (
\\ // align stack and save func,arg
\\ and x1,x1,#-16
\\ stp x0,x3,[x1,#-16]!
\\
\\ // syscall
\\ uxtw x0,w2
\\ mov x2,x4
\\ mov x3,x5
\\ mov x4,x6
\\ mov x8,#220 // SYS_clone
\\ svc #0
\\
\\ cbz x0,1f
\\ // parent
\\ ret
\\ // child
\\1: ldp x1,x0,[sp],#16
\\ blr x1
\\ mov x8,#93 // SYS_exit
\\ svc #0
);
}

pub const restore = restore_rt;

Expand Down
46 changes: 42 additions & 4 deletions lib/std/os/linux/mips.zig
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,48 @@ pub fn syscall7(
);
}

const CloneFn = *const fn (arg: usize) callconv(.C) u8;

/// This matches the libc clone function.
pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
pub fn clone() callconv(.Naked) usize {
// __clone(func, stack, flags, arg, ptid, tls, ctid)
// 3, 4, 5, 6, 7, 8, 9
//
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
// 2 4, 5, 6, 7, 8
asm volatile (
\\ # Save function pointer and argument pointer on new thread stack
\\ and $5, $5, -8
\\ subu $5, $5, 16
\\ sw $4, 0($5)
\\ sw $7, 4($5)
\\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid)
\\ move $4, $6
\\ lw $6, 16($sp)
\\ lw $7, 20($sp)
\\ lw $9, 24($sp)
\\ subu $sp, $sp, 16
\\ sw $9, 16($sp)
\\ li $2, 4120 # SYS_clone
\\ syscall
\\ beq $7, $0, 1f
\\ nop
\\ addu $sp, $sp, 16
\\ jr $ra
\\ subu $2, $0, $2
\\1:
\\ beq $2, $0, 1f
\\ nop
\\ addu $sp, $sp, 16
\\ jr $ra
\\ nop
\\1:
\\ lw $25, 0($sp)
\\ lw $4, 4($sp)
\\ jalr $25
\\ nop
\\ move $4, $2
\\ li $2, 4001 # SYS_exit
\\ syscall
);
}

pub fn restore() callconv(.Naked) noreturn {
asm volatile (
Expand Down
69 changes: 65 additions & 4 deletions lib/std/os/linux/powerpc.zig
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,71 @@ pub fn syscall6(
);
}

const CloneFn = *const fn (arg: usize) callconv(.C) u8;

/// This matches the libc clone function.
pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
pub fn clone() callconv(.Naked) usize {
// __clone(func, stack, flags, arg, ptid, tls, ctid)
// 3, 4, 5, 6, 7, 8, 9
//
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
// 0 3, 4, 5, 6, 7
asm volatile (
\\ # store non-volatile regs r30, r31 on stack in order to put our
\\ # start func and its arg there
\\ stwu 30, -16(1)
\\ stw 31, 4(1)
\\
\\ # save r3 (func) into r30, and r6(arg) into r31
\\ mr 30, 3
\\ mr 31, 6
\\
\\ # create initial stack frame for new thread
\\ clrrwi 4, 4, 4
\\ li 0, 0
\\ stwu 0, -16(4)
\\
\\ #move c into first arg
\\ mr 3, 5
\\ #mr 4, 4
\\ mr 5, 7
\\ mr 6, 8
\\ mr 7, 9
\\
\\ # move syscall number into r0
\\ li 0, 120 # SYS_clone
\\
\\ sc
\\
\\ # check for syscall error
\\ bns+ 1f # jump to label 1 if no summary overflow.
\\ #else
\\ neg 3, 3 #negate the result (errno)
\\ 1:
\\ # compare sc result with 0
\\ cmpwi cr7, 3, 0
\\
\\ # if not 0, jump to end
\\ bne cr7, 2f
\\
\\ #else: we're the child
\\ #call funcptr: move arg (d) into r3
\\ mr 3, 31
\\ #move r30 (funcptr) into CTR reg
\\ mtctr 30
\\ # call CTR reg
\\ bctrl
\\ # mov SYS_exit into r0 (the exit param is already in r3)
\\ li 0, 1
\\ sc
\\
\\ 2:
\\
\\ # restore stack
\\ lwz 30, 0(1)
\\ lwz 31, 4(1)
\\ addi 1, 1, 16
\\
\\ blr
);
}

pub const restore = restore_rt;

Expand Down
49 changes: 45 additions & 4 deletions lib/std/os/linux/powerpc64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,51 @@ pub fn syscall6(
);
}

const CloneFn = *const fn (arg: usize) callconv(.C) u8;

/// This matches the libc clone function.
pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
pub fn clone() callconv(.Naked) usize {
// __clone(func, stack, flags, arg, ptid, tls, ctid)
// 3, 4, 5, 6, 7, 8, 9
//
// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
// 0 3, 4, 5, 6, 7
asm volatile (
\\ # create initial stack frame for new thread
\\ clrrdi 4, 4, 4
\\ li 0, 0
\\ stdu 0,-32(4)
\\
\\ # save fn and arg to child stack
\\ std 3, 8(4)
\\ std 6, 16(4)
\\
\\ # shuffle args into correct registers and call SYS_clone
\\ mr 3, 5
\\ #mr 4, 4
\\ mr 5, 7
\\ mr 6, 8
\\ mr 7, 9
\\ li 0, 120 # SYS_clone = 120
\\ sc
\\
\\ # if error, negate return (errno)
\\ bns+ 1f
\\ neg 3, 3
\\
\\1:
\\ # if we're the parent, return
\\ cmpwi cr7, 3, 0
\\ bnelr cr7
\\
\\ # we're the child. call fn(arg)
\\ ld 3, 16(1)
\\ ld 12, 8(1)
\\ mtctr 12
\\ bctrl
\\
\\ # call SYS_exit. exit code is already in r3 from fn return value
\\ li 0, 1 # SYS_exit = 1
\\ sc
);
}

pub const restore = restore_rt;

Expand Down
37 changes: 34 additions & 3 deletions lib/std/os/linux/riscv32.zig
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,40 @@ pub fn syscall6(
);
}

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 fn clone() callconv(.Naked) usize {
// __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
);
}

pub const restore = restore_rt;

Expand Down
37 changes: 34 additions & 3 deletions lib/std/os/linux/riscv64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,40 @@ pub fn syscall6(
);
}

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 fn clone() callconv(.Naked) usize {
// __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, -16
\\ sd a0, 0(a1)
\\ sd a3, 8(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: ld a1, 0(sp)
\\ ld a0, 8(sp)
\\ jalr a1
\\
\\ # Exit
\\ li a7, 93 # SYS_exit
\\ ecall
);
}

pub const restore = restore_rt;

Expand Down
Loading

0 comments on commit 4098f26

Please sign in to comment.