xref: /illumos-gate/usr/src/lib/libc/i386/sys/getcontext.S (revision ed093b41a93e8563e6e1e5dae0768dda2a7bcc27)
15d9d9091SRichard Lowe/*
25d9d9091SRichard Lowe * CDDL HEADER START
35d9d9091SRichard Lowe *
45d9d9091SRichard Lowe * The contents of this file are subject to the terms of the
55d9d9091SRichard Lowe * Common Development and Distribution License (the "License").
65d9d9091SRichard Lowe * You may not use this file except in compliance with the License.
75d9d9091SRichard Lowe *
85d9d9091SRichard Lowe * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95d9d9091SRichard Lowe * or http://www.opensolaris.org/os/licensing.
105d9d9091SRichard Lowe * See the License for the specific language governing permissions
115d9d9091SRichard Lowe * and limitations under the License.
125d9d9091SRichard Lowe *
135d9d9091SRichard Lowe * When distributing Covered Code, include this CDDL HEADER in each
145d9d9091SRichard Lowe * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155d9d9091SRichard Lowe * If applicable, add the following below this CDDL HEADER, with the
165d9d9091SRichard Lowe * fields enclosed by brackets "[]" replaced with your own identifying
175d9d9091SRichard Lowe * information: Portions Copyright [yyyy] [name of copyright owner]
185d9d9091SRichard Lowe *
195d9d9091SRichard Lowe * CDDL HEADER END
205d9d9091SRichard Lowe */
215d9d9091SRichard Lowe
225d9d9091SRichard Lowe/*
235d9d9091SRichard Lowe * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
245d9d9091SRichard Lowe * Use is subject to license terms.
255d9d9091SRichard Lowe */
265d9d9091SRichard Lowe
27*ed093b41SRobert Mustacchi/*
28*ed093b41SRobert Mustacchi * Copyright 2023 Oxide Computer Company
29*ed093b41SRobert Mustacchi */
30*ed093b41SRobert Mustacchi
315d9d9091SRichard Lowe	.file	"getcontext.s"
325d9d9091SRichard Lowe
335d9d9091SRichard Lowe#include <sys/asm_linkage.h>
345d9d9091SRichard Lowe
355d9d9091SRichard Lowe	ANSI_PRAGMA_WEAK(getcontext,function)
365d9d9091SRichard Lowe	ANSI_PRAGMA_WEAK(swapcontext,function)
375d9d9091SRichard Lowe
385d9d9091SRichard Lowe#include "SYS.h"
395d9d9091SRichard Lowe#include <assym.h>
405d9d9091SRichard Lowe
415d9d9091SRichard Lowe/*
425d9d9091SRichard Lowe * getcontext() and swapcontext() are written in assembler since it has to
435d9d9091SRichard Lowe * capture the correct machine state of the caller, including
445d9d9091SRichard Lowe * the registers: %edi, %esi and %ebx.
455d9d9091SRichard Lowe *
465d9d9091SRichard Lowe * As swapcontext() is actually equivalent to getcontext() + setcontext(),
475d9d9091SRichard Lowe * swapcontext() shares the most code with getcontext().
485d9d9091SRichard Lowe */
495d9d9091SRichard Lowe
505d9d9091SRichard Lowe
51*ed093b41SRobert Mustacchi#define	GETCONTEXT_IMPL(func)						\
525d9d9091SRichard Lowe	movl	4(%esp), %eax;		/* %eax <-- first arg: ucp */	\
535d9d9091SRichard Lowe	pushl	%eax;			/* push ucp for system call */	\
54*ed093b41SRobert Mustacchi	call	func;			/* call syscall */		\
555d9d9091SRichard Lowe	addl	$4, %esp;		/* pop arg */			\
565d9d9091SRichard Lowe	andl	%eax, %eax;		/* if (err_ret_from_syscall) */	\
575d9d9091SRichard Lowe	je	1f;							\
585d9d9091SRichard Lowe	ret;				/*	then return */		\
595d9d9091SRichard Lowe1:									\
605d9d9091SRichard Lowe	movl	4(%esp), %eax;		/* recompute first arg */	\
615d9d9091SRichard Lowe	/*								\
625d9d9091SRichard Lowe	 * fix up %esp and %eip						\
635d9d9091SRichard Lowe	 */								\
645d9d9091SRichard Lowe	leal	UC_MCONTEXT_GREGS (%eax), %edx;				\
655d9d9091SRichard Lowe				/* %edx <-- &ucp->uc_mcontext.gregs */	\
665d9d9091SRichard Lowe	movl	0(%esp), %eax;	/* read return PC from stack */		\
675d9d9091SRichard Lowe	movl	%eax, EIP_OFF (%edx);					\
685d9d9091SRichard Lowe				/* store ret PC in EIP of env var */	\
695d9d9091SRichard Lowe	leal	4(%esp), %eax;	/* get caller's sp at time of call */	\
705d9d9091SRichard Lowe	movl	%eax, UESP_OFF (%edx);					\
715d9d9091SRichard Lowe				/* store the sp into UESP of env var */	\
725d9d9091SRichard Lowe	xorl	%eax, %eax;	/* return 0 */				\
735d9d9091SRichard Lowe	movl	%eax, EAX_OFF (%edx);					\
745d9d9091SRichard Lowe				/* getcontext returns 0 after a setcontext */
755d9d9091SRichard Lowe
765d9d9091SRichard Lowe/*
77*ed093b41SRobert Mustacchi * int getcontext(ucontext_t *ucp)
785d9d9091SRichard Lowe */
795d9d9091SRichard Lowe	ENTRY(getcontext)
80*ed093b41SRobert Mustacchi	GETCONTEXT_IMPL(__getcontext)
815d9d9091SRichard Lowe	ret
825d9d9091SRichard Lowe	SET_SIZE(getcontext)
835d9d9091SRichard Lowe
845d9d9091SRichard Lowe
855d9d9091SRichard Lowe/*
86*ed093b41SRobert Mustacchi * int swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
875d9d9091SRichard Lowe */
885d9d9091SRichard Lowe	ENTRY(swapcontext)
89*ed093b41SRobert Mustacchi	GETCONTEXT_IMPL(__getcontext)
90*ed093b41SRobert Mustacchi	/* call setcontext */
915d9d9091SRichard Lowe	movl	8(%esp), %eax		/* %eax <-- second arg: ucp */
925d9d9091SRichard Lowe	pushl	%eax			/* push ucp for setcontext */
935d9d9091SRichard Lowe	call	setcontext
945d9d9091SRichard Lowe	addl	$4, %esp		/* pop arg: just in case */
955d9d9091SRichard Lowe	ret
965d9d9091SRichard Lowe	SET_SIZE(swapcontext)
97*ed093b41SRobert Mustacchi
98*ed093b41SRobert Mustacchi/*
99*ed093b41SRobert Mustacchi * int getcontext_extd(ucontext_t *ucp, uint32_t flags)
100*ed093b41SRobert Mustacchi */
101*ed093b41SRobert Mustacchi	ENTRY(getcontext_extd)
102*ed093b41SRobert Mustacchi	movl	8(%esp), %eax
103*ed093b41SRobert Mustacchi	cmpl	$0, %eax		/* if (flags != 0) */
104*ed093b41SRobert Mustacchi	jne	2f
105*ed093b41SRobert Mustacchi	GETCONTEXT_IMPL(__getcontext_extd)
106*ed093b41SRobert Mustacchi	ret
107*ed093b41SRobert Mustacchi2:
108*ed093b41SRobert Mustacchi	movl	$EINVAL, %eax		/* errno = EINVAL; */
109*ed093b41SRobert Mustacchi	jmp	__cerror		/* return (-1) */
110*ed093b41SRobert Mustacchi	SET_SIZE(getcontext_extd)
111*ed093b41SRobert Mustacchi
112*ed093b41SRobert Mustacchi
113*ed093b41SRobert Mustacchi/*
114*ed093b41SRobert Mustacchi * int swapcontext_extd(ucontext_t *oucp, const ucontext_t *ucp)
115*ed093b41SRobert Mustacchi */
116*ed093b41SRobert Mustacchi	ENTRY(swapcontext_extd)
117*ed093b41SRobert Mustacchi	movl	8(%esp), %eax
118*ed093b41SRobert Mustacchi	cmpl	$0, %eax		/* if (flags != 0) */
119*ed093b41SRobert Mustacchi	jne	2f
120*ed093b41SRobert Mustacchi	GETCONTEXT_IMPL(__getcontext_extd)
121*ed093b41SRobert Mustacchi	/* call setcontext */
122*ed093b41SRobert Mustacchi	movl	12(%esp), %eax		/* %eax <-- second arg: ucp */
123*ed093b41SRobert Mustacchi	pushl	%eax			/* push ucp for setcontext */
124*ed093b41SRobert Mustacchi	call	setcontext
125*ed093b41SRobert Mustacchi	addl	$4, %esp		/* pop arg: just in case */
126*ed093b41SRobert Mustacchi	ret
127*ed093b41SRobert Mustacchi2:
128*ed093b41SRobert Mustacchi	movl	$EINVAL, %eax		/* errno = EINVAL; */
129*ed093b41SRobert Mustacchi	jmp	__cerror		/* return (-1) */
130*ed093b41SRobert Mustacchi	SET_SIZE(swapcontext_extd)
131