.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de) |
---|
3 | 4 | * Copyright (C) 2002- 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
---|
4 | | - * Licensed under the GPL |
---|
5 | 5 | */ |
---|
6 | 6 | |
---|
7 | 7 | #include <stdlib.h> |
---|
| 8 | +#include <stdbool.h> |
---|
8 | 9 | #include <unistd.h> |
---|
9 | 10 | #include <sched.h> |
---|
10 | 11 | #include <errno.h> |
---|
.. | .. |
---|
249 | 250 | } |
---|
250 | 251 | |
---|
251 | 252 | int userspace_pid[NR_CPUS]; |
---|
| 253 | +int kill_userspace_mm[NR_CPUS]; |
---|
252 | 254 | |
---|
253 | 255 | /** |
---|
254 | 256 | * start_userspace() - prepare a new userspace process |
---|
.. | .. |
---|
342 | 344 | interrupt_end(); |
---|
343 | 345 | |
---|
344 | 346 | while (1) { |
---|
| 347 | + if (kill_userspace_mm[0]) |
---|
| 348 | + fatal_sigsegv(); |
---|
345 | 349 | |
---|
346 | 350 | /* |
---|
347 | 351 | * This can legitimately fail if the process loads a |
---|
.. | .. |
---|
425 | 429 | case SIGBUS: |
---|
426 | 430 | case SIGFPE: |
---|
427 | 431 | case SIGWINCH: |
---|
428 | | - block_signals(); |
---|
| 432 | + block_signals_trace(); |
---|
429 | 433 | (*sig_info[sig])(sig, (struct siginfo *)&si, regs); |
---|
430 | | - unblock_signals(); |
---|
| 434 | + unblock_signals_trace(); |
---|
431 | 435 | break; |
---|
432 | 436 | default: |
---|
433 | 437 | printk(UM_KERN_ERR "userspace - child stopped " |
---|
.. | .. |
---|
625 | 629 | cb_arg = arg; |
---|
626 | 630 | cb_back = &here; |
---|
627 | 631 | |
---|
628 | | - block_signals(); |
---|
| 632 | + block_signals_trace(); |
---|
629 | 633 | if (UML_SETJMP(&here) == 0) |
---|
630 | 634 | UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); |
---|
631 | | - unblock_signals(); |
---|
| 635 | + unblock_signals_trace(); |
---|
632 | 636 | |
---|
633 | 637 | cb_proc = NULL; |
---|
634 | 638 | cb_arg = NULL; |
---|
.. | .. |
---|
637 | 641 | |
---|
638 | 642 | void halt_skas(void) |
---|
639 | 643 | { |
---|
640 | | - block_signals(); |
---|
| 644 | + block_signals_trace(); |
---|
641 | 645 | UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT); |
---|
642 | 646 | } |
---|
643 | 647 | |
---|
| 648 | +static bool noreboot; |
---|
| 649 | + |
---|
| 650 | +static int __init noreboot_cmd_param(char *str, int *add) |
---|
| 651 | +{ |
---|
| 652 | + noreboot = true; |
---|
| 653 | + return 0; |
---|
| 654 | +} |
---|
| 655 | + |
---|
| 656 | +__uml_setup("noreboot", noreboot_cmd_param, |
---|
| 657 | +"noreboot\n" |
---|
| 658 | +" Rather than rebooting, exit always, akin to QEMU's -no-reboot option.\n" |
---|
| 659 | +" This is useful if you're using CONFIG_PANIC_TIMEOUT in order to catch\n" |
---|
| 660 | +" crashes in CI\n"); |
---|
| 661 | + |
---|
644 | 662 | void reboot_skas(void) |
---|
645 | 663 | { |
---|
646 | | - block_signals(); |
---|
647 | | - UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); |
---|
| 664 | + block_signals_trace(); |
---|
| 665 | + UML_LONGJMP(&initial_jmpbuf, noreboot ? INIT_JMP_HALT : INIT_JMP_REBOOT); |
---|
648 | 666 | } |
---|
649 | 667 | |
---|
650 | 668 | void __switch_mm(struct mm_id *mm_idp) |
---|
651 | 669 | { |
---|
652 | 670 | userspace_pid[0] = mm_idp->u.pid; |
---|
| 671 | + kill_userspace_mm[0] = mm_idp->kill; |
---|
653 | 672 | } |
---|