1 /* $NetBSD: trap.c,v 1.74 2022/05/28 21:14:56 andvar Exp $ */ 2 3 /*- 4 * Copyright (c) 2011 Reinoud Zandijk <reinoud (at) netbsd.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.74 2022/05/28 21:14:56 andvar Exp $"); 31 32 #include <sys/types.h> 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/proc.h> 36 #include <sys/systm.h> 37 #include <sys/userret.h> 38 #include <sys/kauth.h> 39 #include <sys/errno.h> 40 41 #include <uvm/uvm_extern.h> 42 #include <machine/cpu.h> 43 #include <machine/pcb.h> 44 #include <machine/pmap.h> 45 #include <machine/machdep.h> 46 #include <machine/intr.h> 47 #include <machine/thunk.h> 48 49 #include "opt_kgdb.h" 50 51 #ifdef KGDB 52 #include <sys/kgdb.h> 53 #endif 54 55 /* define maximum signal number */ 56 #ifndef NSIG 57 #define NSIG 64 58 #endif 59 60 /* forwards and externals */ 61 void setup_signal_handlers(void); 62 void stop_all_signal_handlers(void); 63 64 static sigfunc_t pagefault; 65 static sigfunc_t illegal_instruction; 66 static sigfunc_t alarm; 67 static sigfunc_t sigio; 68 static sigfunc_t pass_on; 69 70 void kgdb_kernel_trap(int signo, vaddr_t pc, vaddr_t va, ucontext_t *ctx); 71 72 /* raw signal handlers */ 73 static char sig_stack[SIGSTKSZ]; 74 static stack_t sigstk; 75 ucontext_t jump_ucp; 76 77 sigfunc_t *sig_funcs[NSIG]; 78 79 /* segv, bus */ 80 extern bool pmap_fault(pmap_t pmap, vaddr_t va, vm_prot_t *atype); 81 82 /* alarm */ 83 void setup_clock_intr(void); 84 extern void clock_intr(void *priv); 85 86 extern int clock_running; 87 void *alrm_ih; 88 89 /* sigio handlers */ 90 struct intr_handler { 91 int (*func)(void *); 92 void *arg; 93 }; 94 #define SIGIO_MAX_HANDLERS 8 95 static struct intr_handler sigio_intr_handler[SIGIO_MAX_HANDLERS]; 96 97 /* misc */ 98 int astpending = 0; 99 100 101 /* XXX why is it here ? */ 102 void 103 startlwp(void *arg) 104 { 105 /* nothing here */ 106 } 107 108 109 void 110 setup_signal_handlers(void) 111 { 112 int i; 113 114 /* 115 * Set up the alternative signal stack. This prevents signals to be 116 * pushed on the NetBSD/usermode userland's stack with all desastrous 117 * effects. Especially ld.so and friends have such tiny stacks that 118 * its not feasible. 119 */ 120 sigstk.ss_sp = sig_stack; 121 sigstk.ss_size = SIGSTKSZ; 122 sigstk.ss_flags = 0; 123 if (thunk_sigaltstack(&sigstk, 0) < 0) 124 panic("can't set alternate stacksize: %d", 125 thunk_geterrno()); 126 127 for (i = 0; i < NSIG; i++) 128 sig_funcs[i] = NULL; 129 130 /* HUP */ 131 /* INT */ /* ttycons ^C */ 132 /* QUIT */ 133 signal_intr_establish(SIGILL, illegal_instruction); 134 signal_intr_establish(SIGTRAP, pass_on); /* special */ 135 /* ABRT */ 136 /* SIGEMT */ 137 signal_intr_establish(SIGFPE, pass_on); 138 /* KILL */ 139 signal_intr_establish(SIGBUS, pagefault); 140 signal_intr_establish(SIGSEGV, pagefault); 141 /* SYS */ 142 /* PIPE */ 143 signal_intr_establish(SIGALRM, alarm); 144 /* TERM */ 145 /* URG */ 146 /* STOP */ 147 /* TSTP */ /* ttycons ^Z */ 148 /* CONT */ 149 /* CHLD */ 150 /* GTTIN */ 151 /* TTOU */ 152 signal_intr_establish(SIGIO, sigio); 153 /* XCPU */ 154 /* XFSZ */ 155 /* VTALRM */ 156 /* PROF */ 157 /* WINCH */ 158 /* INFO */ 159 /* USR1 */ 160 /* USR2 */ 161 /* PWR */ 162 } 163 164 165 /* XXX yes this is blunt */ 166 void 167 stop_all_signal_handlers(void) 168 { 169 int i; 170 for (i = 0; i < NSIG; i++) 171 if (sig_funcs[i]) 172 thunk_sigblock(i); 173 } 174 175 176 void 177 setup_clock_intr(void) 178 { 179 /* setup soft interrupt handler */ 180 alrm_ih = softint_establish(SOFTINT_CLOCK, 181 clock_intr, NULL); 182 } 183 184 185 /* ast and userret */ 186 static void 187 ast(struct lwp *l) 188 { 189 struct pcb *pcb; 190 191 curcpu()->ci_data.cpu_ntrap++; 192 193 do { 194 astpending = 0; 195 mi_userret(l); 196 } while (astpending); 197 198 #if 0 199 /* profiling */ 200 if (l->l_pflag & LP_OWEUPC) { 201 l->l_pflag &= ~LP_OWEUPC; 202 ADDUPROF(l); 203 } 204 #endif 205 206 KASSERT(l == curlwp); KASSERT(l); 207 pcb = lwp_getpcb(l); KASSERT(pcb); 208 } 209 210 211 void 212 userret(struct lwp *l) 213 { 214 /* invoke MI userret code */ 215 mi_userret(l); 216 217 ast(l); 218 } 219 220 221 #ifdef DEBUG 222 /* 223 * Uncomment the following if you want to receive information about what 224 * triggered the fault. Mainly for debugging and porting purposes 225 */ 226 static void 227 print_mem_access_siginfo(int sig, siginfo_t *info, void *ctx, 228 vaddr_t pc, vaddr_t va, vaddr_t sp) 229 { 230 #if 0 231 thunk_printf_debug("SIGSEGV or SIGBUS!\n"); 232 thunk_printf_debug("\tsi_signo = %d\n", info->si_signo); 233 thunk_printf_debug("\tsi_errno = %d\n", info->si_errno); 234 thunk_printf_debug("\tsi_code = %d\n", info->si_code); 235 if (info->si_code == SEGV_MAPERR) 236 thunk_printf_debug("\t\tSEGV_MAPERR\n"); 237 if (info->si_code == SEGV_ACCERR) 238 thunk_printf_debug("\t\tSEGV_ACCERR\n"); 239 if (info->si_code == BUS_ADRALN) 240 thunk_printf_debug("\t\tBUS_ADRALN\n"); 241 if (info->si_code == BUS_ADRERR) 242 thunk_printf_debug("\t\tBUS_ADRERR\n"); 243 if (info->si_code == BUS_OBJERR) 244 thunk_printf_debug("\t\tBUS_OBJERR\n"); 245 thunk_printf_debug("\tsi_addr = %p\n", info->si_addr); 246 thunk_printf_debug("\tsi_trap = %d\n", info->si_trap); 247 #endif 248 249 #if 0 250 thunk_printf("memaccess error, pc %p, va %p, sp %p\n", 251 (void *) pc, (void *) va, (void *) sp); 252 #endif 253 } 254 255 /* 256 * Uncomment the following if you want to receive information about what 257 * triggered the fault. Mainly for debugging and porting purposes 258 */ 259 static void 260 print_illegal_instruction_siginfo(int sig, siginfo_t *info, void *ctx, 261 vaddr_t pc, vaddr_t va, vaddr_t sp) 262 { 263 #if 0 264 thunk_printf("SIGILL!\n"); 265 thunk_printf("\tsi_signo = %d\n", info->si_signo); 266 thunk_printf("\tsi_errno = %d\n", info->si_errno); 267 thunk_printf("\tsi_code = %d\n", info->si_code); 268 if (info->si_code == ILL_ILLOPC) 269 thunk_printf("\t\tIllegal opcode"); 270 if (info->si_code == ILL_ILLOPN) 271 thunk_printf("\t\tIllegal operand"); 272 if (info->si_code == ILL_ILLADR) 273 thunk_printf("\t\tIllegal addressing mode"); 274 if (info->si_code == ILL_ILLTRP) 275 thunk_printf("\t\tIllegal trap"); 276 if (info->si_code == ILL_PRVOPC) 277 thunk_printf("\t\tPrivileged opcode"); 278 if (info->si_code == ILL_PRVREG) 279 thunk_printf("\t\tPrivileged register"); 280 if (info->si_code == ILL_COPROC) 281 thunk_printf("\t\tCoprocessor error"); 282 if (info->si_code == ILL_BADSTK) 283 thunk_printf("\t\tInternal stack error"); 284 thunk_printf("\tsi_addr = %p\n", info->si_addr); 285 thunk_printf("\tsi_trap = %d\n", info->si_trap); 286 287 thunk_printf("%p : ", info->si_addr); 288 for (int i = 0; i < 10; i++) 289 thunk_printf("%02x ", *((uint8_t *) info->si_addr + i)); 290 thunk_printf("\n"); 291 #endif 292 293 #if 0 294 thunk_printf("sigill\n"); 295 #endif 296 } 297 #else /* DEBUG */ 298 #define print_mem_access_siginfo(s, i, c, p, v, sp) {} 299 #define print_illegal_instruction_siginfo(s, i, c, p, v, sp) {} 300 #endif /* DEBUG */ 301 302 303 static void 304 handle_signal(int sig, siginfo_t *info, void *ctx) 305 { 306 sigfunc_t *f; 307 ucontext_t *ucp = ctx; 308 struct lwp *l; 309 struct pcb *pcb; 310 vaddr_t va, sp, pc, fp; 311 long from_userland; 312 313 if (sig == SIGBUS || sig == SIGSEGV || sig == SIGILL) { 314 if (info->si_code == SI_NOINFO) 315 panic("received signal %d with no info", 316 info->si_signo); 317 } 318 319 f = sig_funcs[sig]; 320 KASSERT(f); 321 322 /* get address of possible faulted memory access and page align it */ 323 va = (vaddr_t) info->si_addr; 324 va = trunc_page(va); 325 326 /* get PC address of possibly faulted instruction */ 327 pc = md_get_pc(ctx); 328 329 /* 330 * short-cut for SIGTRAP as we have NO indication anything is valid 331 */ 332 #ifdef KGDB 333 if (sig == SIGTRAP) { 334 from_userland = 0; 335 if (pc < kmem_user_end) 336 from_userland = 1; 337 if (!from_userland) { 338 kgdb_kernel_trap(sig, pc, va, ucp); 339 return; 340 } 341 } 342 #endif 343 344 /* get stack pointer for nesting */ 345 sp = md_get_sp(ctx); 346 347 if (sig == SIGBUS || sig == SIGSEGV) 348 print_mem_access_siginfo(sig, info, ctx, pc, va, sp); 349 if (sig == SIGILL) 350 print_illegal_instruction_siginfo(sig, info, ctx, pc, va, sp); 351 352 /* get thread */ 353 l = curlwp; KASSERT(l); 354 pcb = lwp_getpcb(l); KASSERT(pcb); 355 356 /* currently running on the dedicated signal stack */ 357 358 /* if we're running on a userland stack, switch to the system stack */ 359 from_userland = 0; 360 if ((sp < (vaddr_t) pcb->sys_stack) || 361 (sp > (vaddr_t) pcb->sys_stack_top)) { 362 sp = (vaddr_t) pcb->sys_stack_top - sizeof(register_t); 363 fp = (vaddr_t) &pcb->pcb_userret_ucp; 364 if (pc < kmem_user_end) 365 from_userland = 1; 366 } else { 367 /* stack grows down */ 368 fp = sp - sizeof(ucontext_t) - sizeof(register_t); /* slack */ 369 sp = fp - sizeof(register_t); /* slack */ 370 371 /* sanity check before copying */ 372 if (fp - 4*PAGE_SIZE < (vaddr_t) pcb->sys_stack) 373 panic("%s: out of system stack", __func__); 374 } 375 376 memcpy((void *) fp, ucp, sizeof(ucontext_t)); 377 memcpy(&jump_ucp, ucp, sizeof(ucontext_t)); 378 379 /* create context */ 380 jump_ucp.uc_stack.ss_sp = (void *) pcb->sys_stack; 381 jump_ucp.uc_stack.ss_size = sp - (vaddr_t) pcb->sys_stack; 382 jump_ucp.uc_link = (void *) fp; /* link to old frame on stack */ 383 384 /* prevent multiple nested SIGIOs */ 385 if (sig == SIGIO) 386 thunk_sigfillset(&jump_ucp.uc_sigmask); 387 else 388 thunk_sigemptyset(&jump_ucp.uc_sigmask); 389 jump_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK; 390 391 thunk_makecontext(&jump_ucp, 392 (void (*)(void)) f, 393 4, info, (void *) from_userland, (void *) pc, (void *) va); 394 395 /* switch to the new context on return from signal */ 396 thunk_setcontext(&jump_ucp); 397 // memcpy(ctx, &pcb->pcb_ucp, sizeof(ucontext_t)); 398 } 399 400 401 void 402 signal_intr_establish(int sig, sigfunc_t f) 403 { 404 static struct sigaction sa; 405 406 sig_funcs[sig] = f; 407 408 sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 409 sa.sa_sigaction = (void *) handle_signal; 410 thunk_sigfillset(&sa.sa_mask); 411 if (thunk_sigaction(sig, &sa, NULL) == -1) 412 panic("couldn't register SIG%d handler: %d", sig, 413 thunk_geterrno()); 414 } 415 416 417 /* 418 * Context for handing page faults from the sigsegv handler; check if its a 419 * pmap reference fault or let uvm handle it. 420 */ 421 static void 422 pagefault(siginfo_t *info, vaddr_t from_userland, vaddr_t pc, vaddr_t va) 423 { 424 struct proc *p; 425 struct lwp *l; 426 struct pcb *pcb; 427 struct vmspace *vm; 428 struct vm_map *vm_map; 429 vm_prot_t atype; 430 void *onfault; 431 int from_kernel, lwp_errno, error; 432 ksiginfo_t ksi; 433 434 l = curlwp; KASSERT(l); 435 pcb = lwp_getpcb(l); 436 p = l->l_proc; 437 vm = p->p_vmspace; 438 439 lwp_errno = thunk_geterrno(); 440 441 vm_map = &vm->vm_map; 442 from_kernel = (pc >= kmem_k_start) && (!from_userland); 443 if (from_kernel && (va >= VM_MIN_KERNEL_ADDRESS)) 444 vm_map = kernel_map; 445 446 #if 0 447 thunk_printf("%s: l %p, pcb %p\n", __func__, l, pcb); 448 thunk_printf("\tpc %p, va %p\n", (void *) pc, (void *) va); 449 #endif 450 451 /* can pmap handle it? on its own? (r/m) emulation */ 452 if (pmap_fault(vm_map->pmap, va, &atype)) { 453 /* no use doing anything else here */ 454 goto out_quick; 455 } 456 457 /* ask UVM */ 458 #if 0 459 thunk_printf("%s: l %p, pcb %p, ", __func__, l, pcb); 460 thunk_printf("pc %p, va %p ", (void *) pc, (void *) va); 461 thunk_printf("derived atype %d\n", atype); 462 #endif 463 thunk_printf_debug("pmap fault couldn't handle it! : " 464 "derived atype %d\n", atype); 465 466 onfault = pcb->pcb_onfault; 467 pcb->pcb_onfault = NULL; 468 error = uvm_fault(vm_map, va, atype); 469 pcb->pcb_onfault = onfault; 470 471 if (vm_map != kernel_map) { 472 if (error == 0) 473 uvm_grow(l->l_proc, va); 474 } 475 if (error == EACCES) 476 error = EFAULT; 477 478 /* if uvm handled it, return */ 479 if (error == 0) { 480 // thunk_printf("pagefault leave (uvm)\n"); 481 goto out; 482 } 483 484 /* check if its from copyin/copyout */ 485 if (onfault) { 486 panic("%s: can't call onfault yet\n", __func__); 487 /* XXX implement me ? */ 488 /* jump to given onfault */ 489 // tf = &kernel_tf; 490 // memset(tf, 0, sizeof(struct trapframe)); 491 // tf->tf_pc = onfault; 492 // tf->tf_io[0] = (rv == EACCES) ? EFAULT : rv; 493 goto out; 494 } 495 496 if (from_kernel) { 497 thunk_printf("%s: uvm fault %d, pc %p, va %p, from_kernel %d\n", 498 __func__, error, (void *) pc, (void *) va, from_kernel); 499 panic("Unhandled page fault in kernel mode"); 500 } 501 502 /* send signal */ 503 /* something got wrong */ 504 thunk_printf_debug("%s: uvm fault %d, pc %p, va %p, from_kernel %d\n", 505 __func__, error, (void *) pc, (void *) va, from_kernel); 506 507 thunk_printf_debug("giving signal to userland\n"); 508 509 KASSERT(from_userland); 510 KSI_INIT_TRAP(&ksi); 511 ksi.ksi_signo = info->si_signo; 512 ksi.ksi_trap = 0; /* XXX */ 513 ksi.ksi_code = (error == EPERM) ? SEGV_ACCERR : SEGV_MAPERR; 514 ksi.ksi_addr = (void *) va; 515 516 if (error == ENOMEM) { 517 printf("UVM: pid %d.%d (%s), uid %d killed: " 518 "out of swap\n", 519 p->p_pid, l->l_lid, p->p_comm, 520 l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1); 521 ksi.ksi_signo = SIGKILL; 522 } 523 524 #if 0 525 p->p_emul->e_trapsignal(l, &ksi); 526 #else 527 trapsignal(l, &ksi); 528 #endif 529 530 // thunk_printf("pagefault leave\n"); 531 out: 532 if (from_userland) 533 userret(l); 534 out_quick: 535 thunk_seterrno(lwp_errno); 536 pcb->pcb_errno = lwp_errno; 537 } 538 539 540 /* 541 * handle an illegal instruction. 542 * 543 * arguments 'pc' and 'va' are ignored here 544 */ 545 static void 546 illegal_instruction(siginfo_t *info, vaddr_t from_userland, vaddr_t pc, vaddr_t va) 547 { 548 struct lwp *l = curlwp; 549 struct pcb *pcb = lwp_getpcb(l); 550 ucontext_t *ucp = &pcb->pcb_userret_ucp; 551 ksiginfo_t ksi; 552 553 // thunk_printf("%s: l %p, pcb %p\n", __func__, l, pcb); 554 555 KASSERT(from_userland); 556 557 /* if its a syscall ... */ 558 if (md_syscall_check_opcode(ucp)) { 559 syscall(); 560 userret(l); 561 return; 562 } 563 564 thunk_printf("%s: giving SIGILL (TRAP)\n", __func__); 565 566 KASSERT(from_userland); 567 KSI_INIT_TRAP(&ksi); 568 ksi.ksi_signo = SIGILL; 569 ksi.ksi_trap = 0; /* XXX */ 570 ksi.ksi_errno = 0; // info->si_errno; 571 ksi.ksi_code = 0; // info->si_code; 572 ksi.ksi_addr = (void *) md_get_pc(ucp); /* only reliable source */ 573 574 #if 0 575 p->p_emul->e_trapsignal(l, &ksi); 576 #else 577 trapsignal(l, &ksi); 578 #endif 579 userret(l); 580 } 581 582 583 /* 584 * handle pass to userland signals 585 * 586 * arguments other than the original siginfo_t are not used 587 */ 588 static void 589 pass_on(siginfo_t *info, vaddr_t from_userland, vaddr_t pc, vaddr_t va) 590 { 591 struct lwp *l = curlwp; 592 struct pcb *pcb = lwp_getpcb(l); 593 ucontext_t *ucp = &pcb->pcb_userret_ucp; 594 ksiginfo_t ksi; 595 596 KASSERT(from_userland); 597 KSI_INIT_TRAP(&ksi); 598 ksi.ksi_signo = info->si_signo; 599 ksi.ksi_trap = 0; /* XXX ? */ 600 ksi.ksi_errno = info->si_errno; 601 ksi.ksi_code = info->si_code; 602 ksi.ksi_addr = (void *) md_get_pc(ucp); /* only reliable source */ 603 604 trapsignal(l, &ksi); 605 userret(l); 606 } 607 608 609 /* 610 * handle alarm, a clock ticker. 611 * 612 * arguments 'pc' and 'va' are ignored here 613 */ 614 static void 615 alarm(siginfo_t *info, vaddr_t from_userland, vaddr_t pc, vaddr_t va) 616 { 617 struct lwp *l = curlwp; 618 struct pcb *pcb = lwp_getpcb(l); KASSERT(pcb); 619 620 if (!clock_running) 621 return; 622 // thunk_printf("%s: l %p, pcb %p\n", __func__, l, pcb); 623 624 softint_schedule(alrm_ih); 625 626 KASSERT(l == curlwp); 627 if (from_userland) 628 userret(l); 629 } 630 631 632 /* 633 * handle sigio, a mux for all io operations. 634 * 635 * arguments 'pc' and 'va' are ignored here 636 */ 637 static void 638 sigio(siginfo_t *info, vaddr_t from_userland, vaddr_t pc, vaddr_t va) 639 { 640 struct lwp *l = curlwp; 641 struct pcb *pcb = lwp_getpcb(l); KASSERT(pcb); 642 struct intr_handler *sih; 643 unsigned int n, pass; 644 645 // thunk_printf("%s: l %p, pcb %p\n", __func__, l, pcb); 646 for (pass = 0; pass < 2; pass++) { 647 for (n = 0; n < SIGIO_MAX_HANDLERS; n++) { 648 sih = &sigio_intr_handler[n]; 649 if (sih->func) 650 sih->func(sih->arg); 651 } 652 } 653 654 KASSERT(l == curlwp); 655 if (from_userland) 656 userret(l); /* or ast? */ 657 } 658 659 660 /* sigio register function */ 661 void * 662 sigio_intr_establish(int (*func)(void *), void *arg) 663 { 664 struct intr_handler *sih; 665 unsigned int n; 666 667 for (n = 0; n < SIGIO_MAX_HANDLERS; n++) { 668 sih = &sigio_intr_handler[n]; 669 if (sih->func == NULL) { 670 sih->func = func; 671 sih->arg = arg; 672 return sih; 673 } 674 } 675 676 panic("increase SIGIO_MAX_HANDLERS"); 677 } 678 679