summaryrefslogtreecommitdiffstats
path: root/tools/KSE/rr/kse_asm.S
blob: ac571f7f1aee9441915bfa6c0275e0bb9c48847e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * Copyright (c) 2002 Jonathan Mini <mini@freebsd.org>.
 * Copyright (c) 2001 Daniel Eischen <deischen@freebsd.org>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Neither the name of the author nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 */

#include <machine/asm.h>
__FBSDID("$FreeBSD$");

/*
 * Where do we define these?
 */
#define	MC_SIZE			640	/* sizeof mcontext_t */
#define	UC_MC_OFFSET		16	/* offset to mcontext from ucontext */
#define	UC_MC_LEN_OFFSET	96	/* offset to mc_len from mcontext */
#define	MC_LEN_OFFSET		80	/* offset to mc_len from mcontext */
#define	MC_FP_REGS_OFFSET	96	/* offset to FP regs from mcontext */
#define	MC_FP_CW_OFFSET		96	/* offset to FP control word */
#define	MC_OWNEDFP_OFFSET	88	/* offset to mc_ownedfp from mcontext */
#define	KM_STACK_SP_OFFSET	36	/* offset to km_stack.ss_sp */
#define	KM_STACK_SIZE_OFFSET	40	/* offset to km_stack.ss_sp */
#define	KM_FUNC_OFFSET		32	/* offset to km_func */
 
/*
 * int uts_to_thread(struct kse_thr_mailbox *tdp,
 *	struct kse_thr_mailbox **curthreadp);
 *
 * Does not return on success, returns -1 otherwise.
 */
ENTRY(uts_to_thread)
	movl	4(%esp), %edx		/* get address of kse_thr_mailbox */
					/* .. ucontext_t is at offset 0 */
	cmpl	$0, %edx		/* check for null pointer */
	jne	1f
	movl	$-1, %eax
	jmp	5f
1:	cmpl	$MC_SIZE, UC_MC_LEN_OFFSET(%edx) /* is context valid? */
	je	2f
	movl	$-1, %eax		/* bzzzt, invalid context */
	jmp	5f
2:	movl	8(%esp), %ecx		/* get address of curthreadp */
	movl	%edx, %ebx		/* save the pointer for later */
	/*
	 * From here on, we don't touch the old stack.
	 */
	addl	$UC_MC_OFFSET, %edx	/* add offset to mcontext */
	movl	4(%edx), %gs
	movl	8(%edx), %fs
	movl	12(%edx), %es
	movl	16(%edx), %ds
	movl	76(%edx), %ss
	movl	20(%edx), %edi
	movl	24(%edx), %esi
	movl	28(%edx), %ebp
	movl	72(%edx), %esp		/* switch to context defined stack */
	subl	$4, %esp		/* leave space for the return address */
	movl	60(%edx), %eax		/* put return address at top of stack */
	movl	%eax, (%esp)
	cmpl	$0, MC_OWNEDFP_OFFSET(%edx) /* are FP regs valid? */
	jz	3f
	frstor	MC_FP_REGS_OFFSET(%edx) /* restore FP regs */
	jmp	4f
3:	fninit
	fldcw	MC_FP_CW_OFFSET(%edx)
4:	movl	48(%edx), %eax		/* restore ax, bx, cx, dx */
	pushl	68(%edx)		/* flags on stack */
	pushl	36(%edx)		/* %ebx on stack */
	pushl	44(%edx)		/* %ecx on stack */
	movl	40(%edx), %edx		/* %edx */
	/* 
	 * all registers are now moved out of mailbox, 
	 * it's safe to set current thread pointer
	 */
	movl	%ebx,(%ecx)
	popl	%ecx			/* %ecx off stack */
	pop	%ebx			/* %ebx off stack */
	popf				/* flags off stack */
5:	ret				/* %eip off stack */
END(uts_to_thread)

/*
 * int thread_to_uts(struct kse_thr_mailbox *tm, struct kse_mailbox *km);
 *
 * Does not return on success, returns -1 otherwise.
 */
ENTRY(thread_to_uts)
	movl	4(%esp), %eax		/* get address of context */
	cmpl	$0, %eax		/* check for null pointer */
	jne	1f
	movl	$-1, %eax
	jmp	2f
1:	pushl	%edx			/* save value of edx */
	movl	%eax, %edx		/* get address of context */
	addl	$UC_MC_OFFSET, %edx	/* add offset to mcontext */
	movl	%gs, 4(%edx)
	movl	%fs, 8(%edx)
	movl	%es, 12(%edx)
	movl	%ds, 16(%edx)
	movl	%edi, 20(%edx)
	movl	%esi, 24(%edx)
	movl	%ebp, 28(%edx)
	movl	%ebx, 36(%edx)
	movl	$0, 48(%edx)		/* store successful return in eax */
	popl	%eax			/* get saved value of edx */
	movl	%eax, 40(%edx)		/* save edx */
	movl	%ecx, 44(%edx)
	movl	(%esp), %eax		/* get return address */
	movl	%eax, 60(%edx)		/* save return address */
	movl	%ss, 76(%edx)
	/*
	 * Don't save floating point registers here.
	 *
	 * This is an explicit call to get the current context, so
	 * the caller is done with the floating point registers.
	 * Contexts formed by involuntary switches, such as signal delivery,
	 * have floating point registers saved by the kernel.
	 */
	fnstcw	MC_FP_CW_OFFSET(%edx)
	movl	$0, MC_OWNEDFP_OFFSET(%edx) /* no FP */
	pushfl 				/* get eflags */
	popl	%eax
	movl	%eax, 68(%edx)		/* store eflags */
	movl	%esp, %eax		/* setcontext pushes the return  */
	addl	$4, %eax		/*   address onto the top of the */
	movl	%eax, 72(%edx)		/*   stack; account for this     */
	movl	$MC_SIZE, MC_LEN_OFFSET(%edx) /* context is now valid */
	movl	8(%esp), %edx		/* get address of mailbox */
	movl	KM_STACK_SP_OFFSET(%edx), %eax	/* get bottom of stack */
	addl	KM_STACK_SIZE_OFFSET(%edx), %eax /* add length */
	movl	%eax, %esp		/* switch to the uts's stack */
	pushl	%edx			/* push the address of the mailbox */
	pushl	KM_FUNC_OFFSET(%edx)	/* .. the uts can return to itself */
	pushl	KM_FUNC_OFFSET(%edx)	/* push the address of the uts func */
2:	ret
END(thread_to_uts)

OpenPOWER on IntegriCloud