1111519Sdavidxu/* 2111519Sdavidxu * Copyright (c) 2002 Jonathan Mini <mini@freebsd.org>. 3111519Sdavidxu * Copyright (c) 2001 Daniel Eischen <deischen@freebsd.org>. 4111519Sdavidxu * All rights reserved. 5111519Sdavidxu * 6111519Sdavidxu * Redistribution and use in source and binary forms, with or without 7111519Sdavidxu * modification, are permitted provided that the following conditions 8111519Sdavidxu * are met: 9111519Sdavidxu * 1. Redistributions of source code must retain the above copyright 10111519Sdavidxu * notice, this list of conditions and the following disclaimer. 11111519Sdavidxu * 2. Neither the name of the author nor the names of its contributors 12111519Sdavidxu * may be used to endorse or promote products derived from this software 13111519Sdavidxu * without specific prior written permission. 14111519Sdavidxu * 15111519Sdavidxu * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' AND 16111519Sdavidxu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17111519Sdavidxu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18111519Sdavidxu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19111519Sdavidxu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20111519Sdavidxu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21111519Sdavidxu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22111519Sdavidxu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23111519Sdavidxu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24111519Sdavidxu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25111519Sdavidxu * SUCH DAMAGE. 26111519Sdavidxu * 27111519Sdavidxu * $FreeBSD$ 28111519Sdavidxu */ 29111519Sdavidxu 30111519Sdavidxu#include <machine/asm.h> 31111519Sdavidxu__FBSDID("$FreeBSD$"); 32111519Sdavidxu 33111519Sdavidxu/* 34111519Sdavidxu * Where do we define these? 35111519Sdavidxu */ 36111519Sdavidxu#define MC_SIZE 640 /* sizeof mcontext_t */ 37111519Sdavidxu#define UC_MC_OFFSET 16 /* offset to mcontext from ucontext */ 38111519Sdavidxu#define UC_MC_LEN_OFFSET 96 /* offset to mc_len from mcontext */ 39111519Sdavidxu#define MC_LEN_OFFSET 80 /* offset to mc_len from mcontext */ 40111519Sdavidxu#define MC_FP_REGS_OFFSET 96 /* offset to FP regs from mcontext */ 41111519Sdavidxu#define MC_FP_CW_OFFSET 96 /* offset to FP control word */ 42111519Sdavidxu#define MC_OWNEDFP_OFFSET 88 /* offset to mc_ownedfp from mcontext */ 43111519Sdavidxu#define KM_STACK_SP_OFFSET 36 /* offset to km_stack.ss_sp */ 44111519Sdavidxu#define KM_STACK_SIZE_OFFSET 40 /* offset to km_stack.ss_sp */ 45111519Sdavidxu#define KM_FUNC_OFFSET 32 /* offset to km_func */ 46111519Sdavidxu 47111519Sdavidxu/* 48111519Sdavidxu * int uts_to_thread(struct kse_thr_mailbox *tdp, 49111519Sdavidxu * struct kse_thr_mailbox **curthreadp); 50111519Sdavidxu * 51111519Sdavidxu * Does not return on success, returns -1 otherwise. 52111519Sdavidxu */ 53111519SdavidxuENTRY(uts_to_thread) 54111519Sdavidxu movl 4(%esp), %edx /* get address of kse_thr_mailbox */ 55111519Sdavidxu /* .. ucontext_t is at offset 0 */ 56111519Sdavidxu cmpl $0, %edx /* check for null pointer */ 57111519Sdavidxu jne 1f 58111519Sdavidxu movl $-1, %eax 59111519Sdavidxu jmp 5f 60111519Sdavidxu1: cmpl $MC_SIZE, UC_MC_LEN_OFFSET(%edx) /* is context valid? */ 61111519Sdavidxu je 2f 62111519Sdavidxu movl $-1, %eax /* bzzzt, invalid context */ 63111519Sdavidxu jmp 5f 64111519Sdavidxu2: movl 8(%esp), %ecx /* get address of curthreadp */ 65111519Sdavidxu movl %edx, %ebx /* save the pointer for later */ 66111519Sdavidxu /* 67111519Sdavidxu * From here on, we don't touch the old stack. 68111519Sdavidxu */ 69111519Sdavidxu addl $UC_MC_OFFSET, %edx /* add offset to mcontext */ 70111519Sdavidxu movl 4(%edx), %gs 71111519Sdavidxu movl 8(%edx), %fs 72111519Sdavidxu movl 12(%edx), %es 73111519Sdavidxu movl 16(%edx), %ds 74111519Sdavidxu movl 76(%edx), %ss 75111519Sdavidxu movl 20(%edx), %edi 76111519Sdavidxu movl 24(%edx), %esi 77111519Sdavidxu movl 28(%edx), %ebp 78111519Sdavidxu movl 72(%edx), %esp /* switch to context defined stack */ 79111519Sdavidxu subl $4, %esp /* leave space for the return address */ 80111519Sdavidxu movl 60(%edx), %eax /* put return address at top of stack */ 81111519Sdavidxu movl %eax, (%esp) 82111519Sdavidxu cmpl $0, MC_OWNEDFP_OFFSET(%edx) /* are FP regs valid? */ 83111519Sdavidxu jz 3f 84111519Sdavidxu frstor MC_FP_REGS_OFFSET(%edx) /* restore FP regs */ 85111519Sdavidxu jmp 4f 86111519Sdavidxu3: fninit 87111519Sdavidxu fldcw MC_FP_CW_OFFSET(%edx) 88111519Sdavidxu4: movl 48(%edx), %eax /* restore ax, bx, cx, dx */ 89111519Sdavidxu pushl 68(%edx) /* flags on stack */ 90111519Sdavidxu pushl 36(%edx) /* %ebx on stack */ 91111519Sdavidxu pushl 44(%edx) /* %ecx on stack */ 92111519Sdavidxu movl 40(%edx), %edx /* %edx */ 93111519Sdavidxu /* 94111519Sdavidxu * all registers are now moved out of mailbox, 95111519Sdavidxu * it's safe to set current thread pointer 96111519Sdavidxu */ 97111519Sdavidxu movl %ebx,(%ecx) 98111519Sdavidxu popl %ecx /* %ecx off stack */ 99111519Sdavidxu pop %ebx /* %ebx off stack */ 100111519Sdavidxu popf /* flags off stack */ 101111519Sdavidxu5: ret /* %eip off stack */ 102192760SattilioEND(uts_to_thread) 103111519Sdavidxu 104111519Sdavidxu/* 105111519Sdavidxu * int thread_to_uts(struct kse_thr_mailbox *tm, struct kse_mailbox *km); 106111519Sdavidxu * 107111519Sdavidxu * Does not return on success, returns -1 otherwise. 108111519Sdavidxu */ 109111519SdavidxuENTRY(thread_to_uts) 110111519Sdavidxu movl 4(%esp), %eax /* get address of context */ 111111519Sdavidxu cmpl $0, %eax /* check for null pointer */ 112111519Sdavidxu jne 1f 113111519Sdavidxu movl $-1, %eax 114111519Sdavidxu jmp 2f 115111519Sdavidxu1: pushl %edx /* save value of edx */ 116111519Sdavidxu movl %eax, %edx /* get address of context */ 117111519Sdavidxu addl $UC_MC_OFFSET, %edx /* add offset to mcontext */ 118111519Sdavidxu movl %gs, 4(%edx) 119111519Sdavidxu movl %fs, 8(%edx) 120111519Sdavidxu movl %es, 12(%edx) 121111519Sdavidxu movl %ds, 16(%edx) 122111519Sdavidxu movl %edi, 20(%edx) 123111519Sdavidxu movl %esi, 24(%edx) 124111519Sdavidxu movl %ebp, 28(%edx) 125111519Sdavidxu movl %ebx, 36(%edx) 126111519Sdavidxu movl $0, 48(%edx) /* store successful return in eax */ 127111519Sdavidxu popl %eax /* get saved value of edx */ 128111519Sdavidxu movl %eax, 40(%edx) /* save edx */ 129111519Sdavidxu movl %ecx, 44(%edx) 130111519Sdavidxu movl (%esp), %eax /* get return address */ 131111519Sdavidxu movl %eax, 60(%edx) /* save return address */ 132111519Sdavidxu movl %ss, 76(%edx) 133111519Sdavidxu /* 134111519Sdavidxu * Don't save floating point registers here. 135111519Sdavidxu * 136111519Sdavidxu * This is an explicit call to get the current context, so 137111519Sdavidxu * the caller is done with the floating point registers. 138111519Sdavidxu * Contexts formed by involuntary switches, such as signal delivery, 139111519Sdavidxu * have floating point registers saved by the kernel. 140111519Sdavidxu */ 141111519Sdavidxu fnstcw MC_FP_CW_OFFSET(%edx) 142111519Sdavidxu movl $0, MC_OWNEDFP_OFFSET(%edx) /* no FP */ 143111519Sdavidxu pushfl /* get eflags */ 144111519Sdavidxu popl %eax 145111519Sdavidxu movl %eax, 68(%edx) /* store eflags */ 146111519Sdavidxu movl %esp, %eax /* setcontext pushes the return */ 147111519Sdavidxu addl $4, %eax /* address onto the top of the */ 148111519Sdavidxu movl %eax, 72(%edx) /* stack; account for this */ 149111519Sdavidxu movl $MC_SIZE, MC_LEN_OFFSET(%edx) /* context is now valid */ 150111519Sdavidxu movl 8(%esp), %edx /* get address of mailbox */ 151111519Sdavidxu movl KM_STACK_SP_OFFSET(%edx), %eax /* get bottom of stack */ 152111519Sdavidxu addl KM_STACK_SIZE_OFFSET(%edx), %eax /* add length */ 153111519Sdavidxu movl %eax, %esp /* switch to the uts's stack */ 154111519Sdavidxu pushl %edx /* push the address of the mailbox */ 155111519Sdavidxu pushl KM_FUNC_OFFSET(%edx) /* .. the uts can return to itself */ 156111519Sdavidxu pushl KM_FUNC_OFFSET(%edx) /* push the address of the uts func */ 157111519Sdavidxu2: ret 158192760SattilioEND(thread_to_uts) 159111519Sdavidxu 160