| author | |
| committer | |
| log | f9f894200891c8af6ce3a3ad222cd0bf1ee15587 |
| tree | 098010c79f4246d7a7bb15b7ca24809bfa6c6b32 |
| parent | 75f78bfb77d62ee3e143cb7718a21f492a0d4fa6 |
13 files changed, 414 insertions(+), 441 deletions(-)
lib/c.zig-402| ... | @@ -29,10 +29,6 @@ comptime { | ... | @@ -29,10 +29,6 @@ comptime { |
| 29 | @export(wasm_start, .{ .name = "_start", .linkage = .strong }); | 29 | @export(wasm_start, .{ .name = "_start", .linkage = .strong }); |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | if (native_os == .linux) { | ||
| 33 | @export(clone, .{ .name = "clone" }); | ||
| 34 | } | ||
| 35 | |||
| 36 | if (builtin.link_libc) { | 32 | if (builtin.link_libc) { |
| 37 | @export(strcmp, .{ .name = "strcmp", .linkage = .strong }); | 33 | @export(strcmp, .{ .name = "strcmp", .linkage = .strong }); |
| 38 | @export(strncmp, .{ .name = "strncmp", .linkage = .strong }); | 34 | @export(strncmp, .{ .name = "strncmp", .linkage = .strong }); |
| ... | @@ -188,401 +184,3 @@ test "strncmp" { | ... | @@ -188,401 +184,3 @@ test "strncmp" { |
| 188 | try std.testing.expect(strncmp("b", "a", 1) > 0); | 184 | try std.testing.expect(strncmp("b", "a", 1) > 0); |
| 189 | try std.testing.expect(strncmp("\xff", "\x02", 1) > 0); | 185 | try std.testing.expect(strncmp("\xff", "\x02", 1) > 0); |
| 190 | } | 186 | } |
| 191 | |||
| 192 | // TODO we should be able to put this directly in std/linux/x86_64.zig but | ||
| 193 | // it causes a segfault in release mode. this is a workaround of calling it | ||
| 194 | // across .o file boundaries. fix comptime @ptrCast of nakedcc functions. | ||
| 195 | fn clone() callconv(.Naked) void { | ||
| 196 | switch (native_arch) { | ||
| 197 | .x86 => { | ||
| 198 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | ||
| 199 | // +8, +12, +16, +20, +24, +28, +32 | ||
| 200 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 201 | // eax, ebx, ecx, edx, esi, edi | ||
| 202 | asm volatile ( | ||
| 203 | \\ pushl %%ebp | ||
| 204 | \\ movl %%esp,%%ebp | ||
| 205 | \\ pushl %%ebx | ||
| 206 | \\ pushl %%esi | ||
| 207 | \\ pushl %%edi | ||
| 208 | \\ // Setup the arguments | ||
| 209 | \\ movl 16(%%ebp),%%ebx | ||
| 210 | \\ movl 12(%%ebp),%%ecx | ||
| 211 | \\ andl $-16,%%ecx | ||
| 212 | \\ subl $20,%%ecx | ||
| 213 | \\ movl 20(%%ebp),%%eax | ||
| 214 | \\ movl %%eax,4(%%ecx) | ||
| 215 | \\ movl 8(%%ebp),%%eax | ||
| 216 | \\ movl %%eax,0(%%ecx) | ||
| 217 | \\ movl 24(%%ebp),%%edx | ||
| 218 | \\ movl 28(%%ebp),%%esi | ||
| 219 | \\ movl 32(%%ebp),%%edi | ||
| 220 | \\ movl $120,%%eax | ||
| 221 | \\ int $128 | ||
| 222 | \\ testl %%eax,%%eax | ||
| 223 | \\ jnz 1f | ||
| 224 | \\ popl %%eax | ||
| 225 | \\ xorl %%ebp,%%ebp | ||
| 226 | \\ calll *%%eax | ||
| 227 | \\ movl %%eax,%%ebx | ||
| 228 | \\ movl $1,%%eax | ||
| 229 | \\ int $128 | ||
| 230 | \\1: | ||
| 231 | \\ popl %%edi | ||
| 232 | \\ popl %%esi | ||
| 233 | \\ popl %%ebx | ||
| 234 | \\ popl %%ebp | ||
| 235 | \\ retl | ||
| 236 | ); | ||
| 237 | }, | ||
| 238 | .x86_64 => { | ||
| 239 | asm volatile ( | ||
| 240 | \\ movl $56,%%eax // SYS_clone | ||
| 241 | \\ movq %%rdi,%%r11 | ||
| 242 | \\ movq %%rdx,%%rdi | ||
| 243 | \\ movq %%r8,%%rdx | ||
| 244 | \\ movq %%r9,%%r8 | ||
| 245 | \\ movq 8(%%rsp),%%r10 | ||
| 246 | \\ movq %%r11,%%r9 | ||
| 247 | \\ andq $-16,%%rsi | ||
| 248 | \\ subq $8,%%rsi | ||
| 249 | \\ movq %%rcx,(%%rsi) | ||
| 250 | \\ syscall | ||
| 251 | \\ testq %%rax,%%rax | ||
| 252 | \\ jnz 1f | ||
| 253 | \\ xorl %%ebp,%%ebp | ||
| 254 | \\ popq %%rdi | ||
| 255 | \\ callq *%%r9 | ||
| 256 | \\ movl %%eax,%%edi | ||
| 257 | \\ movl $60,%%eax // SYS_exit | ||
| 258 | \\ syscall | ||
| 259 | \\1: ret | ||
| 260 | \\ | ||
| 261 | ); | ||
| 262 | }, | ||
| 263 | .aarch64, .aarch64_be => { | ||
| 264 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | ||
| 265 | // x0, x1, w2, x3, x4, x5, x6 | ||
| 266 | |||
| 267 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 268 | // x8, x0, x1, x2, x3, x4 | ||
| 269 | asm volatile ( | ||
| 270 | \\ // align stack and save func,arg | ||
| 271 | \\ and x1,x1,#-16 | ||
| 272 | \\ stp x0,x3,[x1,#-16]! | ||
| 273 | \\ | ||
| 274 | \\ // syscall | ||
| 275 | \\ uxtw x0,w2 | ||
| 276 | \\ mov x2,x4 | ||
| 277 | \\ mov x3,x5 | ||
| 278 | \\ mov x4,x6 | ||
| 279 | \\ mov x8,#220 // SYS_clone | ||
| 280 | \\ svc #0 | ||
| 281 | \\ | ||
| 282 | \\ cbz x0,1f | ||
| 283 | \\ // parent | ||
| 284 | \\ ret | ||
| 285 | \\ // child | ||
| 286 | \\1: ldp x1,x0,[sp],#16 | ||
| 287 | \\ blr x1 | ||
| 288 | \\ mov x8,#93 // SYS_exit | ||
| 289 | \\ svc #0 | ||
| 290 | ); | ||
| 291 | }, | ||
| 292 | .arm, .armeb, .thumb, .thumbeb => { | ||
| 293 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | ||
| 294 | // r0, r1, r2, r3, +0, +4, +8 | ||
| 295 | |||
| 296 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 297 | // r7 r0, r1, r2, r3, r4 | ||
| 298 | asm volatile ( | ||
| 299 | \\ stmfd sp!,{r4,r5,r6,r7} | ||
| 300 | \\ mov r7,#120 | ||
| 301 | \\ mov r6,r3 | ||
| 302 | \\ mov r5,r0 | ||
| 303 | \\ mov r0,r2 | ||
| 304 | \\ and r1,r1,#-16 | ||
| 305 | \\ ldr r2,[sp,#16] | ||
| 306 | \\ ldr r3,[sp,#20] | ||
| 307 | \\ ldr r4,[sp,#24] | ||
| 308 | \\ svc 0 | ||
| 309 | \\ tst r0,r0 | ||
| 310 | \\ beq 1f | ||
| 311 | \\ ldmfd sp!,{r4,r5,r6,r7} | ||
| 312 | \\ bx lr | ||
| 313 | \\ | ||
| 314 | \\1: mov r0,r6 | ||
| 315 | \\ bl 3f | ||
| 316 | \\2: mov r7,#1 | ||
| 317 | \\ svc 0 | ||
| 318 | \\ b 2b | ||
| 319 | \\3: bx r5 | ||
| 320 | ); | ||
| 321 | }, | ||
| 322 | .riscv32 => { | ||
| 323 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | ||
| 324 | // a0, a1, a2, a3, a4, a5, a6 | ||
| 325 | |||
| 326 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 327 | // a7 a0, a1, a2, a3, a4 | ||
| 328 | asm volatile ( | ||
| 329 | \\ # Save func and arg to stack | ||
| 330 | \\ addi a1, a1, -8 | ||
| 331 | \\ sw a0, 0(a1) | ||
| 332 | \\ sw a3, 4(a1) | ||
| 333 | \\ | ||
| 334 | \\ # Call SYS_clone | ||
| 335 | \\ mv a0, a2 | ||
| 336 | \\ mv a2, a4 | ||
| 337 | \\ mv a3, a5 | ||
| 338 | \\ mv a4, a6 | ||
| 339 | \\ li a7, 220 # SYS_clone | ||
| 340 | \\ ecall | ||
| 341 | \\ | ||
| 342 | \\ beqz a0, 1f | ||
| 343 | \\ # Parent | ||
| 344 | \\ ret | ||
| 345 | \\ | ||
| 346 | \\ # Child | ||
| 347 | \\1: lw a1, 0(sp) | ||
| 348 | \\ lw a0, 4(sp) | ||
| 349 | \\ jalr a1 | ||
| 350 | \\ | ||
| 351 | \\ # Exit | ||
| 352 | \\ li a7, 93 # SYS_exit | ||
| 353 | \\ ecall | ||
| 354 | ); | ||
| 355 | }, | ||
| 356 | .riscv64 => { | ||
| 357 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | ||
| 358 | // a0, a1, a2, a3, a4, a5, a6 | ||
| 359 | |||
| 360 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 361 | // a7 a0, a1, a2, a3, a4 | ||
| 362 | asm volatile ( | ||
| 363 | \\ # Save func and arg to stack | ||
| 364 | \\ addi a1, a1, -16 | ||
| 365 | \\ sd a0, 0(a1) | ||
| 366 | \\ sd a3, 8(a1) | ||
| 367 | \\ | ||
| 368 | \\ # Call SYS_clone | ||
| 369 | \\ mv a0, a2 | ||
| 370 | \\ mv a2, a4 | ||
| 371 | \\ mv a3, a5 | ||
| 372 | \\ mv a4, a6 | ||
| 373 | \\ li a7, 220 # SYS_clone | ||
| 374 | \\ ecall | ||
| 375 | \\ | ||
| 376 | \\ beqz a0, 1f | ||
| 377 | \\ # Parent | ||
| 378 | \\ ret | ||
| 379 | \\ | ||
| 380 | \\ # Child | ||
| 381 | \\1: ld a1, 0(sp) | ||
| 382 | \\ ld a0, 8(sp) | ||
| 383 | \\ jalr a1 | ||
| 384 | \\ | ||
| 385 | \\ # Exit | ||
| 386 | \\ li a7, 93 # SYS_exit | ||
| 387 | \\ ecall | ||
| 388 | ); | ||
| 389 | }, | ||
| 390 | .mips, .mipsel, .mips64, .mips64el => { | ||
| 391 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | ||
| 392 | // 3, 4, 5, 6, 7, 8, 9 | ||
| 393 | |||
| 394 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 395 | // 2 4, 5, 6, 7, 8 | ||
| 396 | asm volatile ( | ||
| 397 | \\ # Save function pointer and argument pointer on new thread stack | ||
| 398 | \\ and $5, $5, -8 | ||
| 399 | \\ subu $5, $5, 16 | ||
| 400 | \\ sw $4, 0($5) | ||
| 401 | \\ sw $7, 4($5) | ||
| 402 | \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid) | ||
| 403 | \\ move $4, $6 | ||
| 404 | \\ lw $6, 16($sp) | ||
| 405 | \\ lw $7, 20($sp) | ||
| 406 | \\ lw $9, 24($sp) | ||
| 407 | \\ subu $sp, $sp, 16 | ||
| 408 | \\ sw $9, 16($sp) | ||
| 409 | \\ li $2, 4120 | ||
| 410 | \\ syscall | ||
| 411 | \\ beq $7, $0, 1f | ||
| 412 | \\ nop | ||
| 413 | \\ addu $sp, $sp, 16 | ||
| 414 | \\ jr $ra | ||
| 415 | \\ subu $2, $0, $2 | ||
| 416 | \\1: | ||
| 417 | \\ beq $2, $0, 1f | ||
| 418 | \\ nop | ||
| 419 | \\ addu $sp, $sp, 16 | ||
| 420 | \\ jr $ra | ||
| 421 | \\ nop | ||
| 422 | \\1: | ||
| 423 | \\ lw $25, 0($sp) | ||
| 424 | \\ lw $4, 4($sp) | ||
| 425 | \\ jalr $25 | ||
| 426 | \\ nop | ||
| 427 | \\ move $4, $2 | ||
| 428 | \\ li $2, 4001 | ||
| 429 | \\ syscall | ||
| 430 | ); | ||
| 431 | }, | ||
| 432 | .powerpc, .powerpcle => { | ||
| 433 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | ||
| 434 | // 3, 4, 5, 6, 7, 8, 9 | ||
| 435 | |||
| 436 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 437 | // 0 3, 4, 5, 6, 7 | ||
| 438 | asm volatile ( | ||
| 439 | \\ # store non-volatile regs r30, r31 on stack in order to put our | ||
| 440 | \\ # start func and its arg there | ||
| 441 | \\ stwu 30, -16(1) | ||
| 442 | \\ stw 31, 4(1) | ||
| 443 | \\ | ||
| 444 | \\ # save r3 (func) into r30, and r6(arg) into r31 | ||
| 445 | \\ mr 30, 3 | ||
| 446 | \\ mr 31, 6 | ||
| 447 | \\ | ||
| 448 | \\ # create initial stack frame for new thread | ||
| 449 | \\ clrrwi 4, 4, 4 | ||
| 450 | \\ li 0, 0 | ||
| 451 | \\ stwu 0, -16(4) | ||
| 452 | \\ | ||
| 453 | \\ #move c into first arg | ||
| 454 | \\ mr 3, 5 | ||
| 455 | \\ #mr 4, 4 | ||
| 456 | \\ mr 5, 7 | ||
| 457 | \\ mr 6, 8 | ||
| 458 | \\ mr 7, 9 | ||
| 459 | \\ | ||
| 460 | \\ # move syscall number into r0 | ||
| 461 | \\ li 0, 120 | ||
| 462 | \\ | ||
| 463 | \\ sc | ||
| 464 | \\ | ||
| 465 | \\ # check for syscall error | ||
| 466 | \\ bns+ 1f # jump to label 1 if no summary overflow. | ||
| 467 | \\ #else | ||
| 468 | \\ neg 3, 3 #negate the result (errno) | ||
| 469 | \\ 1: | ||
| 470 | \\ # compare sc result with 0 | ||
| 471 | \\ cmpwi cr7, 3, 0 | ||
| 472 | \\ | ||
| 473 | \\ # if not 0, jump to end | ||
| 474 | \\ bne cr7, 2f | ||
| 475 | \\ | ||
| 476 | \\ #else: we're the child | ||
| 477 | \\ #call funcptr: move arg (d) into r3 | ||
| 478 | \\ mr 3, 31 | ||
| 479 | \\ #move r30 (funcptr) into CTR reg | ||
| 480 | \\ mtctr 30 | ||
| 481 | \\ # call CTR reg | ||
| 482 | \\ bctrl | ||
| 483 | \\ # mov SYS_exit into r0 (the exit param is already in r3) | ||
| 484 | \\ li 0, 1 | ||
| 485 | \\ sc | ||
| 486 | \\ | ||
| 487 | \\ 2: | ||
| 488 | \\ | ||
| 489 | \\ # restore stack | ||
| 490 | \\ lwz 30, 0(1) | ||
| 491 | \\ lwz 31, 4(1) | ||
| 492 | \\ addi 1, 1, 16 | ||
| 493 | \\ | ||
| 494 | \\ blr | ||
| 495 | ); | ||
| 496 | }, | ||
| 497 | .powerpc64, .powerpc64le => { | ||
| 498 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | ||
| 499 | // 3, 4, 5, 6, 7, 8, 9 | ||
| 500 | |||
| 501 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 502 | // 0 3, 4, 5, 6, 7 | ||
| 503 | asm volatile ( | ||
| 504 | \\ # create initial stack frame for new thread | ||
| 505 | \\ clrrdi 4, 4, 4 | ||
| 506 | \\ li 0, 0 | ||
| 507 | \\ stdu 0,-32(4) | ||
| 508 | \\ | ||
| 509 | \\ # save fn and arg to child stack | ||
| 510 | \\ std 3, 8(4) | ||
| 511 | \\ std 6, 16(4) | ||
| 512 | \\ | ||
| 513 | \\ # shuffle args into correct registers and call SYS_clone | ||
| 514 | \\ mr 3, 5 | ||
| 515 | \\ #mr 4, 4 | ||
| 516 | \\ mr 5, 7 | ||
| 517 | \\ mr 6, 8 | ||
| 518 | \\ mr 7, 9 | ||
| 519 | \\ li 0, 120 # SYS_clone = 120 | ||
| 520 | \\ sc | ||
| 521 | \\ | ||
| 522 | \\ # if error, negate return (errno) | ||
| 523 | \\ bns+ 1f | ||
| 524 | \\ neg 3, 3 | ||
| 525 | \\ | ||
| 526 | \\1: | ||
| 527 | \\ # if we're the parent, return | ||
| 528 | \\ cmpwi cr7, 3, 0 | ||
| 529 | \\ bnelr cr7 | ||
| 530 | \\ | ||
| 531 | \\ # we're the child. call fn(arg) | ||
| 532 | \\ ld 3, 16(1) | ||
| 533 | \\ ld 12, 8(1) | ||
| 534 | \\ mtctr 12 | ||
| 535 | \\ bctrl | ||
| 536 | \\ | ||
| 537 | \\ # call SYS_exit. exit code is already in r3 from fn return value | ||
| 538 | \\ li 0, 1 # SYS_exit = 1 | ||
| 539 | \\ sc | ||
| 540 | ); | ||
| 541 | }, | ||
| 542 | .sparc64 => { | ||
| 543 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | ||
| 544 | // i0, i1, i2, i3, i4, i5, sp | ||
| 545 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 546 | // g1 o0, o1, o2, o3, o4 | ||
| 547 | asm volatile ( | ||
| 548 | \\ save %%sp, -192, %%sp | ||
| 549 | \\ # Save the func pointer and the arg pointer | ||
| 550 | \\ mov %%i0, %%g2 | ||
| 551 | \\ mov %%i3, %%g3 | ||
| 552 | \\ # Shuffle the arguments | ||
| 553 | \\ mov 217, %%g1 | ||
| 554 | \\ mov %%i2, %%o0 | ||
| 555 | \\ # Add some extra space for the initial frame | ||
| 556 | \\ sub %%i1, 176 + 2047, %%o1 | ||
| 557 | \\ mov %%i4, %%o2 | ||
| 558 | \\ mov %%i5, %%o3 | ||
| 559 | \\ ldx [%%fp + 0x8af], %%o4 | ||
| 560 | \\ t 0x6d | ||
| 561 | \\ bcs,pn %%xcc, 2f | ||
| 562 | \\ nop | ||
| 563 | \\ # The child pid is returned in o0 while o1 tells if this | ||
| 564 | \\ # process is # the child (=1) or the parent (=0). | ||
| 565 | \\ brnz %%o1, 1f | ||
| 566 | \\ nop | ||
| 567 | \\ # Parent process, return the child pid | ||
| 568 | \\ mov %%o0, %%i0 | ||
| 569 | \\ ret | ||
| 570 | \\ restore | ||
| 571 | \\1: | ||
| 572 | \\ # Child process, call func(arg) | ||
| 573 | \\ mov %%g0, %%fp | ||
| 574 | \\ call %%g2 | ||
| 575 | \\ mov %%g3, %%o0 | ||
| 576 | \\ # Exit | ||
| 577 | \\ mov 1, %%g1 | ||
| 578 | \\ t 0x6d | ||
| 579 | \\2: | ||
| 580 | \\ # The syscall failed | ||
| 581 | \\ sub %%g0, %%o0, %%i0 | ||
| 582 | \\ ret | ||
| 583 | \\ restore | ||
| 584 | ); | ||
| 585 | }, | ||
| 586 | else => @compileError("Implement clone() for this arch."), | ||
| 587 | } | ||
| 588 | } |
lib/std/os/linux.zig+21-1| ... | @@ -65,6 +65,27 @@ pub const socketcall = syscall_bits.socketcall; | ... | @@ -65,6 +65,27 @@ pub const socketcall = syscall_bits.socketcall; |
| 65 | pub const syscall_pipe = syscall_bits.syscall_pipe; | 65 | pub const syscall_pipe = syscall_bits.syscall_pipe; |
| 66 | pub const syscall_fork = syscall_bits.syscall_fork; | 66 | pub const syscall_fork = syscall_bits.syscall_fork; |
| 67 | 67 | ||
| 68 | pub fn clone( | ||
| 69 | func: *const fn (arg: usize) callconv(.C) u8, | ||
| 70 | stack: usize, | ||
| 71 | flags: u32, | ||
| 72 | arg: usize, | ||
| 73 | ptid: *i32, | ||
| 74 | tp: usize, // aka tls | ||
| 75 | ctid: *i32, | ||
| 76 | ) usize { | ||
| 77 | // Can't directly call a naked function; cast to C calling convention first. | ||
| 78 | return @as(*const fn ( | ||
| 79 | *const fn (arg: usize) callconv(.C) u8, | ||
| 80 | usize, | ||
| 81 | u32, | ||
| 82 | usize, | ||
| 83 | *i32, | ||
| 84 | usize, | ||
| 85 | *i32, | ||
| 86 | ) callconv(.C) usize, @ptrCast(&syscall_bits.clone))(func, stack, flags, arg, ptid, tp, ctid); | ||
| 87 | } | ||
| 88 | |||
| 68 | pub const ARCH = arch_bits.ARCH; | 89 | pub const ARCH = arch_bits.ARCH; |
| 69 | pub const Elf_Symndx = arch_bits.Elf_Symndx; | 90 | pub const Elf_Symndx = arch_bits.Elf_Symndx; |
| 70 | pub const F = arch_bits.F; | 91 | pub const F = arch_bits.F; |
| ... | @@ -77,7 +98,6 @@ pub const Stat = arch_bits.Stat; | ... | @@ -77,7 +98,6 @@ pub const Stat = arch_bits.Stat; |
| 77 | pub const VDSO = arch_bits.VDSO; | 98 | pub const VDSO = arch_bits.VDSO; |
| 78 | pub const blkcnt_t = arch_bits.blkcnt_t; | 99 | pub const blkcnt_t = arch_bits.blkcnt_t; |
| 79 | pub const blksize_t = arch_bits.blksize_t; | 100 | pub const blksize_t = arch_bits.blksize_t; |
| 80 | pub const clone = arch_bits.clone; | ||
| 81 | pub const dev_t = arch_bits.dev_t; | 101 | pub const dev_t = arch_bits.dev_t; |
| 82 | pub const ino_t = arch_bits.ino_t; | 102 | pub const ino_t = arch_bits.ino_t; |
| 83 | pub const mcontext_t = arch_bits.mcontext_t; | 103 | pub const mcontext_t = arch_bits.mcontext_t; |
lib/std/os/linux/arm-eabi.zig+30-4| ... | @@ -98,10 +98,36 @@ pub fn syscall6( | ... | @@ -98,10 +98,36 @@ pub fn syscall6( |
| 98 | ); | 98 | ); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | const CloneFn = *const fn (arg: usize) callconv(.C) u8; | 101 | pub fn clone() callconv(.Naked) usize { |
| 102 | 102 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | |
| 103 | /// This matches the libc clone function. | 103 | // r0, r1, r2, r3, +0, +4, +8 |
| 104 | pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; | 104 | // |
| 105 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 106 | // r7 r0, r1, r2, r3, r4 | ||
| 107 | asm volatile ( | ||
| 108 | \\ stmfd sp!,{r4,r5,r6,r7} | ||
| 109 | \\ mov r7,#120 // SYS_clone | ||
| 110 | \\ mov r6,r3 | ||
| 111 | \\ mov r5,r0 | ||
| 112 | \\ mov r0,r2 | ||
| 113 | \\ and r1,r1,#-16 | ||
| 114 | \\ ldr r2,[sp,#16] | ||
| 115 | \\ ldr r3,[sp,#20] | ||
| 116 | \\ ldr r4,[sp,#24] | ||
| 117 | \\ svc 0 | ||
| 118 | \\ tst r0,r0 | ||
| 119 | \\ beq 1f | ||
| 120 | \\ ldmfd sp!,{r4,r5,r6,r7} | ||
| 121 | \\ bx lr | ||
| 122 | \\ | ||
| 123 | \\1: mov r0,r6 | ||
| 124 | \\ bl 3f | ||
| 125 | \\2: mov r7,#1 // SYS_exit | ||
| 126 | \\ svc 0 | ||
| 127 | \\ b 2b | ||
| 128 | \\3: bx r5 | ||
| 129 | ); | ||
| 130 | } | ||
| 105 | 131 | ||
| 106 | pub fn restore() callconv(.Naked) noreturn { | 132 | pub fn restore() callconv(.Naked) noreturn { |
| 107 | switch (@import("builtin").zig_backend) { | 133 | switch (@import("builtin").zig_backend) { |
lib/std/os/linux/arm64.zig+29-4| ... | @@ -98,10 +98,35 @@ pub fn syscall6( | ... | @@ -98,10 +98,35 @@ pub fn syscall6( |
| 98 | ); | 98 | ); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | const CloneFn = *const fn (arg: usize) callconv(.C) u8; | 101 | pub fn clone() callconv(.Naked) usize { |
| 102 | 102 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | |
| 103 | /// This matches the libc clone function. | 103 | // x0, x1, w2, x3, x4, x5, x6 |
| 104 | pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; | 104 | // |
| 105 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 106 | // x8, x0, x1, x2, x3, x4 | ||
| 107 | asm volatile ( | ||
| 108 | \\ // align stack and save func,arg | ||
| 109 | \\ and x1,x1,#-16 | ||
| 110 | \\ stp x0,x3,[x1,#-16]! | ||
| 111 | \\ | ||
| 112 | \\ // syscall | ||
| 113 | \\ uxtw x0,w2 | ||
| 114 | \\ mov x2,x4 | ||
| 115 | \\ mov x3,x5 | ||
| 116 | \\ mov x4,x6 | ||
| 117 | \\ mov x8,#220 // SYS_clone | ||
| 118 | \\ svc #0 | ||
| 119 | \\ | ||
| 120 | \\ cbz x0,1f | ||
| 121 | \\ // parent | ||
| 122 | \\ ret | ||
| 123 | \\ // child | ||
| 124 | \\1: ldp x1,x0,[sp],#16 | ||
| 125 | \\ blr x1 | ||
| 126 | \\ mov x8,#93 // SYS_exit | ||
| 127 | \\ svc #0 | ||
| 128 | ); | ||
| 129 | } | ||
| 105 | 130 | ||
| 106 | pub const restore = restore_rt; | 131 | pub const restore = restore_rt; |
| 107 | 132 |
lib/std/os/linux/mips.zig+42-4| ... | @@ -190,10 +190,48 @@ pub fn syscall7( | ... | @@ -190,10 +190,48 @@ pub fn syscall7( |
| 190 | ); | 190 | ); |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | const CloneFn = *const fn (arg: usize) callconv(.C) u8; | 193 | pub fn clone() callconv(.Naked) usize { |
| 194 | 194 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | |
| 195 | /// This matches the libc clone function. | 195 | // 3, 4, 5, 6, 7, 8, 9 |
| 196 | pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; | 196 | // |
| 197 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 198 | // 2 4, 5, 6, 7, 8 | ||
| 199 | asm volatile ( | ||
| 200 | \\ # Save function pointer and argument pointer on new thread stack | ||
| 201 | \\ and $5, $5, -8 | ||
| 202 | \\ subu $5, $5, 16 | ||
| 203 | \\ sw $4, 0($5) | ||
| 204 | \\ sw $7, 4($5) | ||
| 205 | \\ # Shuffle (fn,sp,fl,arg,ptid,tls,ctid) to (fl,sp,ptid,tls,ctid) | ||
| 206 | \\ move $4, $6 | ||
| 207 | \\ lw $6, 16($sp) | ||
| 208 | \\ lw $7, 20($sp) | ||
| 209 | \\ lw $9, 24($sp) | ||
| 210 | \\ subu $sp, $sp, 16 | ||
| 211 | \\ sw $9, 16($sp) | ||
| 212 | \\ li $2, 4120 # SYS_clone | ||
| 213 | \\ syscall | ||
| 214 | \\ beq $7, $0, 1f | ||
| 215 | \\ nop | ||
| 216 | \\ addu $sp, $sp, 16 | ||
| 217 | \\ jr $ra | ||
| 218 | \\ subu $2, $0, $2 | ||
| 219 | \\1: | ||
| 220 | \\ beq $2, $0, 1f | ||
| 221 | \\ nop | ||
| 222 | \\ addu $sp, $sp, 16 | ||
| 223 | \\ jr $ra | ||
| 224 | \\ nop | ||
| 225 | \\1: | ||
| 226 | \\ lw $25, 0($sp) | ||
| 227 | \\ lw $4, 4($sp) | ||
| 228 | \\ jalr $25 | ||
| 229 | \\ nop | ||
| 230 | \\ move $4, $2 | ||
| 231 | \\ li $2, 4001 # SYS_exit | ||
| 232 | \\ syscall | ||
| 233 | ); | ||
| 234 | } | ||
| 197 | 235 | ||
| 198 | pub fn restore() callconv(.Naked) noreturn { | 236 | pub fn restore() callconv(.Naked) noreturn { |
| 199 | asm volatile ( | 237 | asm volatile ( |
lib/std/os/linux/powerpc.zig+65-4| ... | @@ -126,10 +126,71 @@ pub fn syscall6( | ... | @@ -126,10 +126,71 @@ pub fn syscall6( |
| 126 | ); | 126 | ); |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | const CloneFn = *const fn (arg: usize) callconv(.C) u8; | 129 | pub fn clone() callconv(.Naked) usize { |
| 130 | 130 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | |
| 131 | /// This matches the libc clone function. | 131 | // 3, 4, 5, 6, 7, 8, 9 |
| 132 | pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; | 132 | // |
| 133 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 134 | // 0 3, 4, 5, 6, 7 | ||
| 135 | asm volatile ( | ||
| 136 | \\ # store non-volatile regs r30, r31 on stack in order to put our | ||
| 137 | \\ # start func and its arg there | ||
| 138 | \\ stwu 30, -16(1) | ||
| 139 | \\ stw 31, 4(1) | ||
| 140 | \\ | ||
| 141 | \\ # save r3 (func) into r30, and r6(arg) into r31 | ||
| 142 | \\ mr 30, 3 | ||
| 143 | \\ mr 31, 6 | ||
| 144 | \\ | ||
| 145 | \\ # create initial stack frame for new thread | ||
| 146 | \\ clrrwi 4, 4, 4 | ||
| 147 | \\ li 0, 0 | ||
| 148 | \\ stwu 0, -16(4) | ||
| 149 | \\ | ||
| 150 | \\ #move c into first arg | ||
| 151 | \\ mr 3, 5 | ||
| 152 | \\ #mr 4, 4 | ||
| 153 | \\ mr 5, 7 | ||
| 154 | \\ mr 6, 8 | ||
| 155 | \\ mr 7, 9 | ||
| 156 | \\ | ||
| 157 | \\ # move syscall number into r0 | ||
| 158 | \\ li 0, 120 # SYS_clone | ||
| 159 | \\ | ||
| 160 | \\ sc | ||
| 161 | \\ | ||
| 162 | \\ # check for syscall error | ||
| 163 | \\ bns+ 1f # jump to label 1 if no summary overflow. | ||
| 164 | \\ #else | ||
| 165 | \\ neg 3, 3 #negate the result (errno) | ||
| 166 | \\ 1: | ||
| 167 | \\ # compare sc result with 0 | ||
| 168 | \\ cmpwi cr7, 3, 0 | ||
| 169 | \\ | ||
| 170 | \\ # if not 0, jump to end | ||
| 171 | \\ bne cr7, 2f | ||
| 172 | \\ | ||
| 173 | \\ #else: we're the child | ||
| 174 | \\ #call funcptr: move arg (d) into r3 | ||
| 175 | \\ mr 3, 31 | ||
| 176 | \\ #move r30 (funcptr) into CTR reg | ||
| 177 | \\ mtctr 30 | ||
| 178 | \\ # call CTR reg | ||
| 179 | \\ bctrl | ||
| 180 | \\ # mov SYS_exit into r0 (the exit param is already in r3) | ||
| 181 | \\ li 0, 1 | ||
| 182 | \\ sc | ||
| 183 | \\ | ||
| 184 | \\ 2: | ||
| 185 | \\ | ||
| 186 | \\ # restore stack | ||
| 187 | \\ lwz 30, 0(1) | ||
| 188 | \\ lwz 31, 4(1) | ||
| 189 | \\ addi 1, 1, 16 | ||
| 190 | \\ | ||
| 191 | \\ blr | ||
| 192 | ); | ||
| 193 | } | ||
| 133 | 194 | ||
| 134 | pub const restore = restore_rt; | 195 | pub const restore = restore_rt; |
| 135 | 196 |
lib/std/os/linux/powerpc64.zig+45-4| ... | @@ -126,10 +126,51 @@ pub fn syscall6( | ... | @@ -126,10 +126,51 @@ pub fn syscall6( |
| 126 | ); | 126 | ); |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | const CloneFn = *const fn (arg: usize) callconv(.C) u8; | 129 | pub fn clone() callconv(.Naked) usize { |
| 130 | 130 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | |
| 131 | /// This matches the libc clone function. | 131 | // 3, 4, 5, 6, 7, 8, 9 |
| 132 | pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; | 132 | // |
| 133 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 134 | // 0 3, 4, 5, 6, 7 | ||
| 135 | asm volatile ( | ||
| 136 | \\ # create initial stack frame for new thread | ||
| 137 | \\ clrrdi 4, 4, 4 | ||
| 138 | \\ li 0, 0 | ||
| 139 | \\ stdu 0,-32(4) | ||
| 140 | \\ | ||
| 141 | \\ # save fn and arg to child stack | ||
| 142 | \\ std 3, 8(4) | ||
| 143 | \\ std 6, 16(4) | ||
| 144 | \\ | ||
| 145 | \\ # shuffle args into correct registers and call SYS_clone | ||
| 146 | \\ mr 3, 5 | ||
| 147 | \\ #mr 4, 4 | ||
| 148 | \\ mr 5, 7 | ||
| 149 | \\ mr 6, 8 | ||
| 150 | \\ mr 7, 9 | ||
| 151 | \\ li 0, 120 # SYS_clone = 120 | ||
| 152 | \\ sc | ||
| 153 | \\ | ||
| 154 | \\ # if error, negate return (errno) | ||
| 155 | \\ bns+ 1f | ||
| 156 | \\ neg 3, 3 | ||
| 157 | \\ | ||
| 158 | \\1: | ||
| 159 | \\ # if we're the parent, return | ||
| 160 | \\ cmpwi cr7, 3, 0 | ||
| 161 | \\ bnelr cr7 | ||
| 162 | \\ | ||
| 163 | \\ # we're the child. call fn(arg) | ||
| 164 | \\ ld 3, 16(1) | ||
| 165 | \\ ld 12, 8(1) | ||
| 166 | \\ mtctr 12 | ||
| 167 | \\ bctrl | ||
| 168 | \\ | ||
| 169 | \\ # call SYS_exit. exit code is already in r3 from fn return value | ||
| 170 | \\ li 0, 1 # SYS_exit = 1 | ||
| 171 | \\ sc | ||
| 172 | ); | ||
| 173 | } | ||
| 133 | 174 | ||
| 134 | pub const restore = restore_rt; | 175 | pub const restore = restore_rt; |
| 135 | 176 |
lib/std/os/linux/riscv32.zig+34-3| ... | @@ -95,9 +95,40 @@ pub fn syscall6( | ... | @@ -95,9 +95,40 @@ pub fn syscall6( |
| 95 | ); | 95 | ); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | const CloneFn = *const fn (arg: usize) callconv(.C) u8; | 98 | pub fn clone() callconv(.Naked) usize { |
| 99 | 99 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | |
| 100 | pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; | 100 | // a0, a1, a2, a3, a4, a5, a6 |
| 101 | // | ||
| 102 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 103 | // a7 a0, a1, a2, a3, a4 | ||
| 104 | asm volatile ( | ||
| 105 | \\ # Save func and arg to stack | ||
| 106 | \\ addi a1, a1, -8 | ||
| 107 | \\ sw a0, 0(a1) | ||
| 108 | \\ sw a3, 4(a1) | ||
| 109 | \\ | ||
| 110 | \\ # Call SYS_clone | ||
| 111 | \\ mv a0, a2 | ||
| 112 | \\ mv a2, a4 | ||
| 113 | \\ mv a3, a5 | ||
| 114 | \\ mv a4, a6 | ||
| 115 | \\ li a7, 220 # SYS_clone | ||
| 116 | \\ ecall | ||
| 117 | \\ | ||
| 118 | \\ beqz a0, 1f | ||
| 119 | \\ # Parent | ||
| 120 | \\ ret | ||
| 121 | \\ | ||
| 122 | \\ # Child | ||
| 123 | \\1: lw a1, 0(sp) | ||
| 124 | \\ lw a0, 4(sp) | ||
| 125 | \\ jalr a1 | ||
| 126 | \\ | ||
| 127 | \\ # Exit | ||
| 128 | \\ li a7, 93 # SYS_exit | ||
| 129 | \\ ecall | ||
| 130 | ); | ||
| 131 | } | ||
| 101 | 132 | ||
| 102 | pub const restore = restore_rt; | 133 | pub const restore = restore_rt; |
| 103 | 134 |
lib/std/os/linux/riscv64.zig+34-3| ... | @@ -95,9 +95,40 @@ pub fn syscall6( | ... | @@ -95,9 +95,40 @@ pub fn syscall6( |
| 95 | ); | 95 | ); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | const CloneFn = *const fn (arg: usize) callconv(.C) u8; | 98 | pub fn clone() callconv(.Naked) usize { |
| 99 | 99 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | |
| 100 | pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; | 100 | // a0, a1, a2, a3, a4, a5, a6 |
| 101 | // | ||
| 102 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 103 | // a7 a0, a1, a2, a3, a4 | ||
| 104 | asm volatile ( | ||
| 105 | \\ # Save func and arg to stack | ||
| 106 | \\ addi a1, a1, -16 | ||
| 107 | \\ sd a0, 0(a1) | ||
| 108 | \\ sd a3, 8(a1) | ||
| 109 | \\ | ||
| 110 | \\ # Call SYS_clone | ||
| 111 | \\ mv a0, a2 | ||
| 112 | \\ mv a2, a4 | ||
| 113 | \\ mv a3, a5 | ||
| 114 | \\ mv a4, a6 | ||
| 115 | \\ li a7, 220 # SYS_clone | ||
| 116 | \\ ecall | ||
| 117 | \\ | ||
| 118 | \\ beqz a0, 1f | ||
| 119 | \\ # Parent | ||
| 120 | \\ ret | ||
| 121 | \\ | ||
| 122 | \\ # Child | ||
| 123 | \\1: ld a1, 0(sp) | ||
| 124 | \\ ld a0, 8(sp) | ||
| 125 | \\ jalr a1 | ||
| 126 | \\ | ||
| 127 | \\ # Exit | ||
| 128 | \\ li a7, 93 # SYS_exit | ||
| 129 | \\ ecall | ||
| 130 | ); | ||
| 131 | } | ||
| 101 | 132 | ||
| 102 | pub const restore = restore_rt; | 133 | pub const restore = restore_rt; |
| 103 | 134 |
lib/std/os/linux/sparc64.zig+45-4| ... | @@ -178,10 +178,51 @@ pub fn syscall6( | ... | @@ -178,10 +178,51 @@ pub fn syscall6( |
| 178 | ); | 178 | ); |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | const CloneFn = *const fn (arg: usize) callconv(.C) u8; | 181 | pub fn clone() callconv(.Naked) usize { |
| 182 | 182 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | |
| 183 | /// This matches the libc clone function. | 183 | // i0, i1, i2, i3, i4, i5, sp |
| 184 | pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; | 184 | // |
| 185 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 186 | // g1 o0, o1, o2, o3, o4 | ||
| 187 | asm volatile ( | ||
| 188 | \\ save %%sp, -192, %%sp | ||
| 189 | \\ # Save the func pointer and the arg pointer | ||
| 190 | \\ mov %%i0, %%g2 | ||
| 191 | \\ mov %%i3, %%g3 | ||
| 192 | \\ # Shuffle the arguments | ||
| 193 | \\ mov 217, %%g1 # SYS_clone | ||
| 194 | \\ mov %%i2, %%o0 | ||
| 195 | \\ # Add some extra space for the initial frame | ||
| 196 | \\ sub %%i1, 176 + 2047, %%o1 | ||
| 197 | \\ mov %%i4, %%o2 | ||
| 198 | \\ mov %%i5, %%o3 | ||
| 199 | \\ ldx [%%fp + 0x8af], %%o4 | ||
| 200 | \\ t 0x6d | ||
| 201 | \\ bcs,pn %%xcc, 2f | ||
| 202 | \\ nop | ||
| 203 | \\ # The child pid is returned in o0 while o1 tells if this | ||
| 204 | \\ # process is # the child (=1) or the parent (=0). | ||
| 205 | \\ brnz %%o1, 1f | ||
| 206 | \\ nop | ||
| 207 | \\ # Parent process, return the child pid | ||
| 208 | \\ mov %%o0, %%i0 | ||
| 209 | \\ ret | ||
| 210 | \\ restore | ||
| 211 | \\1: | ||
| 212 | \\ # Child process, call func(arg) | ||
| 213 | \\ mov %%g0, %%fp | ||
| 214 | \\ call %%g2 | ||
| 215 | \\ mov %%g3, %%o0 | ||
| 216 | \\ # Exit | ||
| 217 | \\ mov 1, %%g1 # SYS_exit | ||
| 218 | \\ t 0x6d | ||
| 219 | \\2: | ||
| 220 | \\ # The syscall failed | ||
| 221 | \\ sub %%g0, %%o0, %%i0 | ||
| 222 | \\ ret | ||
| 223 | \\ restore | ||
| 224 | ); | ||
| 225 | } | ||
| 185 | 226 | ||
| 186 | pub const restore = restore_rt; | 227 | pub const restore = restore_rt; |
| 187 | 228 |
lib/std/os/linux/thumb.zig+2| ... | @@ -141,6 +141,8 @@ pub fn syscall6( | ... | @@ -141,6 +141,8 @@ pub fn syscall6( |
| 141 | ); | 141 | ); |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | pub const clone = @import("arm-eabi.zig").clone; | ||
| 145 | |||
| 144 | pub fn restore() callconv(.Naked) noreturn { | 146 | pub fn restore() callconv(.Naked) noreturn { |
| 145 | asm volatile ( | 147 | asm volatile ( |
| 146 | \\ mov r7, %[number] | 148 | \\ mov r7, %[number] |
lib/std/os/linux/x86.zig+42-4| ... | @@ -118,10 +118,48 @@ pub fn socketcall(call: usize, args: [*]const usize) usize { | ... | @@ -118,10 +118,48 @@ pub fn socketcall(call: usize, args: [*]const usize) usize { |
| 118 | ); | 118 | ); |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | const CloneFn = *const fn (arg: usize) callconv(.C) u8; | 121 | pub fn clone() callconv(.Naked) usize { |
| 122 | 122 | // __clone(func, stack, flags, arg, ptid, tls, ctid) | |
| 123 | /// This matches the libc clone function. | 123 | // +8, +12, +16, +20, +24, +28, +32 |
| 124 | pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; | 124 | // |
| 125 | // syscall(SYS_clone, flags, stack, ptid, tls, ctid) | ||
| 126 | // eax, ebx, ecx, edx, esi, edi | ||
| 127 | asm volatile ( | ||
| 128 | \\ pushl %%ebp | ||
| 129 | \\ movl %%esp,%%ebp | ||
| 130 | \\ pushl %%ebx | ||
| 131 | \\ pushl %%esi | ||
| 132 | \\ pushl %%edi | ||
| 133 | \\ // Setup the arguments | ||
| 134 | \\ movl 16(%%ebp),%%ebx | ||
| 135 | \\ movl 12(%%ebp),%%ecx | ||
| 136 | \\ andl $-16,%%ecx | ||
| 137 | \\ subl $20,%%ecx | ||
| 138 | \\ movl 20(%%ebp),%%eax | ||
| 139 | \\ movl %%eax,4(%%ecx) | ||
| 140 | \\ movl 8(%%ebp),%%eax | ||
| 141 | \\ movl %%eax,0(%%ecx) | ||
| 142 | \\ movl 24(%%ebp),%%edx | ||
| 143 | \\ movl 28(%%ebp),%%esi | ||
| 144 | \\ movl 32(%%ebp),%%edi | ||
| 145 | \\ movl $120,%%eax // SYS_clone | ||
| 146 | \\ int $128 | ||
| 147 | \\ testl %%eax,%%eax | ||
| 148 | \\ jnz 1f | ||
| 149 | \\ popl %%eax | ||
| 150 | \\ xorl %%ebp,%%ebp | ||
| 151 | \\ calll *%%eax | ||
| 152 | \\ movl %%eax,%%ebx | ||
| 153 | \\ movl $1,%%eax // SYS_exit | ||
| 154 | \\ int $128 | ||
| 155 | \\1: | ||
| 156 | \\ popl %%edi | ||
| 157 | \\ popl %%esi | ||
| 158 | \\ popl %%ebx | ||
| 159 | \\ popl %%ebp | ||
| 160 | \\ retl | ||
| 161 | ); | ||
| 162 | } | ||
| 125 | 163 | ||
| 126 | pub fn restore() callconv(.Naked) noreturn { | 164 | pub fn restore() callconv(.Naked) noreturn { |
| 127 | switch (@import("builtin").zig_backend) { | 165 | switch (@import("builtin").zig_backend) { |
lib/std/os/linux/x86_64.zig+25-4| ... | @@ -100,10 +100,31 @@ pub fn syscall6( | ... | @@ -100,10 +100,31 @@ pub fn syscall6( |
| 100 | ); | 100 | ); |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | const CloneFn = *const fn (arg: usize) callconv(.C) u8; | 103 | pub fn clone() callconv(.Naked) usize { |
| 104 | 104 | asm volatile ( | |
| 105 | /// This matches the libc clone function. | 105 | \\ movl $56,%%eax // SYS_clone |
| 106 | pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; | 106 | \\ movq %%rdi,%%r11 |
| 107 | \\ movq %%rdx,%%rdi | ||
| 108 | \\ movq %%r8,%%rdx | ||
| 109 | \\ movq %%r9,%%r8 | ||
| 110 | \\ movq 8(%%rsp),%%r10 | ||
| 111 | \\ movq %%r11,%%r9 | ||
| 112 | \\ andq $-16,%%rsi | ||
| 113 | \\ subq $8,%%rsi | ||
| 114 | \\ movq %%rcx,(%%rsi) | ||
| 115 | \\ syscall | ||
| 116 | \\ testq %%rax,%%rax | ||
| 117 | \\ jnz 1f | ||
| 118 | \\ xorl %%ebp,%%ebp | ||
| 119 | \\ popq %%rdi | ||
| 120 | \\ callq *%%r9 | ||
| 121 | \\ movl %%eax,%%edi | ||
| 122 | \\ movl $60,%%eax // SYS_exit | ||
| 123 | \\ syscall | ||
| 124 | \\1: ret | ||
| 125 | \\ | ||
| 126 | ); | ||
| 127 | } | ||
| 107 | 128 | ||
| 108 | pub const restore = restore_rt; | 129 | pub const restore = restore_rt; |
| 109 | 130 |