kse_asm.S revision 103973
1/*
2 * Copyright (c) 2002 Jonathan Mini <mini@freebsd.org>.
3 * Copyright (c) 2001 Daniel Eischen <deischen@freebsd.org>.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Neither the name of the author nor the names of its contributors
12 *    may be used to endorse or promote products derived from this software
13 *    without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: head/tools/KSE/ksetest/kse_asm.S 103973 2002-09-25 18:14:38Z archie $
28 */
29
30#include <machine/asm.h>
31__FBSDID("$FreeBSD: head/tools/KSE/ksetest/kse_asm.S 103973 2002-09-25 18:14:38Z archie $");
32
33/*
34 * Where do we define these?
35 */
36#define	MC_SIZE			640	/* sizeof mcontext_t */
37#define	UC_MC_OFFSET		16	/* offset to mcontext from ucontext */
38#define	UC_MC_LEN_OFFSET	96	/* offset to mc_len from mcontext */
39#define	MC_LEN_OFFSET		80	/* offset to mc_len from mcontext */
40#define	MC_FP_REGS_OFFSET	96	/* offset to FP regs from mcontext */
41#define	MC_FP_CW_OFFSET		96	/* offset to FP control word */
42#define	MC_OWNEDFP_OFFSET	88	/* offset to mc_ownedfp from mcontext */
43#define	KM_STACK_SP_OFFSET	32	/* offset to km_stack.ss_sp */
44#define	KM_STACK_SIZE_OFFSET	36	/* offset to km_stack.ss_sp */
45#define	KM_FUNC_OFFSET		28	/* offset to km_func */
46
47/*
48 * int uts_to_thread(struct kse_thr_mailbox *tdp,
49 *	struct kse_thr_mailbox **curthreadp);
50 *
51 * Does not return on success, returns -1 otherwise.
52 */
53ENTRY(uts_to_thread)
54	movl	4(%esp), %edx		/* get address of kse_thr_mailbox */
55					/* .. ucontext_t is at offset 0 */
56	cmpl	$0, %edx		/* check for null pointer */
57	jne	1f
58	movl	$-1, %eax
59	jmp	5f
601:	cmpl	$MC_SIZE, UC_MC_LEN_OFFSET(%edx) /* is context valid? */
61	je	2f
62	movl	$-1, %eax		/* bzzzt, invalid context */
63	jmp	5f
642:	movl	8(%esp), %eax		/* get address of curthreadp */
65	movl	%edx, (%eax)		/* we're now the current thread */
66	/*
67	 * From here on, we don't touch the old stack.
68	 */
69	addl	$UC_MC_OFFSET, %edx	/* add offset to mcontext */
70	movl	4(%edx), %gs
71	movl	8(%edx), %fs
72	movl	12(%edx), %es
73	movl	16(%edx), %ds
74	movl	76(%edx), %ss
75	movl	20(%edx), %edi
76	movl	24(%edx), %esi
77	movl	28(%edx), %ebp
78	movl	72(%edx), %esp		/* switch to context defined stack */
79	subl	$4, %esp		/* leave space for the return address */
80	movl	60(%edx), %eax		/* put return address at top of stack */
81	movl	%eax, (%esp)
82	cmpl	$0, MC_OWNEDFP_OFFSET(%edx) /* are FP regs valid? */
83	jz	3f
84	frstor	MC_FP_REGS_OFFSET(%edx) /* restore FP regs */
85	jmp	4f
863:	fninit
87	fldcw	MC_FP_CW_OFFSET(%edx)
884:	movl	48(%edx), %eax		/* restore ax, bx, cx */
89	movl	36(%edx), %ebx
90	movl	44(%edx), %ecx
91	pushl	68(%edx)		/* flags on stack */
92	pushl	40(%edx)		/* %edx on stack  */
93	popl	%edx			/* %edx off stack */
94	popf				/* flags off stack */
955:	ret				/* %eip off stack */
96
97/*
98 * int thread_to_uts(struct kse_thr_mailbox *tm, struct kse_mailbox *km);
99 *
100 * Does not return on success, returns -1 otherwise.
101 */
102ENTRY(thread_to_uts)
103	movl	4(%esp), %eax		/* get address of context */
104	cmpl	$0, %eax		/* check for null pointer */
105	jne	1f
106	movl	$-1, %eax
107	jmp	2f
1081:	pushl	%edx			/* save value of edx */
109	movl	%eax, %edx		/* get address of context */
110	addl	$UC_MC_OFFSET, %edx	/* add offset to mcontext */
111	movl	%gs, 4(%edx)
112	movl	%fs, 8(%edx)
113	movl	%es, 12(%edx)
114	movl	%ds, 16(%edx)
115	movl	%edi, 20(%edx)
116	movl	%esi, 24(%edx)
117	movl	%ebp, 28(%edx)
118	movl	%ebx, 36(%edx)
119	movl	$0, 48(%edx)		/* store successful return in eax */
120	popl	%eax			/* get saved value of edx */
121	movl	%eax, 40(%edx)		/* save edx */
122	movl	%ecx, 44(%edx)
123	movl	(%esp), %eax		/* get return address */
124	movl	%eax, 60(%edx)		/* save return address */
125	movl	%ss, 76(%edx)
126	/*
127	 * Don't save floating point registers here.
128	 *
129	 * This is an explicit call to get the current context, so
130	 * the caller is done with the floating point registers.
131	 * Contexts formed by involuntary switches, such as signal delivery,
132	 * have floating point registers saved by the kernel.
133	 */
134	fnstcw	MC_FP_CW_OFFSET(%edx)
135	movl	$0, MC_OWNEDFP_OFFSET(%edx) /* no FP */
136	lahf				/* get eflags */
137	movl	%eax, 68(%edx)		/* store eflags */
138	movl	%esp, %eax		/* setcontext pushes the return  */
139	addl	$4, %eax		/*   address onto the top of the */
140	movl	%eax, 72(%edx)		/*   stack; account for this     */
141	movl	$MC_SIZE, MC_LEN_OFFSET(%edx) /* context is now valid */
142	movl	8(%esp), %edx		/* get address of mailbox */
143	movl	KM_STACK_SP_OFFSET(%edx), %eax	/* get bottom of stack */
144	addl	KM_STACK_SIZE_OFFSET(%edx), %eax /* add length */
145	movl	%eax, %esp		/* switch to the uts's stack */
146	pushl	%edx			/* push the address of the mailbox */
147	pushl	KM_FUNC_OFFSET(%edx)	/* .. the uts can return to itself */
148	pushl	KM_FUNC_OFFSET(%edx)	/* push the address of the uts func */
1492:	ret
150
151