1 /* $NetBSD: pthread_md.h,v 1.5 2004/02/11 21:04:10 nathanw Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Nathan J. Williams. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #ifndef _LIB_PTHREAD_I386_MD_H 40 #define _LIB_PTHREAD_I386_MD_H 41 42 #include <sys/ucontext.h> 43 44 extern int (*_md_getcontext_u)(ucontext_t *); 45 extern int (*_md_setcontext_u)(const ucontext_t *); 46 extern int (*_md_swapcontext_u)(ucontext_t *, const ucontext_t *); 47 48 #define _getcontext_u(uc) (*_md_getcontext_u)((uc)) 49 #define _setcontext_u(uc) (*_md_setcontext_u)((uc)) 50 #define _swapcontext_u(ouc, nuc) (*_md_swapcontext_u)((ouc), (nuc)) 51 52 int _getcontext_u_s87(ucontext_t *); 53 int _setcontext_u_s87(const ucontext_t *); 54 int _swapcontext_u_s87(ucontext_t *, const ucontext_t *); 55 int _getcontext_u_xmm(ucontext_t *); 56 int _setcontext_u_xmm(const ucontext_t *); 57 int _swapcontext_u_xmm(ucontext_t *, const ucontext_t *); 58 59 void pthread__i386_init(void); 60 61 #define PTHREAD_MD_INIT pthread__i386_init(); 62 63 static __inline long 64 pthread__sp(void) 65 { 66 long ret; 67 __asm("movl %%esp, %0" : "=g" (ret)); 68 69 return ret; 70 } 71 72 #define pthread__uc_sp(ucp) ((ucp)->uc_mcontext.__gregs[_REG_UESP]) 73 #define pthread__uc_pc(ucp) ((ucp)->uc_mcontext.__gregs[_REG_EIP]) 74 75 /* 76 * Set initial, sane values for registers whose values aren't just 77 * "don't care". 78 * 0x2b is GSEL(GUDATA_SEL, SEL_UPL), and 79 * 0x23 is GSEL(GUCODE_SEL, SEL_UPL), from arch/i386/include/segments.h. 80 * 0x202 is PSL_USERSET from arch/i386/include/psl.h 81 */ 82 #define _INITCONTEXT_U_MD(ucp) \ 83 (ucp)->uc_mcontext.__gregs[_REG_GS] = 0x2b, \ 84 (ucp)->uc_mcontext.__gregs[_REG_FS] = 0x2b, \ 85 (ucp)->uc_mcontext.__gregs[_REG_ES] = 0x2b, \ 86 (ucp)->uc_mcontext.__gregs[_REG_DS] = 0x2b, \ 87 (ucp)->uc_mcontext.__gregs[_REG_CS] = 0x23, \ 88 (ucp)->uc_mcontext.__gregs[_REG_SS] = 0x2b, \ 89 (ucp)->uc_mcontext.__gregs[_REG_EFL] = 0x202; 90 91 /* 92 * Usable stack space below the ucontext_t. 93 * See comment in pthread_switch.S about STACK_SWITCH. 94 */ 95 #define STACKSPACE 32 /* room for 8 integer values */ 96 97 /* 98 * Conversions between struct reg and struct mcontext. Used by 99 * libpthread_dbg. 100 */ 101 102 #define PTHREAD_UCONTEXT_TO_REG(reg, uc) do { \ 103 (reg)->r_gs = (uc)->uc_mcontext.__gregs[_REG_GS]; \ 104 (reg)->r_fs = (uc)->uc_mcontext.__gregs[_REG_FS]; \ 105 (reg)->r_es = (uc)->uc_mcontext.__gregs[_REG_ES]; \ 106 (reg)->r_ds = (uc)->uc_mcontext.__gregs[_REG_DS]; \ 107 (reg)->r_edi = (uc)->uc_mcontext.__gregs[_REG_EDI]; \ 108 (reg)->r_esi = (uc)->uc_mcontext.__gregs[_REG_ESI]; \ 109 (reg)->r_ebp = (uc)->uc_mcontext.__gregs[_REG_EBP]; \ 110 (reg)->r_ebx = (uc)->uc_mcontext.__gregs[_REG_EBX]; \ 111 (reg)->r_edx = (uc)->uc_mcontext.__gregs[_REG_EDX]; \ 112 (reg)->r_ecx = (uc)->uc_mcontext.__gregs[_REG_ECX]; \ 113 (reg)->r_eax = (uc)->uc_mcontext.__gregs[_REG_EAX]; \ 114 (reg)->r_eip = (uc)->uc_mcontext.__gregs[_REG_EIP]; \ 115 (reg)->r_cs = (uc)->uc_mcontext.__gregs[_REG_CS]; \ 116 (reg)->r_eflags = (uc)->uc_mcontext.__gregs[_REG_EFL]; \ 117 (reg)->r_esp = (uc)->uc_mcontext.__gregs[_REG_UESP]; \ 118 (reg)->r_ss = (uc)->uc_mcontext.__gregs[_REG_SS]; \ 119 } while (/*CONSTCOND*/0) 120 121 #define PTHREAD_REG_TO_UCONTEXT(uc, reg) do { \ 122 (uc)->uc_mcontext.__gregs[_REG_GS] = (reg)->r_gs; \ 123 (uc)->uc_mcontext.__gregs[_REG_FS] = (reg)->r_fs; \ 124 (uc)->uc_mcontext.__gregs[_REG_ES] = (reg)->r_es; \ 125 (uc)->uc_mcontext.__gregs[_REG_DS] = (reg)->r_ds; \ 126 (uc)->uc_mcontext.__gregs[_REG_EDI] = (reg)->r_edi; \ 127 (uc)->uc_mcontext.__gregs[_REG_ESI] = (reg)->r_esi; \ 128 (uc)->uc_mcontext.__gregs[_REG_EBP] = (reg)->r_ebp; \ 129 (uc)->uc_mcontext.__gregs[_REG_EBX] = (reg)->r_ebx; \ 130 (uc)->uc_mcontext.__gregs[_REG_EDX] = (reg)->r_edx; \ 131 (uc)->uc_mcontext.__gregs[_REG_ECX] = (reg)->r_ecx; \ 132 (uc)->uc_mcontext.__gregs[_REG_EAX] = (reg)->r_eax; \ 133 (uc)->uc_mcontext.__gregs[_REG_EIP] = (reg)->r_eip; \ 134 (uc)->uc_mcontext.__gregs[_REG_CS] = (reg)->r_cs; \ 135 (uc)->uc_mcontext.__gregs[_REG_EFL] = (reg)->r_eflags; \ 136 (uc)->uc_mcontext.__gregs[_REG_UESP]= (reg)->r_esp; \ 137 (uc)->uc_mcontext.__gregs[_REG_SS] = (reg)->r_ss; \ 138 /*LINTED precision loss */ \ 139 (uc)->uc_flags = ((uc)->uc_flags | _UC_CPU) & ~_UC_USER; \ 140 } while (/*CONSTCOND*/0) 141 142 143 #define PTHREAD_UCONTEXT_TO_FPREG(freg, uc) \ 144 (void)memcpy((freg)->__data, \ 145 (uc)->uc_mcontext.__fpregs.__fp_reg_set.__fpchip_state.__fp_state, \ 146 sizeof(struct fpreg)) 147 148 #define PTHREAD_FPREG_TO_UCONTEXT(uc, freg) do { \ 149 (void)memcpy( \ 150 (uc)->uc_mcontext.__fpregs.__fp_reg_set.__fpchip_state.__fp_state, \ 151 (freg)->__data, sizeof(struct fpreg)); \ 152 /*LINTED precision loss */ \ 153 (uc)->uc_flags = ((uc)->uc_flags | _UC_FPU) & ~_UC_USER; \ 154 } while (/*CONSTCOND*/0) 155 156 #define PTHREAD_UCONTEXT_XREG_FLAG _UC_FXSAVE 157 158 #define PTHREAD_UCONTEXT_TO_XREG(xreg, uc) \ 159 (void)memcpy((xreg), \ 160 (uc)->uc_mcontext.__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm, \ 161 sizeof(struct xmmregs)) 162 163 #define PTHREAD_XREG_TO_UCONTEXT(uc, xreg) do { \ 164 (void)memcpy( \ 165 (uc)->uc_mcontext.__fpregs.__fp_reg_set.__fp_xmm_state.__fp_xmm, \ 166 (xreg), \ 167 sizeof(struct xmmregs)); \ 168 (uc)->uc_flags = ((uc)->uc_flags | _UC_FXSAVE) & ~_UC_USER; \ 169 } while (/*CONSTCOND*/0) 170 171 #endif /* _LIB_PTHREAD_I386_MD_H */ 172