xref: /freebsd/lib/libsys/amd64/pdrfork_thread.S (revision 74a2bf1b7a7ff0c872499cb94df24713f61c872c)
1*74a2bf1bSKonstantin Belousov/*-
2*74a2bf1bSKonstantin Belousov * SPDX-License-Identifier: BSD-2-Clause
3*74a2bf1bSKonstantin Belousov *
4*74a2bf1bSKonstantin Belousov * Copyright 2000 Peter Wemm <peter@FreeBSD.org>
5*74a2bf1bSKonstantin Belousov * Copyright 2003 Alan L. Cox <alc@cs.rice.edu>
6*74a2bf1bSKonstantin Belousov * Copyright 2026 The FreeBSD Foundation
7*74a2bf1bSKonstantin Belousov * All rights reserved.
8*74a2bf1bSKonstantin Belousov *
9*74a2bf1bSKonstantin Belousov * Portions of this software were developed by
10*74a2bf1bSKonstantin Belousov * Konstantin Belousov <kib@FreeBSD.org> under sponsorship from
11*74a2bf1bSKonstantin Belousov * the FreeBSD Foundation.
12*74a2bf1bSKonstantin Belousov */
13*74a2bf1bSKonstantin Belousov
14*74a2bf1bSKonstantin Belousov#include <machine/asm.h>
15*74a2bf1bSKonstantin Belousov/*
16*74a2bf1bSKonstantin Belousov * With thanks to John Dyson for the original version of this.
17*74a2bf1bSKonstantin Belousov */
18*74a2bf1bSKonstantin Belousov
19*74a2bf1bSKonstantin Belousov#include <SYS.h>
20*74a2bf1bSKonstantin Belousov
21*74a2bf1bSKonstantin Belousov/*
22*74a2bf1bSKonstantin Belousov *                %rdi %esi     %rdx     %rcx        %r8        %r9
23*74a2bf1bSKonstantin Belousov * pdrfork_thread(fdp, pdflags, rfflags, stack_addr, start_fnc, start_arg);
24*74a2bf1bSKonstantin Belousov *
25*74a2bf1bSKonstantin Belousov * fdp			Pointer for the resulting fd location
26*74a2bf1bSKonstantin Belousov * pdflags		Flags as to pdfork.
27*74a2bf1bSKonstantin Belousov * rfflags:		Flags as to rfork.
28*74a2bf1bSKonstantin Belousov * stack_addr:		Top of stack for thread.
29*74a2bf1bSKonstantin Belousov * start_fnc:		Address of thread function to call in child.
30*74a2bf1bSKonstantin Belousov * start_arg:		Argument to pass to the thread function in child.
31*74a2bf1bSKonstantin Belousov */
32*74a2bf1bSKonstantin Belousov
33*74a2bf1bSKonstantin BelousovENTRY(pdrfork_thread)
34*74a2bf1bSKonstantin Belousov	pushq	%rbx
35*74a2bf1bSKonstantin Belousov	pushq	%r12
36*74a2bf1bSKonstantin Belousov	pushq	%r13
37*74a2bf1bSKonstantin Belousov	movq	%r8, %rbx
38*74a2bf1bSKonstantin Belousov	movq	%r9, %r12
39*74a2bf1bSKonstantin Belousov	movq	%rcx, %r13
40*74a2bf1bSKonstantin Belousov
41*74a2bf1bSKonstantin Belousov	/*
42*74a2bf1bSKonstantin Belousov	 * Prepare and execute the thread creation syscall
43*74a2bf1bSKonstantin Belousov	 */
44*74a2bf1bSKonstantin Belousov	_SYSCALL(pdrfork)
45*74a2bf1bSKonstantin Belousov	jb 	2f
46*74a2bf1bSKonstantin Belousov
47*74a2bf1bSKonstantin Belousov	/*
48*74a2bf1bSKonstantin Belousov	 * Check to see if we are in the parent or child
49*74a2bf1bSKonstantin Belousov	 */
50*74a2bf1bSKonstantin Belousov	cmpl	$0, %edx
51*74a2bf1bSKonstantin Belousov	jnz	1f
52*74a2bf1bSKonstantin Belousov	popq	%r13
53*74a2bf1bSKonstantin Belousov	popq	%r12
54*74a2bf1bSKonstantin Belousov	popq	%rbx
55*74a2bf1bSKonstantin Belousov	ret
56*74a2bf1bSKonstantin Belousov
57*74a2bf1bSKonstantin Belousov	/*
58*74a2bf1bSKonstantin Belousov	 * If we are in the child (new thread), then
59*74a2bf1bSKonstantin Belousov	 * set-up the call to the internal subroutine.  If it
60*74a2bf1bSKonstantin Belousov	 * returns, then call __exit.
61*74a2bf1bSKonstantin Belousov	 */
62*74a2bf1bSKonstantin Belousov1:
63*74a2bf1bSKonstantin Belousov	movq	%r13, %rsp
64*74a2bf1bSKonstantin Belousov	movq	%r12, %rdi
65*74a2bf1bSKonstantin Belousov	call	*%rbx
66*74a2bf1bSKonstantin Belousov	movl	%eax, %edi
67*74a2bf1bSKonstantin Belousov
68*74a2bf1bSKonstantin Belousov	/*
69*74a2bf1bSKonstantin Belousov	 * Exit system call
70*74a2bf1bSKonstantin Belousov	 */
71*74a2bf1bSKonstantin Belousov	_SYSCALL(exit)
72*74a2bf1bSKonstantin Belousov
73*74a2bf1bSKonstantin Belousov	/*
74*74a2bf1bSKonstantin Belousov	 * Branch here if the thread creation fails:
75*74a2bf1bSKonstantin Belousov	 */
76*74a2bf1bSKonstantin Belousov2:
77*74a2bf1bSKonstantin Belousov	popq	%r13
78*74a2bf1bSKonstantin Belousov	popq	%r12
79*74a2bf1bSKonstantin Belousov	popq	%rbx
80*74a2bf1bSKonstantin Belousov	jmp	HIDENAME(cerror)
81*74a2bf1bSKonstantin BelousovEND(pdrfork_thread)
82*74a2bf1bSKonstantin Belousov
83*74a2bf1bSKonstantin Belousov	.section .note.GNU-stack,"",%progbits
84