kse_asm.S revision 107165
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 107165 2002-11-22 00:23:02Z julian $
2899073Sjulian */
2999073Sjulian
30103581Smini#include <machine/asm.h>
31103581Smini__FBSDID("$FreeBSD: head/tools/KSE/ksetest/kse_asm.S 107165 2002-11-22 00:23:02Z julian $");
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 */
65107165Sjulian	movl	%edx, %ebx		/* save the pointer for later */
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)
88107165Sjulian4:	pushl	68(%edx)		/* flags */
89107165Sjulian	pushl	48(%edx)		/* eax */
90107165Sjulian	pushl	36(%edx)		/* ebx */
91107165Sjulian	movl	40(%edx), %edx		/* edx */
92107165Sjulian	movl	%ebx, (%eax)		/* <---- set new mailbox pointer */
93107165Sjulian	popl	%ebx
94107165Sjulian	popl	%eax
95107165Sjulian	popf
96107165Sjulian5:	ret
9799073Sjulian
9899073Sjulian/*
99103973Sarchie * int thread_to_uts(struct kse_thr_mailbox *tm, struct kse_mailbox *km);
100103581Smini *
101103581Smini * Does not return on success, returns -1 otherwise.
10299073Sjulian */
103103581SminiENTRY(thread_to_uts)
104103581Smini	movl	4(%esp), %eax		/* get address of context */
105103581Smini	cmpl	$0, %eax		/* check for null pointer */
106103581Smini	jne	1f
107103581Smini	movl	$-1, %eax
108103581Smini	jmp	2f
109103581Smini1:	pushl	%edx			/* save value of edx */
110103581Smini	movl	%eax, %edx		/* get address of context */
111103581Smini	addl	$UC_MC_OFFSET, %edx	/* add offset to mcontext */
112103581Smini	movl	%gs, 4(%edx)
113103581Smini	movl	%fs, 8(%edx)
114103581Smini	movl	%es, 12(%edx)
115103581Smini	movl	%ds, 16(%edx)
116103581Smini	movl	%edi, 20(%edx)
117103581Smini	movl	%esi, 24(%edx)
118103581Smini	movl	%ebp, 28(%edx)
119103581Smini	movl	%ebx, 36(%edx)
120103581Smini	movl	$0, 48(%edx)		/* store successful return in eax */
121103581Smini	popl	%eax			/* get saved value of edx */
122103581Smini	movl	%eax, 40(%edx)		/* save edx */
123103581Smini	movl	%ecx, 44(%edx)
124103581Smini	movl	(%esp), %eax		/* get return address */
125103581Smini	movl	%eax, 60(%edx)		/* save return address */
126103581Smini	movl	%ss, 76(%edx)
127103581Smini	/*
128103581Smini	 * Don't save floating point registers here.
129103581Smini	 *
130103581Smini	 * This is an explicit call to get the current context, so
131103581Smini	 * the caller is done with the floating point registers.
132103581Smini	 * Contexts formed by involuntary switches, such as signal delivery,
133103581Smini	 * have floating point registers saved by the kernel.
134103581Smini	 */
135103581Smini	fnstcw	MC_FP_CW_OFFSET(%edx)
136103581Smini	movl	$0, MC_OWNEDFP_OFFSET(%edx) /* no FP */
137107138Sdavidxu	pushfl 				/* get eflags */
138107138Sdavidxu	popl	%eax
139103581Smini	movl	%eax, 68(%edx)		/* store eflags */
140103581Smini	movl	%esp, %eax		/* setcontext pushes the return  */
141103581Smini	addl	$4, %eax		/*   address onto the top of the */
142103581Smini	movl	%eax, 72(%edx)		/*   stack; account for this     */
143103581Smini	movl	$MC_SIZE, MC_LEN_OFFSET(%edx) /* context is now valid */
144103581Smini	movl	8(%esp), %edx		/* get address of mailbox */
145103581Smini	movl	KM_STACK_SP_OFFSET(%edx), %eax	/* get bottom of stack */
146103581Smini	addl	KM_STACK_SIZE_OFFSET(%edx), %eax /* add length */
147103581Smini	movl	%eax, %esp		/* switch to the uts's stack */
148103581Smini	pushl	%edx			/* push the address of the mailbox */
149103581Smini	pushl	KM_FUNC_OFFSET(%edx)	/* .. the uts can return to itself */
150103581Smini	pushl	KM_FUNC_OFFSET(%edx)	/* push the address of the uts func */
151103581Smini2:	ret
15299073Sjulian
153