kse_asm.S revision 103581
1103581Smini/* 2103581Smini * Copyright (c) 2002 Jonathan Mini <mini@freebsd.org>. 3103581Smini * Copyright (c) 2001 Daniel Eischen <deischen@freebsd.org>. 4103581Smini * All rights reserved. 5103581Smini * 6103581Smini * Redistribution and use in source and binary forms, with or without 7103581Smini * modification, are permitted provided that the following conditions 8103581Smini * are met: 9103581Smini * 1. Redistributions of source code must retain the above copyright 10103581Smini * notice, this list of conditions and the following disclaimer. 11103581Smini * 2. Neither the name of the author nor the names of its contributors 12103581Smini * may be used to endorse or promote products derived from this software 13103581Smini * without specific prior written permission. 14103581Smini * 15103581Smini * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' AND 16103581Smini * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17103581Smini * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18103581Smini * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19103581Smini * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20103581Smini * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21103581Smini * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22103581Smini * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23103581Smini * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24103581Smini * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25103581Smini * SUCH DAMAGE. 26103581Smini * 2799073Sjulian * $FreeBSD: head/tools/KSE/ksetest/kse_asm.S 103581 2002-09-19 02:15:27Z mini $ 2899073Sjulian */ 2999073Sjulian 30103581Smini#include <machine/asm.h> 31103581Smini__FBSDID("$FreeBSD: head/tools/KSE/ksetest/kse_asm.S 103581 2002-09-19 02:15:27Z mini $"); 3299073Sjulian 33103581Smini/* 34103581Smini * Where do we define these? 35103581Smini */ 36103581Smini#define MC_SIZE 640 /* sizeof mcontext_t */ 37103581Smini#define UC_MC_OFFSET 16 /* offset to mcontext from ucontext */ 38103581Smini#define UC_MC_LEN_OFFSET 96 /* offset to mc_len from mcontext */ 39103581Smini#define MC_LEN_OFFSET 80 /* offset to mc_len from mcontext */ 40103581Smini#define MC_FP_REGS_OFFSET 96 /* offset to FP regs from mcontext */ 41103581Smini#define MC_FP_CW_OFFSET 96 /* offset to FP control word */ 42103581Smini#define MC_OWNEDFP_OFFSET 88 /* offset to mc_ownedfp from mcontext */ 43103581Smini#define KM_STACK_SP_OFFSET 32 /* offset to km_stack.ss_sp */ 44103581Smini#define KM_STACK_SIZE_OFFSET 36 /* offset to km_stack.ss_sp */ 45103581Smini#define KM_FUNC_OFFSET 28 /* offset to km_func */ 46103581Smini 47103581Smini/* 48103581Smini * int uts_to_thread(thread_mailbox *tdp, thread_mailbox **curthreadp); 49103581Smini * 50103581Smini * Does not return on success, returns -1 otherwise. 51103581Smini */ 52103581SminiENTRY(uts_to_thread) 53103581Smini movl 4(%esp), %edx /* get address of thread_mailbox */ 54103581Smini /* .. ucontext_t is at offset 0 */ 55103581Smini cmpl $0, %edx /* check for null pointer */ 56103581Smini jne 1f 57103581Smini movl $-1, %eax 58103581Smini jmp 5f 59103581Smini1: cmpl $MC_SIZE, UC_MC_LEN_OFFSET(%edx) /* is context valid? */ 60103581Smini je 2f 61103581Smini movl $-1, %eax /* bzzzt, invalid context */ 62103581Smini jmp 5f 63103581Smini2: movl 8(%esp), %eax /* get address of curthreadp */ 64103581Smini movl %edx, (%eax) /* we're now the current thread */ 65103581Smini /* 66103581Smini * From here on, we don't touch the old stack. 67103581Smini */ 68103581Smini addl $UC_MC_OFFSET, %edx /* add offset to mcontext */ 69103581Smini movl 4(%edx), %gs 70103581Smini movl 8(%edx), %fs 71103581Smini movl 12(%edx), %es 72103581Smini movl 16(%edx), %ds 73103581Smini movl 76(%edx), %ss 74103581Smini movl 20(%edx), %edi 75103581Smini movl 24(%edx), %esi 76103581Smini movl 28(%edx), %ebp 77103581Smini movl 72(%edx), %esp /* switch to context defined stack */ 78103581Smini subl $4, %esp /* leave space for the return address */ 79103581Smini movl 60(%edx), %eax /* put return address at top of stack */ 80103581Smini movl %eax, (%esp) 81103581Smini cmpl $0, MC_OWNEDFP_OFFSET(%edx) /* are FP regs valid? */ 82103581Smini jz 3f 83103581Smini frstor MC_FP_REGS_OFFSET(%edx) /* restore FP regs */ 84103581Smini jmp 4f 85103581Smini3: fninit 86103581Smini fldcw MC_FP_CW_OFFSET(%edx) 87103581Smini4: movl 48(%edx), %eax /* restore ax, bx, cx */ 88103581Smini movl 36(%edx), %ebx 89103581Smini movl 44(%edx), %ecx 90103581Smini pushl 68(%edx) /* flags on stack */ 91103581Smini pushl 40(%edx) /* %edx on stack */ 92103581Smini popl %edx /* %edx off stack */ 93103581Smini popf /* flags off stack */ 94103581Smini5: ret /* %eip off stack */ 9599073Sjulian 9699073Sjulian/* 97103581Smini * int thread_to_uts(thread_mailbox *tm, kse_mailbox *km); 98103581Smini * 99103581Smini * Does not return on success, returns -1 otherwise. 10099073Sjulian */ 101103581SminiENTRY(thread_to_uts) 102103581Smini movl 4(%esp), %eax /* get address of context */ 103103581Smini cmpl $0, %eax /* check for null pointer */ 104103581Smini jne 1f 105103581Smini movl $-1, %eax 106103581Smini jmp 2f 107103581Smini1: pushl %edx /* save value of edx */ 108103581Smini movl %eax, %edx /* get address of context */ 109103581Smini addl $UC_MC_OFFSET, %edx /* add offset to mcontext */ 110103581Smini movl %gs, 4(%edx) 111103581Smini movl %fs, 8(%edx) 112103581Smini movl %es, 12(%edx) 113103581Smini movl %ds, 16(%edx) 114103581Smini movl %edi, 20(%edx) 115103581Smini movl %esi, 24(%edx) 116103581Smini movl %ebp, 28(%edx) 117103581Smini movl %ebx, 36(%edx) 118103581Smini movl $0, 48(%edx) /* store successful return in eax */ 119103581Smini popl %eax /* get saved value of edx */ 120103581Smini movl %eax, 40(%edx) /* save edx */ 121103581Smini movl %ecx, 44(%edx) 122103581Smini movl (%esp), %eax /* get return address */ 123103581Smini movl %eax, 60(%edx) /* save return address */ 124103581Smini movl %ss, 76(%edx) 125103581Smini /* 126103581Smini * Don't save floating point registers here. 127103581Smini * 128103581Smini * This is an explicit call to get the current context, so 129103581Smini * the caller is done with the floating point registers. 130103581Smini * Contexts formed by involuntary switches, such as signal delivery, 131103581Smini * have floating point registers saved by the kernel. 132103581Smini */ 133103581Smini fnstcw MC_FP_CW_OFFSET(%edx) 134103581Smini movl $0, MC_OWNEDFP_OFFSET(%edx) /* no FP */ 135103581Smini lahf /* get eflags */ 136103581Smini movl %eax, 68(%edx) /* store eflags */ 137103581Smini movl %esp, %eax /* setcontext pushes the return */ 138103581Smini addl $4, %eax /* address onto the top of the */ 139103581Smini movl %eax, 72(%edx) /* stack; account for this */ 140103581Smini movl $MC_SIZE, MC_LEN_OFFSET(%edx) /* context is now valid */ 141103581Smini movl 8(%esp), %edx /* get address of mailbox */ 142103581Smini movl KM_STACK_SP_OFFSET(%edx), %eax /* get bottom of stack */ 143103581Smini addl KM_STACK_SIZE_OFFSET(%edx), %eax /* add length */ 144103581Smini movl %eax, %esp /* switch to the uts's stack */ 145103581Smini pushl %edx /* push the address of the mailbox */ 146103581Smini pushl KM_FUNC_OFFSET(%edx) /* .. the uts can return to itself */ 147103581Smini pushl KM_FUNC_OFFSET(%edx) /* push the address of the uts func */ 148103581Smini2: ret 14999073Sjulian 150