xref: /openbsd-src/lib/libc/arch/amd64/sys/tfork_thread.S (revision 83762a71f74848f4d09174ce350838b4204957c5)
1*83762a71Sderaadt/*	$OpenBSD: tfork_thread.S,v 1.12 2023/12/10 16:45:51 deraadt Exp $ */
2c6f64c6fSguenther/*-
3c6f64c6fSguenther * Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org>
4c6f64c6fSguenther * Copyright (c) 2003 Alan L. Cox <alc@cs.rice.edu>
5c6f64c6fSguenther * All rights reserved.
6c6f64c6fSguenther *
7c6f64c6fSguenther * Redistribution and use in source and binary forms, with or without
8c6f64c6fSguenther * modification, are permitted provided that the following conditions
9c6f64c6fSguenther * are met:
10c6f64c6fSguenther * 1. Redistributions of source code must retain the above copyright
11c6f64c6fSguenther *    notice, this list of conditions and the following disclaimer.
12c6f64c6fSguenther * 2. Redistributions in binary form must reproduce the above copyright
13c6f64c6fSguenther *    notice, this list of conditions and the following disclaimer in the
14c6f64c6fSguenther *    documentation and/or other materials provided with the distribution.
15c6f64c6fSguenther *
16c6f64c6fSguenther * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17c6f64c6fSguenther * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18c6f64c6fSguenther * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19c6f64c6fSguenther * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20c6f64c6fSguenther * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21c6f64c6fSguenther * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22c6f64c6fSguenther * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23c6f64c6fSguenther * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24c6f64c6fSguenther * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25c6f64c6fSguenther * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26c6f64c6fSguenther * SUCH DAMAGE.
27c6f64c6fSguenther */
28c6f64c6fSguenther
29c6f64c6fSguenther#include <machine/asm.h>
30c6f64c6fSguenther
31c6f64c6fSguenther/*
32c6f64c6fSguenther * With thanks to John Dyson for the original version of this.
33c6f64c6fSguenther */
34c6f64c6fSguenther
35c6f64c6fSguenther#include "SYS.h"
36c6f64c6fSguenther
37c6f64c6fSguenther/*
38c6f64c6fSguenther *                %rdi   %rsi   %rdx       %rcx
3916b62b6aSguenther * __tfork_thread(param, psize, start_fnc, start_arg);
40c6f64c6fSguenther *
41c6f64c6fSguenther * param:		Argument to pass to the actual kernel call.
4216b62b6aSguenther * psize:		Other argument to pass to the actual kernel call.
43c6f64c6fSguenther * start_fnc:		Address of thread function to call in child.
44c6f64c6fSguenther * start_arg:		Argument to pass to the thread function in child.
45c6f64c6fSguenther */
46c6f64c6fSguenther
47c6f64c6fSguentherENTRY(__tfork_thread)
487e6b5442Sguenther	.cfi_startproc
4939b8558cSmortimer	RETGUARD_SETUP(__tfork_thread, r11);
5039b8558cSmortimer	RETGUARD_PUSH(r11);
51c6f64c6fSguenther	movq	%rdx, %r8
52c6f64c6fSguenther	movq	%rcx, %r9
53c6f64c6fSguenther
54c6f64c6fSguenther	/*
55c6f64c6fSguenther	 * Prepare and execute the thread creation syscall
56c6f64c6fSguenther	 */
57c6f64c6fSguenther	movl	$SYS___tfork, %eax
587e6b5442Sguenther	.cfi_endproc
59*83762a71Sderaadt99:	syscall
60*83762a71Sderaadt	PINSYSCALL(SYS___tfork, 99b)
61c6f64c6fSguenther	jb 	2f
62c6f64c6fSguenther
63c6f64c6fSguenther	/*
64c6f64c6fSguenther	 * Check to see if we are in the parent or child
65c6f64c6fSguenther	 */
6611225f07Sguenther	cmpl	$0, %eax
6711225f07Sguenther	jz	1f
6839b8558cSmortimer	jmp	3f
69c6f64c6fSguenther
7050634ea5Sguenther	/* the retpoline we'll use to call the child's main */
7150634ea5Sguenther	_ALIGN_TRAPS
727e6b5442Sguenther	.cfi_startproc
7350634ea5Sguenther0:	JMP_RETPOLINE(r8)
7450634ea5Sguenther
75c6f64c6fSguenther	/*
76c6f64c6fSguenther	 * If we are in the child (new thread), then
77c6f64c6fSguenther	 * set-up the call to the internal subroutine.  If it
78c6f64c6fSguenther	 * returns, then call __threxit.
79c6f64c6fSguenther	 */
8050634ea5Sguenther	_ALIGN_TRAPS
81c6f64c6fSguenther1:
827e6b5442Sguenther	/* Mark top frame of new thread in CFI and with zero FP */
837e6b5442Sguenther	.cfi_undefined	rip
847e6b5442Sguenther	.cfi_undefined	rsp
857e6b5442Sguenther	xorl	%ebp, %ebp
86c6f64c6fSguenther	movq	%r9, %rdi
8750634ea5Sguenther	call	0b
88c6f64c6fSguenther
89c6f64c6fSguenther	/*
90c6f64c6fSguenther	 * Thread exit system call
91c6f64c6fSguenther	 */
92c6f64c6fSguenther	movl	$SYS___threxit, %eax
93c6f64c6fSguenther	xorl	%edi, %edi
94*83762a71Sderaadt98:	syscall
95*83762a71Sderaadt	PINSYSCALL(SYS___threxit, 98b)
9613df6982Sderaadt	int3
97c6f64c6fSguenther
98c6f64c6fSguenther	/*
99c6f64c6fSguenther	 * Branch here if the thread creation fails:
100c6f64c6fSguenther	 */
101c6f64c6fSguenther2:
102fe38b55cSguenther	SET_ERRNO
10339b8558cSmortimer3:
10439b8558cSmortimer	RETGUARD_POP(r11);
10539b8558cSmortimer	RETGUARD_CHECK(__tfork_thread, r11);
106fe38b55cSguenther	ret
1077e6b5442Sguenther	.cfi_endproc
108fdc9f3d7SuebayasiEND(__tfork_thread)
109