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