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() is written in assembler since it has to capture the correct 435d9d9091SRichard Lowe * machine state of the calle. 445d9d9091SRichard Lowe * 455d9d9091SRichard Lowe * As swapcontext() is actually equivalent to getcontext() + setcontext(), 465d9d9091SRichard Lowe * swapcontext() shares the most code with getcontext(). 475d9d9091SRichard Lowe */ 485d9d9091SRichard Lowe 49*ed093b41SRobert Mustacchi#define GETCONTEXT_IMPL(offset, func) \ 505d9d9091SRichard Lowe pushq %rdi; /* preserve the ucontext_t pointer */ \ 51*ed093b41SRobert Mustacchi call func; /* call syscall */ \ 525d9d9091SRichard Lowe popq %rdx; \ 535d9d9091SRichard Lowe andl %eax, %eax; /* if (error_return_from_syscall) */ \ 545d9d9091SRichard Lowe je 1f; \ 555d9d9091SRichard Lowe addq $offset, %rsp; \ 565d9d9091SRichard Lowe ret; /* then just return */ \ 575d9d9091SRichard Lowe1: \ 585d9d9091SRichard Lowe /* \ 595d9d9091SRichard Lowe * fix up %rsp and %rip \ 605d9d9091SRichard Lowe */ \ 615d9d9091SRichard Lowe addq $UC_MCONTEXT_GREGS, %rdx; \ 625d9d9091SRichard Lowe /* &ucp->uc_mcontext.gregs */ \ 635d9d9091SRichard Lowe movq offset+0(%rsp), %rax; \ 645d9d9091SRichard Lowe /* read return PC from stack */ \ 655d9d9091SRichard Lowe movq %rax, RIP_OFF (%rdx); \ 665d9d9091SRichard Lowe /* store ret PC in EIP of env var */ \ 675d9d9091SRichard Lowe leaq offset+8(%rsp), %rax; \ 685d9d9091SRichard Lowe /* get caller's sp at time of call */ \ 695d9d9091SRichard Lowe movq %rax, RSP_OFF (%rdx); \ 705d9d9091SRichard Lowe /* store the sp into UESP of env var */ \ 715d9d9091SRichard Lowe xorq %rax, %rax; /* return 0 */ \ 725d9d9091SRichard Lowe movq %rax, RAX_OFF (%rdx); \ 735d9d9091SRichard Lowe /* getcontext returns 0 after setcontext */ 745d9d9091SRichard Lowe 755d9d9091SRichard Lowe/* 76*ed093b41SRobert Mustacchi * int getcontext(ucontext_t *ucp) 775d9d9091SRichard Lowe */ 785d9d9091SRichard Lowe 795d9d9091SRichard Lowe ENTRY(getcontext) 80*ed093b41SRobert Mustacchi GETCONTEXT_IMPL(0, __getcontext) 815d9d9091SRichard Lowe ret 825d9d9091SRichard Lowe SET_SIZE(getcontext) 835d9d9091SRichard Lowe 845d9d9091SRichard Lowe/* 85*ed093b41SRobert Mustacchi * int swapcontext(ucontext_t *oucp, const ucontext_t *ucp) 865d9d9091SRichard Lowe */ 875d9d9091SRichard Lowe 885d9d9091SRichard Lowe ENTRY(swapcontext) 895d9d9091SRichard Lowe pushq %rsi /* preserve the 2nd argument */ 905d9d9091SRichard Lowe 91*ed093b41SRobert Mustacchi GETCONTEXT_IMPL(8, __getcontext) 925d9d9091SRichard Lowe 935d9d9091SRichard Lowe /* call setcontext */ 945d9d9091SRichard Lowe popq %rdi 955d9d9091SRichard Lowe call setcontext 965d9d9091SRichard Lowe ret 975d9d9091SRichard Lowe SET_SIZE(swapcontext) 98*ed093b41SRobert Mustacchi 99*ed093b41SRobert Mustacchi/* 100*ed093b41SRobert Mustacchi * int getcontext_extd(ucontext_t *ctx, uint32_t flags) 101*ed093b41SRobert Mustacchi */ 102*ed093b41SRobert Mustacchi ENTRY(getcontext_extd) 103*ed093b41SRobert Mustacchi cmpl $0, %esi 104*ed093b41SRobert Mustacchi jne 2f 105*ed093b41SRobert Mustacchi GETCONTEXT_IMPL(0, __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 * int swapcontext_extd(ucontext_t *oucp, uint32_t flags, const ucontext_t *ucp) 114*ed093b41SRobert Mustacchi */ 115*ed093b41SRobert Mustacchi ENTRY(swapcontext_extd) 116*ed093b41SRobert Mustacchi cmpl $0, %esi 117*ed093b41SRobert Mustacchi jne 2f 118*ed093b41SRobert Mustacchi pushq %rdx /* preserve the 3rd argument */ 119*ed093b41SRobert Mustacchi 120*ed093b41SRobert Mustacchi GETCONTEXT_IMPL(8, __getcontext_extd) 121*ed093b41SRobert Mustacchi 122*ed093b41SRobert Mustacchi /* call setcontext */ 123*ed093b41SRobert Mustacchi popq %rdi 124*ed093b41SRobert Mustacchi call setcontext 125*ed093b41SRobert Mustacchi ret 126*ed093b41SRobert Mustacchi2: 127*ed093b41SRobert Mustacchi movl $EINVAL, %eax /* errno = EINVAL */ 128*ed093b41SRobert Mustacchi jmp __cerror /* return (-1) */ 129*ed093b41SRobert Mustacchi SET_SIZE(swapcontext_extd) 130