pm_machdep.c revision 209613
1/*- 2 * Copyright (c) 1992 Terrence R. Lambert. 3 * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * William Jolitz. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 34 * from: src/sys/i386/i386/machdep.c,v 1.385.2.3 2000/05/10 02:04:46 obrien 35 * JNPR: pm_machdep.c,v 1.9.2.1 2007/08/16 15:59:10 girish 36 */ 37 38#include <sys/cdefs.h> 39__FBSDID("$FreeBSD: head/sys/mips/mips/pm_machdep.c 209613 2010-06-30 18:03:42Z jhb $"); 40 41#include "opt_compat.h" 42#include "opt_cputype.h" 43 44#include <sys/types.h> 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/sysent.h> 48#include <sys/proc.h> 49#include <sys/signalvar.h> 50#include <sys/exec.h> 51#include <sys/imgact.h> 52#include <sys/ucontext.h> 53#include <sys/lock.h> 54#include <sys/syscallsubr.h> 55#include <sys/sysproto.h> 56#include <sys/ptrace.h> 57#include <sys/syslog.h> 58#include <vm/vm.h> 59#include <vm/pmap.h> 60#include <vm/vm_map.h> 61#include <vm/vm_extern.h> 62#include <sys/user.h> 63#include <sys/uio.h> 64#include <machine/reg.h> 65#include <machine/md_var.h> 66#include <machine/sigframe.h> 67#include <machine/vmparam.h> 68#include <sys/vnode.h> 69#include <fs/pseudofs/pseudofs.h> 70#include <fs/procfs/procfs.h> 71 72#define UCONTEXT_MAGIC 0xACEDBADE 73 74/* 75 * Send an interrupt to process. 76 * 77 * Stack is set up to allow sigcode stored 78 * at top to call routine, followed by kcall 79 * to sigreturn routine below. After sigreturn 80 * resets the signal mask, the stack, and the 81 * frame pointer, it returns to the user 82 * specified pc, psl. 83 */ 84void 85sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 86{ 87 struct proc *p; 88 struct thread *td; 89 struct trapframe *regs; 90 struct sigacts *psp; 91 struct sigframe sf, *sfp; 92 int sig; 93 int oonstack; 94 95 td = curthread; 96 p = td->td_proc; 97 PROC_LOCK_ASSERT(p, MA_OWNED); 98 sig = ksi->ksi_signo; 99 psp = p->p_sigacts; 100 mtx_assert(&psp->ps_mtx, MA_OWNED); 101 102 regs = td->td_frame; 103 oonstack = sigonstack(regs->sp); 104 105 /* save user context */ 106 bzero(&sf, sizeof(struct sigframe)); 107 sf.sf_uc.uc_sigmask = *mask; 108 sf.sf_uc.uc_stack = td->td_sigstk; 109 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 110 sf.sf_uc.uc_mcontext.mc_pc = regs->pc; 111 sf.sf_uc.uc_mcontext.mullo = regs->mullo; 112 sf.sf_uc.uc_mcontext.mulhi = regs->mulhi; 113 sf.sf_uc.uc_mcontext.mc_regs[0] = UCONTEXT_MAGIC; /* magic number */ 114 bcopy((void *)®s->ast, (void *)&sf.sf_uc.uc_mcontext.mc_regs[1], 115 sizeof(sf.sf_uc.uc_mcontext.mc_regs) - sizeof(register_t)); 116 sf.sf_uc.uc_mcontext.mc_fpused = td->td_md.md_flags & MDTD_FPUSED; 117 if (sf.sf_uc.uc_mcontext.mc_fpused) { 118 /* if FPU has current state, save it first */ 119 if (td == PCPU_GET(fpcurthread)) 120 MipsSaveCurFPState(td); 121 bcopy((void *)&td->td_frame->f0, 122 (void *)sf.sf_uc.uc_mcontext.mc_fpregs, 123 sizeof(sf.sf_uc.uc_mcontext.mc_fpregs)); 124 } 125 126 /* Allocate and validate space for the signal handler context. */ 127 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 128 SIGISMEMBER(psp->ps_sigonstack, sig)) { 129 sfp = (struct sigframe *)((vm_offset_t)(td->td_sigstk.ss_sp + 130 td->td_sigstk.ss_size - sizeof(struct sigframe)) 131 & ~(sizeof(__int64_t) - 1)); 132 } else 133 sfp = (struct sigframe *)((vm_offset_t)(regs->sp - 134 sizeof(struct sigframe)) & ~(sizeof(__int64_t) - 1)); 135 136 /* Translate the signal if appropriate */ 137 if (p->p_sysent->sv_sigtbl) { 138 if (sig <= p->p_sysent->sv_sigsize) 139 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 140 } 141 142 /* Build the argument list for the signal handler. */ 143 regs->a0 = sig; 144 regs->a2 = (register_t)(intptr_t)&sfp->sf_uc; 145 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 146 /* Signal handler installed with SA_SIGINFO. */ 147 regs->a1 = (register_t)(intptr_t)&sfp->sf_si; 148 /* sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; */ 149 150 /* fill siginfo structure */ 151 sf.sf_si.si_signo = sig; 152 sf.sf_si.si_code = ksi->ksi_code; 153 sf.sf_si.si_addr = (void*)(intptr_t)regs->badvaddr; 154 } else { 155 /* Old FreeBSD-style arguments. */ 156 regs->a1 = ksi->ksi_code; 157 regs->a3 = regs->badvaddr; 158 /* sf.sf_ahu.sf_handler = catcher; */ 159 } 160 161 mtx_unlock(&psp->ps_mtx); 162 PROC_UNLOCK(p); 163 164 /* 165 * Copy the sigframe out to the user's stack. 166 */ 167 if (copyout(&sf, sfp, sizeof(struct sigframe)) != 0) { 168 /* 169 * Something is wrong with the stack pointer. 170 * ...Kill the process. 171 */ 172 PROC_LOCK(p); 173 sigexit(td, SIGILL); 174 } 175 176 regs->pc = (register_t)(intptr_t)catcher; 177 regs->t9 = (register_t)(intptr_t)catcher; 178 regs->sp = (register_t)(intptr_t)sfp; 179 /* 180 * Signal trampoline code is at base of user stack. 181 */ 182 regs->ra = (register_t)(intptr_t)PS_STRINGS - *(p->p_sysent->sv_szsigcode); 183 PROC_LOCK(p); 184 mtx_lock(&psp->ps_mtx); 185} 186 187#ifdef GONE_IN_7 188/* 189 * Build siginfo_t for SA thread 190 */ 191void 192cpu_thread_siginfo(int sig, u_long code, siginfo_t *si) 193{ 194 struct proc *p; 195 struct thread *td; 196 197 td = curthread; 198 p = td->td_proc; 199 PROC_LOCK_ASSERT(p, MA_OWNED); 200 201 bzero(si, sizeof(*si)); 202 si->si_signo = sig; 203 si->si_code = code; 204 /* XXXKSE fill other fields */ 205} 206#endif 207 208/* 209 * System call to cleanup state after a signal 210 * has been taken. Reset signal mask and 211 * stack state from context left by sendsig (above). 212 * Return to previous pc as specified by 213 * context left by sendsig. 214 */ 215int 216sigreturn(struct thread *td, struct sigreturn_args *uap) 217{ 218 struct trapframe *regs; 219 ucontext_t *ucp; 220 ucontext_t uc; 221 int error; 222 223 ucp = &uc; 224 225 error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 226 if (error != 0) 227 return (error); 228 229 regs = td->td_frame; 230 231/* #ifdef DEBUG */ 232 if (ucp->uc_mcontext.mc_regs[ZERO] != UCONTEXT_MAGIC) { 233 printf("sigreturn: pid %d, ucp %p\n", td->td_proc->p_pid, ucp); 234 printf(" old sp %p ra %p pc %p\n", 235 (void *)(intptr_t)regs->sp, (void *)(intptr_t)regs->ra, (void *)(intptr_t)regs->pc); 236 printf(" new sp %p ra %p pc %p z %p\n", 237 (void *)(intptr_t)ucp->uc_mcontext.mc_regs[SP], 238 (void *)(intptr_t)ucp->uc_mcontext.mc_regs[RA], 239 (void *)(intptr_t)ucp->uc_mcontext.mc_regs[PC], 240 (void *)(intptr_t)ucp->uc_mcontext.mc_regs[ZERO]); 241 return EINVAL; 242 } 243/* #endif */ 244 245 bcopy((const void *)&ucp->uc_mcontext.mc_regs[1], (void *)®s->ast, 246 sizeof(ucp->uc_mcontext.mc_regs) - sizeof(register_t)); 247 248 if (ucp->uc_mcontext.mc_fpused) 249 bcopy((const void *)ucp->uc_mcontext.mc_fpregs, 250 (void *)&td->td_frame->f0, 251 sizeof(ucp->uc_mcontext.mc_fpregs)); 252 253 regs->pc = ucp->uc_mcontext.mc_pc; 254 regs->mullo = ucp->uc_mcontext.mullo; 255 regs->mulhi = ucp->uc_mcontext.mulhi; 256 257 kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); 258 259 return(EJUSTRETURN); 260} 261 262 263int 264ptrace_set_pc(struct thread *td, unsigned long addr) 265{ 266 td->td_frame->pc = (register_t) addr; 267 return 0; 268} 269 270static int 271ptrace_read_int(struct thread *td, off_t addr, int *v) 272{ 273 struct iovec iov; 274 struct uio uio; 275 276 PROC_LOCK_ASSERT(td->td_proc, MA_NOTOWNED); 277 iov.iov_base = (caddr_t) v; 278 iov.iov_len = sizeof(int); 279 uio.uio_iov = &iov; 280 uio.uio_iovcnt = 1; 281 uio.uio_offset = (off_t)addr; 282 uio.uio_resid = sizeof(int); 283 uio.uio_segflg = UIO_SYSSPACE; 284 uio.uio_rw = UIO_READ; 285 uio.uio_td = td; 286 return proc_rwmem(td->td_proc, &uio); 287} 288 289static int 290ptrace_write_int(struct thread *td, off_t addr, int v) 291{ 292 struct iovec iov; 293 struct uio uio; 294 295 PROC_LOCK_ASSERT(td->td_proc, MA_NOTOWNED); 296 iov.iov_base = (caddr_t) &v; 297 iov.iov_len = sizeof(int); 298 uio.uio_iov = &iov; 299 uio.uio_iovcnt = 1; 300 uio.uio_offset = (off_t)addr; 301 uio.uio_resid = sizeof(int); 302 uio.uio_segflg = UIO_SYSSPACE; 303 uio.uio_rw = UIO_WRITE; 304 uio.uio_td = td; 305 return proc_rwmem(td->td_proc, &uio); 306} 307 308int 309ptrace_single_step(struct thread *td) 310{ 311 unsigned va; 312 struct trapframe *locr0 = td->td_frame; 313 int i; 314 int bpinstr = BREAK_SSTEP; 315 int curinstr; 316 struct proc *p; 317 318 p = td->td_proc; 319 PROC_UNLOCK(p); 320 /* 321 * Fetch what's at the current location. 322 */ 323 ptrace_read_int(td, (off_t)locr0->pc, &curinstr); 324 325 /* compute next address after current location */ 326 if(curinstr != 0) { 327 va = MipsEmulateBranch(locr0, locr0->pc, locr0->fsr, 328 (uintptr_t)&curinstr); 329 } else { 330 va = locr0->pc + 4; 331 } 332 if (td->td_md.md_ss_addr) { 333 printf("SS %s (%d): breakpoint already set at %x (va %x)\n", 334 p->p_comm, p->p_pid, td->td_md.md_ss_addr, va); /* XXX */ 335 return (EFAULT); 336 } 337 td->td_md.md_ss_addr = va; 338 /* 339 * Fetch what's at the current location. 340 */ 341 ptrace_read_int(td, (off_t)va, &td->td_md.md_ss_instr); 342 343 /* 344 * Store breakpoint instruction at the "next" location now. 345 */ 346 i = ptrace_write_int (td, va, bpinstr); 347 348 /* 349 * The sync'ing of I & D caches is done by procfs_domem() 350 * through procfs_rwmem(). 351 */ 352 353 PROC_LOCK(p); 354 if (i < 0) 355 return (EFAULT); 356#if 0 357 printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n", 358 p->p_comm, p->p_pid, p->p_md.md_ss_addr, 359 p->p_md.md_ss_instr, locr0->pc, curinstr); /* XXX */ 360#endif 361 return (0); 362} 363 364 365void 366makectx(struct trapframe *tf, struct pcb *pcb) 367{ 368 369 pcb->pcb_regs.ra = tf->ra; 370 pcb->pcb_regs.pc = tf->pc; 371 pcb->pcb_regs.sp = tf->sp; 372} 373 374int 375fill_regs(struct thread *td, struct reg *regs) 376{ 377 memcpy(regs, td->td_frame, sizeof(struct reg)); 378 return (0); 379} 380 381int 382set_regs(struct thread *td, struct reg *regs) 383{ 384 struct trapframe *f; 385 register_t sr; 386 387 f = (struct trapframe *) td->td_frame; 388 /* 389 * Don't allow the user to change SR 390 */ 391 sr = f->sr; 392 memcpy(td->td_frame, regs, sizeof(struct reg)); 393 f->sr = sr; 394 return (0); 395} 396 397int 398get_mcontext(struct thread *td, mcontext_t *mcp, int flags) 399{ 400 struct trapframe *tp; 401 402 tp = td->td_frame; 403 PROC_LOCK(curthread->td_proc); 404 mcp->mc_onstack = sigonstack(tp->sp); 405 PROC_UNLOCK(curthread->td_proc); 406 bcopy((void *)&td->td_frame->zero, (void *)&mcp->mc_regs, 407 sizeof(mcp->mc_regs)); 408 409 mcp->mc_fpused = td->td_md.md_flags & MDTD_FPUSED; 410 if (mcp->mc_fpused) { 411 bcopy((void *)&td->td_frame->f0, (void *)&mcp->mc_fpregs, 412 sizeof(mcp->mc_fpregs)); 413 } 414 if (flags & GET_MC_CLEAR_RET) { 415 mcp->mc_regs[V0] = 0; 416 mcp->mc_regs[V1] = 0; 417 mcp->mc_regs[A3] = 0; 418 } 419 420 mcp->mc_pc = td->td_frame->pc; 421 mcp->mullo = td->td_frame->mullo; 422 mcp->mulhi = td->td_frame->mulhi; 423 mcp->mc_tls = td->td_md.md_tls; 424 return (0); 425} 426 427int 428set_mcontext(struct thread *td, const mcontext_t *mcp) 429{ 430 struct trapframe *tp; 431 432 tp = td->td_frame; 433 bcopy((void *)&mcp->mc_regs, (void *)&td->td_frame->zero, 434 sizeof(mcp->mc_regs)); 435 436 td->td_md.md_flags = mcp->mc_fpused & MDTD_FPUSED; 437 if (mcp->mc_fpused) { 438 bcopy((void *)&mcp->mc_fpregs, (void *)&td->td_frame->f0, 439 sizeof(mcp->mc_fpregs)); 440 } 441 td->td_frame->pc = mcp->mc_pc; 442 td->td_frame->mullo = mcp->mullo; 443 td->td_frame->mulhi = mcp->mulhi; 444 td->td_md.md_tls = mcp->mc_tls; 445 /* Dont let user to set any bits in Status and casue registers */ 446 447 return (0); 448} 449 450int 451fill_fpregs(struct thread *td, struct fpreg *fpregs) 452{ 453 if (td == PCPU_GET(fpcurthread)) 454 MipsSaveCurFPState(td); 455 memcpy(fpregs, &td->td_frame->f0, sizeof(struct fpreg)); 456 return 0; 457} 458 459int 460set_fpregs(struct thread *td, struct fpreg *fpregs) 461{ 462 if (PCPU_GET(fpcurthread) == td) 463 PCPU_SET(fpcurthread, (struct thread *)0); 464 memcpy(&td->td_frame->f0, fpregs, sizeof(struct fpreg)); 465 return 0; 466} 467 468 469/* 470 * Clear registers on exec 471 * $sp is set to the stack pointer passed in. $pc is set to the entry 472 * point given by the exec_package passed in, as is $t9 (used for PIC 473 * code by the MIPS elf abi). 474 */ 475void 476exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) 477{ 478 479 bzero((caddr_t)td->td_frame, sizeof(struct trapframe)); 480 481 /* 482 * Make sp 64-bit aligned. 483 */ 484 td->td_frame->sp = ((register_t) stack) & ~(sizeof(__int64_t) - 1); 485 td->td_frame->pc = imgp->entry_addr & ~3; 486 td->td_frame->t9 = imgp->entry_addr & ~3; /* abicall req */ 487 td->td_frame->sr = SR_KSU_USER | SR_EXL | SR_INT_ENAB | 488 (mips_rd_status() & ALL_INT_MASK); 489#if defined(__mips_n32) || defined(__mips_n64) 490 td->td_frame->sr |= SR_PX; 491#endif 492#ifdef TARGET_OCTEON 493 td->td_frame->sr |= MIPS_SR_COP_2_BIT | MIPS32_SR_PX | MIPS_SR_UX | 494 MIPS_SR_KX | MIPS_SR_SX; 495#endif 496 /* 497 * FREEBSD_DEVELOPERS_FIXME: 498 * Setup any other CPU-Specific registers (Not MIPS Standard) 499 * and/or bits in other standard MIPS registers (if CPU-Specific) 500 * that are needed. 501 */ 502 503 /* 504 * Set up arguments for the rtld-capable crt0: 505 * a0 stack pointer 506 * a1 rtld cleanup (filled in by dynamic loader) 507 * a2 rtld object (filled in by dynamic loader) 508 * a3 ps_strings 509 */ 510 td->td_frame->a0 = (register_t) stack; 511 td->td_frame->a1 = 0; 512 td->td_frame->a2 = 0; 513 td->td_frame->a3 = (register_t)imgp->ps_strings; 514 515 td->td_md.md_flags &= ~MDTD_FPUSED; 516 if (PCPU_GET(fpcurthread) == td) 517 PCPU_SET(fpcurthread, (struct thread *)0); 518 td->td_md.md_ss_addr = 0; 519} 520 521int 522ptrace_clear_single_step(struct thread *td) 523{ 524 int i; 525 struct proc *p; 526 527 p = td->td_proc; 528 PROC_LOCK_ASSERT(p, MA_OWNED); 529 if (!td->td_md.md_ss_addr) 530 return EINVAL; 531 532 /* 533 * Restore original instruction and clear BP 534 */ 535 i = ptrace_write_int (td, td->td_md.md_ss_addr, td->td_md.md_ss_instr); 536 537 /* The sync'ing of I & D caches is done by procfs_domem(). */ 538 539 if (i < 0) { 540 log(LOG_ERR, "SS %s %d: can't restore instruction at %x: %x\n", 541 p->p_comm, p->p_pid, td->td_md.md_ss_addr, 542 td->td_md.md_ss_instr); 543 } 544 td->td_md.md_ss_addr = 0; 545 return 0; 546} 547