]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/KSE/ksetest/kse_asm.S
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / tools / KSE / ksetest / kse_asm.S
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$
28  */
29
30 #include <machine/asm.h>
31 __FBSDID("$FreeBSD$");
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      36      /* offset to km_stack.ss_sp */
44 #define KM_STACK_SIZE_OFFSET    40      /* offset to km_stack.ss_sp */
45 #define KM_FUNC_OFFSET          32      /* 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  */
53 ENTRY(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
60 1:      cmpl    $MC_SIZE, UC_MC_LEN_OFFSET(%edx) /* is context valid? */
61         je      2f
62         movl    $-1, %eax               /* bzzzt, invalid context */
63         jmp     5f
64 2:      movl    8(%esp), %ecx           /* get address of curthreadp */
65         movl    %edx, %ebx              /* save the pointer for later */
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
86 3:      fninit
87         fldcw   MC_FP_CW_OFFSET(%edx)
88 4:      movl    48(%edx), %eax          /* restore ax, bx, cx, dx */
89         pushl   68(%edx)                /* flags on stack */
90         pushl   36(%edx)                /* %ebx on stack */
91         pushl   44(%edx)                /* %ecx on stack */
92         movl    40(%edx), %edx          /* %edx */
93         /* 
94          * all registers are now moved out of mailbox, 
95          * it's safe to set current thread pointer
96          */
97         movl    %ebx,(%ecx)
98         popl    %ecx                    /* %ecx off stack */
99         pop     %ebx                    /* %ebx off stack */
100         popf                            /* flags off stack */
101 5:      ret                             /* %eip off stack */
102 END(uts_to_thread)
103
104 /*
105  * int thread_to_uts(struct kse_thr_mailbox *tm, struct kse_mailbox *km);
106  *
107  * Does not return on success, returns -1 otherwise.
108  */
109 ENTRY(thread_to_uts)
110         movl    4(%esp), %eax           /* get address of context */
111         cmpl    $0, %eax                /* check for null pointer */
112         jne     1f
113         movl    $-1, %eax
114         jmp     2f
115 1:      pushl   %edx                    /* save value of edx */
116         movl    %eax, %edx              /* get address of context */
117         addl    $UC_MC_OFFSET, %edx     /* add offset to mcontext */
118         movl    %gs, 4(%edx)
119         movl    %fs, 8(%edx)
120         movl    %es, 12(%edx)
121         movl    %ds, 16(%edx)
122         movl    %edi, 20(%edx)
123         movl    %esi, 24(%edx)
124         movl    %ebp, 28(%edx)
125         movl    %ebx, 36(%edx)
126         movl    $0, 48(%edx)            /* store successful return in eax */
127         popl    %eax                    /* get saved value of edx */
128         movl    %eax, 40(%edx)          /* save edx */
129         movl    %ecx, 44(%edx)
130         movl    (%esp), %eax            /* get return address */
131         movl    %eax, 60(%edx)          /* save return address */
132         movl    %ss, 76(%edx)
133         /*
134          * Don't save floating point registers here.
135          *
136          * This is an explicit call to get the current context, so
137          * the caller is done with the floating point registers.
138          * Contexts formed by involuntary switches, such as signal delivery,
139          * have floating point registers saved by the kernel.
140          */
141         fnstcw  MC_FP_CW_OFFSET(%edx)
142         movl    $0, MC_OWNEDFP_OFFSET(%edx) /* no FP */
143         pushfl                          /* get eflags */
144         popl    %eax
145         movl    %eax, 68(%edx)          /* store eflags */
146         movl    %esp, %eax              /* setcontext pushes the return  */
147         addl    $4, %eax                /*   address onto the top of the */
148         movl    %eax, 72(%edx)          /*   stack; account for this     */
149         movl    $MC_SIZE, MC_LEN_OFFSET(%edx) /* context is now valid */
150         movl    8(%esp), %edx           /* get address of mailbox */
151         movl    KM_STACK_SP_OFFSET(%edx), %eax  /* get bottom of stack */
152         addl    KM_STACK_SIZE_OFFSET(%edx), %eax /* add length */
153         movl    %eax, %esp              /* switch to the uts's stack */
154         pushl   %edx                    /* push the address of the mailbox */
155         pushl   KM_FUNC_OFFSET(%edx)    /* .. the uts can return to itself */
156         pushl   KM_FUNC_OFFSET(%edx)    /* push the address of the uts func */
157 2:      ret
158 END(thread_to_uts)
159