kse_asm.S revision 107138
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 107138 2002-11-21 09:48:39Z davidxu $ 2899073Sjulian */ 2999073Sjulian 30103581Smini#include <machine/asm.h> 31103581Smini__FBSDID("$FreeBSD: head/tools/KSE/ksetest/kse_asm.S 107138 2002-11-21 09:48:39Z davidxu $"); 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 */ 43107035Sdavidxu#define KM_STACK_SP_OFFSET 36 /* offset to km_stack.ss_sp */ 44107035Sdavidxu#define KM_STACK_SIZE_OFFSET 40 /* offset to km_stack.ss_sp */ 45107035Sdavidxu#define KM_FUNC_OFFSET 32 /* offset to km_func */ 46103581Smini 47103581Smini/* 48103973Sarchie * int uts_to_thread(struct kse_thr_mailbox *tdp, 49103973Sarchie * struct kse_thr_mailbox **curthreadp); 50103581Smini * 51103581Smini * Does not return on success, returns -1 otherwise. 52103581Smini */ 53103581SminiENTRY(uts_to_thread) 54103973Sarchie movl 4(%esp), %edx /* get address of kse_thr_mailbox */ 55103581Smini /* .. ucontext_t is at offset 0 */ 56103581Smini cmpl $0, %edx /* check for null pointer */ 57103581Smini jne 1f 58103581Smini movl $-1, %eax 59103581Smini jmp 5f 60103581Smini1: cmpl $MC_SIZE, UC_MC_LEN_OFFSET(%edx) /* is context valid? */ 61103581Smini je 2f 62103581Smini movl $-1, %eax /* bzzzt, invalid context */ 63103581Smini jmp 5f 64103581Smini2: movl 8(%esp), %eax /* get address of curthreadp */ 65103581Smini movl %edx, (%eax) /* we're now the current thread */ 66103581Smini /* 67103581Smini * From here on, we don't touch the old stack. 68103581Smini */ 69103581Smini addl $UC_MC_OFFSET, %edx /* add offset to mcontext */ 70103581Smini movl 4(%edx), %gs 71103581Smini movl 8(%edx), %fs 72103581Smini movl 12(%edx), %es 73103581Smini movl 16(%edx), %ds 74103581Smini movl 76(%edx), %ss 75103581Smini movl 20(%edx), %edi 76103581Smini movl 24(%edx), %esi 77103581Smini movl 28(%edx), %ebp 78103581Smini movl 72(%edx), %esp /* switch to context defined stack */ 79103581Smini subl $4, %esp /* leave space for the return address */ 80103581Smini movl 60(%edx), %eax /* put return address at top of stack */ 81103581Smini movl %eax, (%esp) 82103581Smini cmpl $0, MC_OWNEDFP_OFFSET(%edx) /* are FP regs valid? */ 83103581Smini jz 3f 84103581Smini frstor MC_FP_REGS_OFFSET(%edx) /* restore FP regs */ 85103581Smini jmp 4f 86103581Smini3: fninit 87103581Smini fldcw MC_FP_CW_OFFSET(%edx) 88103581Smini4: movl 48(%edx), %eax /* restore ax, bx, cx */ 89103581Smini movl 36(%edx), %ebx 90103581Smini movl 44(%edx), %ecx 91103581Smini pushl 68(%edx) /* flags on stack */ 92103581Smini pushl 40(%edx) /* %edx on stack */ 93103581Smini popl %edx /* %edx off stack */ 94103581Smini popf /* flags off stack */ 95103581Smini5: ret /* %eip off stack */ 9699073Sjulian 9799073Sjulian/* 98103973Sarchie * int thread_to_uts(struct kse_thr_mailbox *tm, struct kse_mailbox *km); 99103581Smini * 100103581Smini * Does not return on success, returns -1 otherwise. 10199073Sjulian */ 102103581SminiENTRY(thread_to_uts) 103103581Smini movl 4(%esp), %eax /* get address of context */ 104103581Smini cmpl $0, %eax /* check for null pointer */ 105103581Smini jne 1f 106103581Smini movl $-1, %eax 107103581Smini jmp 2f 108103581Smini1: pushl %edx /* save value of edx */ 109103581Smini movl %eax, %edx /* get address of context */ 110103581Smini addl $UC_MC_OFFSET, %edx /* add offset to mcontext */ 111103581Smini movl %gs, 4(%edx) 112103581Smini movl %fs, 8(%edx) 113103581Smini movl %es, 12(%edx) 114103581Smini movl %ds, 16(%edx) 115103581Smini movl %edi, 20(%edx) 116103581Smini movl %esi, 24(%edx) 117103581Smini movl %ebp, 28(%edx) 118103581Smini movl %ebx, 36(%edx) 119103581Smini movl $0, 48(%edx) /* store successful return in eax */ 120103581Smini popl %eax /* get saved value of edx */ 121103581Smini movl %eax, 40(%edx) /* save edx */ 122103581Smini movl %ecx, 44(%edx) 123103581Smini movl (%esp), %eax /* get return address */ 124103581Smini movl %eax, 60(%edx) /* save return address */ 125103581Smini movl %ss, 76(%edx) 126103581Smini /* 127103581Smini * Don't save floating point registers here. 128103581Smini * 129103581Smini * This is an explicit call to get the current context, so 130103581Smini * the caller is done with the floating point registers. 131103581Smini * Contexts formed by involuntary switches, such as signal delivery, 132103581Smini * have floating point registers saved by the kernel. 133103581Smini */ 134103581Smini fnstcw MC_FP_CW_OFFSET(%edx) 135103581Smini movl $0, MC_OWNEDFP_OFFSET(%edx) /* no FP */ 136107138Sdavidxu pushfl /* get eflags */ 137107138Sdavidxu popl %eax 138103581Smini movl %eax, 68(%edx) /* store eflags */ 139103581Smini movl %esp, %eax /* setcontext pushes the return */ 140103581Smini addl $4, %eax /* address onto the top of the */ 141103581Smini movl %eax, 72(%edx) /* stack; account for this */ 142103581Smini movl $MC_SIZE, MC_LEN_OFFSET(%edx) /* context is now valid */ 143103581Smini movl 8(%esp), %edx /* get address of mailbox */ 144103581Smini movl KM_STACK_SP_OFFSET(%edx), %eax /* get bottom of stack */ 145103581Smini addl KM_STACK_SIZE_OFFSET(%edx), %eax /* add length */ 146103581Smini movl %eax, %esp /* switch to the uts's stack */ 147103581Smini pushl %edx /* push the address of the mailbox */ 148103581Smini pushl KM_FUNC_OFFSET(%edx) /* .. the uts can return to itself */ 149103581Smini pushl KM_FUNC_OFFSET(%edx) /* push the address of the uts func */ 150103581Smini2: ret 15199073Sjulian 152