1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 22 /* All Rights Reserved */ 23 24 25 /* 26 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <sys/param.h> 33 #include <sys/types.h> 34 #include <sys/vmparam.h> 35 #include <sys/systm.h> 36 #include <sys/signal.h> 37 #include <sys/stack.h> 38 #include <sys/regset.h> 39 #include <sys/privregs.h> 40 #include <sys/frame.h> 41 #include <sys/proc.h> 42 #include <sys/psw.h> 43 #include <sys/ucontext.h> 44 #include <sys/asm_linkage.h> 45 #include <sys/errno.h> 46 #include <sys/archsystm.h> 47 #include <sys/schedctl.h> 48 #include <sys/debug.h> 49 #include <sys/sysmacros.h> 50 51 /* 52 * Save user context. 53 */ 54 void 55 savecontext(ucontext_t *ucp, k_sigset_t mask) 56 { 57 proc_t *p = ttoproc(curthread); 58 klwp_t *lwp = ttolwp(curthread); 59 struct regs *rp = lwptoregs(lwp); 60 61 /* 62 * We unconditionally assign to every field through the end 63 * of the gregs, but we need to bzero() everything -after- that 64 * to avoid having any kernel stack garbage escape to userland. 65 */ 66 bzero(&ucp->uc_mcontext.fpregs, sizeof (ucontext_t) - 67 offsetof(ucontext_t, uc_mcontext.fpregs)); 68 69 ucp->uc_flags = UC_ALL; 70 ucp->uc_link = (struct ucontext *)lwp->lwp_oldcontext; 71 72 /* 73 * Try to copyin() the ustack if one is registered. If the stack 74 * has zero size, this indicates that stack bounds checking has 75 * been disabled for this LWP. If stack bounds checking is disabled 76 * or the copyin() fails, we fall back to the legacy behavior. 77 */ 78 if (lwp->lwp_ustack == NULL || 79 copyin((void *)lwp->lwp_ustack, &ucp->uc_stack, 80 sizeof (ucp->uc_stack)) != 0 || 81 ucp->uc_stack.ss_size == 0) { 82 83 if (lwp->lwp_sigaltstack.ss_flags == SS_ONSTACK) { 84 ucp->uc_stack = lwp->lwp_sigaltstack; 85 } else { 86 ucp->uc_stack.ss_sp = p->p_usrstack - p->p_stksize; 87 ucp->uc_stack.ss_size = p->p_stksize; 88 ucp->uc_stack.ss_flags = 0; 89 } 90 } 91 92 getgregs(lwp, ucp->uc_mcontext.gregs); 93 if (lwp->lwp_pcb.pcb_fpu.fpu_flags & FPU_EN) 94 getfpregs(lwp, &ucp->uc_mcontext.fpregs); 95 else 96 ucp->uc_flags &= ~UC_FPU; 97 98 sigktou(&mask, &ucp->uc_sigmask); 99 /* 100 * If the trace flag is set, arrange for single-stepping and 101 * turn off the trace flag. 102 */ 103 if (rp->r_ps & PS_T) { 104 lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING; 105 rp->r_ps &= ~PS_T; 106 } 107 } 108 109 /* 110 * Restore user context. 111 */ 112 void 113 restorecontext(ucontext_t *ucp) 114 { 115 kthread_t *t = curthread; 116 klwp_t *lwp = ttolwp(t); 117 118 lwp->lwp_oldcontext = (uintptr_t)ucp->uc_link; 119 120 if (ucp->uc_flags & UC_STACK) { 121 if (ucp->uc_stack.ss_flags == SS_ONSTACK) 122 lwp->lwp_sigaltstack = ucp->uc_stack; 123 else 124 lwp->lwp_sigaltstack.ss_flags &= ~SS_ONSTACK; 125 } 126 127 if (ucp->uc_flags & UC_CPU) { 128 /* 129 * If the trace flag is set, mark the lwp to take a 130 * single-step trap on return to user level (below). 131 * The x86 lcall interface and sysenter has already done this, 132 * and turned off the flag, but amd64 syscall interface has not. 133 */ 134 if (lwptoregs(lwp)->r_ps & PS_T) 135 lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING; 136 setgregs(lwp, ucp->uc_mcontext.gregs); 137 lwp->lwp_eosys = JUSTRETURN; 138 t->t_post_sys = 1; 139 } 140 141 if (ucp->uc_flags & UC_FPU) 142 setfpregs(lwp, &ucp->uc_mcontext.fpregs); 143 144 if (ucp->uc_flags & UC_SIGMASK) { 145 proc_t *p = ttoproc(t); 146 147 mutex_enter(&p->p_lock); 148 schedctl_finish_sigblock(t); 149 sigutok(&ucp->uc_sigmask, &t->t_hold); 150 if (sigcheck(p, t)) 151 t->t_sig_check = 1; 152 mutex_exit(&p->p_lock); 153 } 154 } 155 156 157 int 158 getsetcontext(int flag, void *arg) 159 { 160 ucontext_t uc; 161 ucontext_t *ucp; 162 klwp_t *lwp = ttolwp(curthread); 163 stack_t dummy_stk; 164 165 /* 166 * In future releases, when the ucontext structure grows, 167 * getcontext should be modified to only return the fields 168 * specified in the uc_flags. That way, the structure can grow 169 * and still be binary compatible will all .o's which will only 170 * have old fields defined in uc_flags 171 */ 172 173 switch (flag) { 174 default: 175 return (set_errno(EINVAL)); 176 177 case GETCONTEXT: 178 if (schedctl_sigblock(curthread)) { 179 proc_t *p = ttoproc(curthread); 180 mutex_enter(&p->p_lock); 181 schedctl_finish_sigblock(curthread); 182 mutex_exit(&p->p_lock); 183 } 184 savecontext(&uc, curthread->t_hold); 185 if (copyout(&uc, arg, sizeof (uc))) 186 return (set_errno(EFAULT)); 187 return (0); 188 189 case SETCONTEXT: 190 ucp = arg; 191 if (ucp == NULL) 192 exit(CLD_EXITED, 0); 193 /* 194 * Don't copyin filler or floating state unless we need it. 195 * The ucontext_t struct and fields are specified in the ABI. 196 */ 197 if (copyin(ucp, &uc, sizeof (ucontext_t) - 198 sizeof (uc.uc_filler) - 199 sizeof (uc.uc_mcontext.fpregs))) { 200 return (set_errno(EFAULT)); 201 } 202 203 if ((uc.uc_flags & UC_FPU) && 204 copyin(&ucp->uc_mcontext.fpregs, &uc.uc_mcontext.fpregs, 205 sizeof (uc.uc_mcontext.fpregs))) { 206 return (set_errno(EFAULT)); 207 } 208 209 restorecontext(&uc); 210 211 if ((uc.uc_flags & UC_STACK) && (lwp->lwp_ustack != 0)) 212 (void) copyout(&uc.uc_stack, (stack_t *)lwp->lwp_ustack, 213 sizeof (uc.uc_stack)); 214 return (0); 215 216 case GETUSTACK: 217 if (copyout(&lwp->lwp_ustack, arg, sizeof (caddr_t))) 218 return (set_errno(EFAULT)); 219 return (0); 220 221 case SETUSTACK: 222 if (copyin(arg, &dummy_stk, sizeof (dummy_stk))) 223 return (set_errno(EFAULT)); 224 lwp->lwp_ustack = (uintptr_t)arg; 225 return (0); 226 } 227 } 228 229 #ifdef _SYSCALL32_IMPL 230 231 /* 232 * Save user context for 32-bit processes. 233 */ 234 void 235 savecontext32(ucontext32_t *ucp, k_sigset_t mask) 236 { 237 proc_t *p = ttoproc(curthread); 238 klwp_t *lwp = ttolwp(curthread); 239 struct regs *rp = lwptoregs(lwp); 240 241 bzero(&ucp->uc_mcontext.fpregs, sizeof (ucontext32_t) - 242 offsetof(ucontext32_t, uc_mcontext.fpregs)); 243 244 ucp->uc_flags = UC_ALL; 245 ucp->uc_link = (caddr32_t)lwp->lwp_oldcontext; 246 247 if (lwp->lwp_ustack == NULL || 248 copyin((void *)lwp->lwp_ustack, &ucp->uc_stack, 249 sizeof (ucp->uc_stack)) != 0 || 250 ucp->uc_stack.ss_size == 0) { 251 252 if (lwp->lwp_sigaltstack.ss_flags == SS_ONSTACK) { 253 ucp->uc_stack.ss_sp = 254 (caddr32_t)(uintptr_t)lwp->lwp_sigaltstack.ss_sp; 255 ucp->uc_stack.ss_size = 256 (size32_t)lwp->lwp_sigaltstack.ss_size; 257 ucp->uc_stack.ss_flags = SS_ONSTACK; 258 } else { 259 ucp->uc_stack.ss_sp = (caddr32_t)(uintptr_t) 260 (p->p_usrstack - p->p_stksize); 261 ucp->uc_stack.ss_size = (size32_t)p->p_stksize; 262 ucp->uc_stack.ss_flags = 0; 263 } 264 } 265 266 getgregs32(lwp, ucp->uc_mcontext.gregs); 267 if (lwp->lwp_pcb.pcb_fpu.fpu_flags & FPU_EN) 268 getfpregs32(lwp, &ucp->uc_mcontext.fpregs); 269 else 270 ucp->uc_flags &= ~UC_FPU; 271 272 sigktou(&mask, &ucp->uc_sigmask); 273 /* 274 * If the trace flag is set, arrange for single-stepping and 275 * turn off the trace flag. 276 */ 277 if (rp->r_ps & PS_T) { 278 lwp->lwp_pcb.pcb_flags |= DEBUG_PENDING; 279 rp->r_ps &= ~PS_T; 280 } 281 } 282 283 int 284 getsetcontext32(int flag, void *arg) 285 { 286 ucontext32_t uc; 287 ucontext_t ucnat; 288 ucontext32_t *ucp; 289 klwp_t *lwp = ttolwp(curthread); 290 caddr32_t ustack32; 291 stack32_t dummy_stk32; 292 293 switch (flag) { 294 default: 295 return (set_errno(EINVAL)); 296 297 case GETCONTEXT: 298 if (schedctl_sigblock(curthread)) { 299 proc_t *p = ttoproc(curthread); 300 mutex_enter(&p->p_lock); 301 schedctl_finish_sigblock(curthread); 302 mutex_exit(&p->p_lock); 303 } 304 savecontext32(&uc, curthread->t_hold); 305 if (copyout(&uc, arg, sizeof (uc))) 306 return (set_errno(EFAULT)); 307 return (0); 308 309 case SETCONTEXT: 310 ucp = arg; 311 if (ucp == NULL) 312 exit(CLD_EXITED, 0); 313 if (copyin(ucp, &uc, sizeof (uc) - 314 sizeof (uc.uc_filler) - 315 sizeof (uc.uc_mcontext.fpregs))) { 316 return (set_errno(EFAULT)); 317 } 318 if ((uc.uc_flags & UC_FPU) && 319 copyin(&ucp->uc_mcontext.fpregs, &uc.uc_mcontext.fpregs, 320 sizeof (uc.uc_mcontext.fpregs))) { 321 return (set_errno(EFAULT)); 322 } 323 324 ucontext_32ton(&uc, &ucnat); 325 restorecontext(&ucnat); 326 327 if ((uc.uc_flags & UC_STACK) && (lwp->lwp_ustack != 0)) 328 (void) copyout(&uc.uc_stack, 329 (stack32_t *)lwp->lwp_ustack, sizeof (uc.uc_stack)); 330 return (0); 331 332 case GETUSTACK: 333 ustack32 = (caddr32_t)lwp->lwp_ustack; 334 if (copyout(&ustack32, arg, sizeof (ustack32))) 335 return (set_errno(EFAULT)); 336 return (0); 337 338 case SETUSTACK: 339 if (copyin(arg, &dummy_stk32, sizeof (dummy_stk32))) 340 return (set_errno(EFAULT)); 341 lwp->lwp_ustack = (uintptr_t)arg; 342 return (0); 343 } 344 } 345 346 #endif /* _SYSCALL32_IMPL */ 347