1/*- 2 * Copyright (c) 2001 Daniel Eischen <deischen@freebsd.org>. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Neither the name of the author nor the names of its contributors 11 * may be used to endorse or promote products derived from this software 12 * without specific prior written permission. 13 * 14 * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <machine/asm.h> 28__FBSDID("$FreeBSD$"); 29 30/* 31 * Where do we define these? 32 */ 33#define MC_LEN_OFFSET 80 /* offset to mc_len from mcontext */ 34#define MC_LEN 640 /* mc_len <machine/ucontext.h> */ 35#define MC_FPFMT_OFFSET 84 36#define MC_FPFMT_NODEV 0x10000 37#define MC_FPFMT_387 0x10001 38#define MC_FPFMT_XMM 0x10002 39#define MC_OWNEDFP_OFFSET 88 40#define MC_OWNEDFP_NONE 0x20000 41#define MC_OWNEDFP_FPU 0x20001 42#define MC_OWNEDFP_PCB 0x20002 43#define MC_FPREGS_OFFSET 96 /* offset to FP regs from mcontext */ 44#define MC_FP_CW_OFFSET 96 /* offset to FP control word */ 45 46/* 47 * int thr_setcontext(mcontext_t *mcp, intptr_t val, intptr_t *loc) 48 * 49 * Restores the context in mcp. 50 * 51 * Returns 0 if there are no errors; -1 otherwise 52 */ 53 .weak CNAME(_thr_setcontext) 54 .set CNAME(_thr_setcontext),CNAME(__thr_setcontext) 55ENTRY(__thr_setcontext) 56 movl 4(%esp), %edx /* get address of mcontext */ 57 cmpl $0, %edx /* check for null pointer */ 58 jne 1f 59 movl $-1, %eax 60 jmp 8f 611: cmpl $MC_LEN, MC_LEN_OFFSET(%edx) /* is context valid? */ 62 je 2f 63 movl $-1, %eax /* bzzzt, invalid context */ 64 jmp 8f 652: /*movl 4(%edx), %gs*/ /* we don't touch %gs */ 66 movw 8(%edx), %fs 67 movw 12(%edx), %es 68 movw 16(%edx), %ds 69 movw 76(%edx), %ss 70 movl 20(%edx), %edi 71 movl 24(%edx), %esi 72 movl 28(%edx), %ebp 73 movl %esp, %ecx /* save current stack in ecx */ 74 movl 72(%edx), %esp /* switch to context defined stack */ 75 pushl 60(%edx) /* push return address on stack */ 76 pushl 44(%edx) /* push ecx on stack */ 77 pushl 48(%edx) /* push eax on stack */ 78 /* 79 * if (mc_fpowned == MC_OWNEDFP_FPU || mc_fpowned == MC_OWNEDFP_PCB) { 80 * if (mc_fpformat == MC_FPFMT_387) 81 * restore 387 FP register format 82 * else if (mc_fpformat == MC_FPFMT_XMM) 83 * restore XMM/SSE FP register format 84 * } 85 */ 86 cmpl $MC_OWNEDFP_FPU, MC_OWNEDFP_OFFSET(%edx) 87 je 3f 88 cmpl $MC_OWNEDFP_PCB, MC_OWNEDFP_OFFSET(%edx) 89 jne 5f 903: cmpl $MC_FPFMT_387, MC_FPFMT_OFFSET(%edx) 91 jne 4f 92 frstor MC_FPREGS_OFFSET(%edx) /* restore 387 FP regs */ 93 jmp 6f 944: cmpl $MC_FPFMT_XMM, MC_FPFMT_OFFSET(%edx) 95 jne 5f 96 fxrstor MC_FPREGS_OFFSET(%edx) /* restore XMM FP regs */ 97 jmp 6f 985: fninit 99 fldcw MC_FP_CW_OFFSET(%edx) 1006: pushl 68(%edx) /* push flags register on stack*/ 101 movl 36(%edx), %ebx /* restore ebx and edx */ 102 movl 40(%edx), %edx 103 movl 12(%ecx), %eax /* get 3rd arg (loc) */ 104 cmpl $0, %eax /* do nothing if loc == null */ 105 je 7f 106 movl 8(%ecx), %ecx /* get 2nd arg (val) */ 107 movl %ecx, (%eax) /* set loc = val */ 1087: popfl /* restore flags after test */ 109 popl %eax /* restore eax and ecx last */ 110 popl %ecx 1118: ret 112 113/* 114 * int thr_getcontext(mcontext_t *mcp); 115 * 116 * Returns -1 if there is an error, 0 no errors; 1 upon return 117 * from a setcontext(). 118 */ 119 .weak CNAME(_thr_getcontext) 120 .set CNAME(_thr_getcontext),CNAME(__thr_getcontext) 121ENTRY(__thr_getcontext) 122 pushl %edx /* save edx */ 123 movl 8(%esp), %edx /* get address of mcontext */ 124 cmpl $0, %edx /* check for null pointer */ 125 jne 1f 126 popl %edx /* restore edx and stack */ 127 movl $-1, %eax 128 jmp 2f 1291: /*movw %gs, 4(%edx)*/ /* we don't touch %gs */ 130 movw %fs, 8(%edx) 131 movw %es, 12(%edx) 132 movw %ds, 16(%edx) 133 movw %ss, 76(%edx) 134 movl %edi, 20(%edx) 135 movl %esi, 24(%edx) 136 movl %ebp, 28(%edx) 137 movl %ebx, 36(%edx) 138 movl $1, 48(%edx) /* store successful return in eax */ 139 popl %eax /* get saved value of edx */ 140 movl %eax, 40(%edx) /* save edx */ 141 movl %ecx, 44(%edx) 142 movl (%esp), %eax /* get return address */ 143 movl %eax, 60(%edx) /* save return address */ 144 fnstcw MC_FP_CW_OFFSET(%edx) 145 movl $MC_LEN, MC_LEN_OFFSET(%edx) 146 movl $MC_FPFMT_NODEV, MC_FPFMT_OFFSET(%edx) /* no FP */ 147 movl $MC_OWNEDFP_NONE, MC_OWNEDFP_OFFSET(%edx) /* no FP */ 148 pushfl 149 popl %eax /* get eflags */ 150 movl %eax, 68(%edx) /* store eflags */ 151 movl %esp, %eax /* setcontext pushes the return */ 152 addl $4, %eax /* address onto the top of the */ 153 movl %eax, 72(%edx) /* stack; account for this */ 154 movl 40(%edx), %edx /* restore edx -- is this needed? */ 155 xorl %eax, %eax /* return 0 */ 1562: ret 157