| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * kgdbts is a test suite for kgdb for the sole purpose of validating |
|---|
| 3 | 4 | * that key pieces of the kgdb internals are working properly such as |
|---|
| .. | .. |
|---|
| 6 | 7 | * Created by: Jason Wessel <jason.wessel@windriver.com> |
|---|
| 7 | 8 | * |
|---|
| 8 | 9 | * Copyright (c) 2008 Wind River Systems, Inc. |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 11 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 12 | | - * published by the Free Software Foundation. |
|---|
| 13 | | - * |
|---|
| 14 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 15 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 16 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|---|
| 17 | | - * See the GNU General Public License for more details. |
|---|
| 18 | | - * |
|---|
| 19 | | - * You should have received a copy of the GNU General Public License |
|---|
| 20 | | - * along with this program; if not, write to the Free Software |
|---|
| 21 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 22 | 10 | */ |
|---|
| 23 | 11 | /* Information about the kgdb test suite. |
|---|
| 24 | 12 | * ------------------------------------- |
|---|
| .. | .. |
|---|
| 45 | 33 | * You can also specify optional tests: |
|---|
| 46 | 34 | * N## = Go to sleep with interrupts of for ## seconds |
|---|
| 47 | 35 | * to test the HW NMI watchdog |
|---|
| 48 | | - * F## = Break at do_fork for ## iterations |
|---|
| 36 | + * F## = Break at kernel_clone for ## iterations |
|---|
| 49 | 37 | * S## = Break at sys_open for ## iterations |
|---|
| 50 | 38 | * I## = Run the single step test ## iterations |
|---|
| 51 | 39 | * |
|---|
| 52 | | - * NOTE: that the do_fork and sys_open tests are mutually exclusive. |
|---|
| 40 | + * NOTE: that the kernel_clone and sys_open tests are mutually exclusive. |
|---|
| 53 | 41 | * |
|---|
| 54 | 42 | * To invoke the kgdb test suite from boot you use a kernel start |
|---|
| 55 | 43 | * argument as follows: |
|---|
| 56 | 44 | * kgdbts=V1 kgdbwait |
|---|
| 57 | | - * Or if you wanted to perform the NMI test for 6 seconds and do_fork |
|---|
| 45 | + * Or if you wanted to perform the NMI test for 6 seconds and kernel_clone |
|---|
| 58 | 46 | * test for 100 forks, you could use: |
|---|
| 59 | 47 | * kgdbts=V1N6F100 kgdbwait |
|---|
| 60 | 48 | * |
|---|
| .. | .. |
|---|
| 86 | 74 | * echo kgdbts=V1S10000 > /sys/module/kgdbts/parameters/kgdbts |
|---|
| 87 | 75 | * fg # and hit control-c |
|---|
| 88 | 76 | * fg # and hit control-c |
|---|
| 89 | | - * ## This tests break points on do_fork |
|---|
| 77 | + * ## This tests break points on kernel_clone |
|---|
| 90 | 78 | * while [ 1 ] ; do date > /dev/null ; done & |
|---|
| 91 | 79 | * while [ 1 ] ; do date > /dev/null ; done & |
|---|
| 92 | 80 | * echo kgdbts=V1F1000 > /sys/module/kgdbts/parameters/kgdbts |
|---|
| .. | .. |
|---|
| 222 | 210 | addr = (unsigned long)kgdbts_break_test; |
|---|
| 223 | 211 | else if (!strcmp(arg, "sys_open")) |
|---|
| 224 | 212 | addr = (unsigned long)do_sys_open; |
|---|
| 225 | | - else if (!strcmp(arg, "do_fork")) |
|---|
| 226 | | - addr = (unsigned long)_do_fork; |
|---|
| 213 | + else if (!strcmp(arg, "kernel_clone")) |
|---|
| 214 | + addr = (unsigned long)kernel_clone; |
|---|
| 227 | 215 | else if (!strcmp(arg, "hw_break_val")) |
|---|
| 228 | 216 | addr = (unsigned long)&hw_break_val; |
|---|
| 229 | 217 | addr = (unsigned long) dereference_function_descriptor((void *)addr); |
|---|
| .. | .. |
|---|
| 323 | 311 | |
|---|
| 324 | 312 | if (arch_needs_sstep_emulation && sstep_addr && |
|---|
| 325 | 313 | ip + offset == sstep_addr && |
|---|
| 326 | | - ((!strcmp(arg, "sys_open") || !strcmp(arg, "do_fork")))) { |
|---|
| 314 | + ((!strcmp(arg, "sys_open") || !strcmp(arg, "kernel_clone")))) { |
|---|
| 327 | 315 | /* This is special case for emulated single step */ |
|---|
| 328 | 316 | v2printk("Emul: rewind hit single step bp\n"); |
|---|
| 329 | 317 | restart_from_top_after_write = 1; |
|---|
| .. | .. |
|---|
| 609 | 597 | }; |
|---|
| 610 | 598 | |
|---|
| 611 | 599 | /* |
|---|
| 612 | | - * Test for hitting a breakpoint at do_fork for what ever the number |
|---|
| 600 | + * Test for hitting a breakpoint at kernel_clone for what ever the number |
|---|
| 613 | 601 | * of iterations required by the variable repeat_test. |
|---|
| 614 | 602 | */ |
|---|
| 615 | | -static struct test_struct do_fork_test[] = { |
|---|
| 603 | +static struct test_struct do_kernel_clone_test[] = { |
|---|
| 616 | 604 | { "?", "S0*" }, /* Clear break points */ |
|---|
| 617 | | - { "do_fork", "OK", sw_break, }, /* set sw breakpoint */ |
|---|
| 605 | + { "kernel_clone", "OK", sw_break, }, /* set sw breakpoint */ |
|---|
| 618 | 606 | { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */ |
|---|
| 619 | | - { "do_fork", "OK", sw_rem_break }, /*remove breakpoint */ |
|---|
| 620 | | - { "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */ |
|---|
| 607 | + { "kernel_clone", "OK", sw_rem_break }, /*remove breakpoint */ |
|---|
| 608 | + { "g", "kernel_clone", NULL, check_and_rewind_pc }, /* check location */ |
|---|
| 621 | 609 | { "write", "OK", write_regs, emul_reset }, /* Write registers */ |
|---|
| 622 | 610 | { "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */ |
|---|
| 623 | | - { "g", "do_fork", NULL, check_single_step }, |
|---|
| 624 | | - { "do_fork", "OK", sw_break, }, /* set sw breakpoint */ |
|---|
| 611 | + { "g", "kernel_clone", NULL, check_single_step }, |
|---|
| 612 | + { "kernel_clone", "OK", sw_break, }, /* set sw breakpoint */ |
|---|
| 625 | 613 | { "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */ |
|---|
| 626 | 614 | { "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */ |
|---|
| 627 | 615 | { "", "", get_cont_catch, put_cont_catch }, |
|---|
| .. | .. |
|---|
| 841 | 829 | char before[BREAK_INSTR_SIZE]; |
|---|
| 842 | 830 | char after[BREAK_INSTR_SIZE]; |
|---|
| 843 | 831 | |
|---|
| 844 | | - probe_kernel_read(before, (char *)kgdbts_break_test, |
|---|
| 832 | + copy_from_kernel_nofault(before, (char *)kgdbts_break_test, |
|---|
| 845 | 833 | BREAK_INSTR_SIZE); |
|---|
| 846 | 834 | init_simple_test(); |
|---|
| 847 | 835 | ts.tst = plant_and_detach_test; |
|---|
| .. | .. |
|---|
| 849 | 837 | /* Activate test with initial breakpoint */ |
|---|
| 850 | 838 | if (!is_early) |
|---|
| 851 | 839 | kgdb_breakpoint(); |
|---|
| 852 | | - probe_kernel_read(after, (char *)kgdbts_break_test, |
|---|
| 853 | | - BREAK_INSTR_SIZE); |
|---|
| 840 | + copy_from_kernel_nofault(after, (char *)kgdbts_break_test, |
|---|
| 841 | + BREAK_INSTR_SIZE); |
|---|
| 854 | 842 | if (memcmp(before, after, BREAK_INSTR_SIZE)) { |
|---|
| 855 | 843 | printk(KERN_CRIT "kgdbts: ERROR kgdb corrupted memory\n"); |
|---|
| 856 | 844 | panic("kgdb memory corruption"); |
|---|
| .. | .. |
|---|
| 948 | 936 | kgdb_breakpoint(); |
|---|
| 949 | 937 | } |
|---|
| 950 | 938 | |
|---|
| 951 | | -static void run_do_fork_test(void) |
|---|
| 939 | +static void run_kernel_clone_test(void) |
|---|
| 952 | 940 | { |
|---|
| 953 | 941 | init_simple_test(); |
|---|
| 954 | | - ts.tst = do_fork_test; |
|---|
| 955 | | - ts.name = "do_fork_test"; |
|---|
| 942 | + ts.tst = do_kernel_clone_test; |
|---|
| 943 | + ts.name = "do_kernel_clone_test"; |
|---|
| 956 | 944 | /* Activate test with initial breakpoint */ |
|---|
| 957 | 945 | kgdb_breakpoint(); |
|---|
| 958 | 946 | } |
|---|
| .. | .. |
|---|
| 980 | 968 | static void kgdbts_run_tests(void) |
|---|
| 981 | 969 | { |
|---|
| 982 | 970 | char *ptr; |
|---|
| 983 | | - int fork_test = 0; |
|---|
| 971 | + int clone_test = 0; |
|---|
| 984 | 972 | int do_sys_open_test = 0; |
|---|
| 985 | 973 | int sstep_test = 1000; |
|---|
| 986 | 974 | int nmi_sleep = 0; |
|---|
| .. | .. |
|---|
| 994 | 982 | |
|---|
| 995 | 983 | ptr = strchr(config, 'F'); |
|---|
| 996 | 984 | if (ptr) |
|---|
| 997 | | - fork_test = simple_strtol(ptr + 1, NULL, 10); |
|---|
| 985 | + clone_test = simple_strtol(ptr + 1, NULL, 10); |
|---|
| 998 | 986 | ptr = strchr(config, 'S'); |
|---|
| 999 | 987 | if (ptr) |
|---|
| 1000 | 988 | do_sys_open_test = simple_strtol(ptr + 1, NULL, 10); |
|---|
| .. | .. |
|---|
| 1038 | 1026 | run_nmi_sleep_test(nmi_sleep); |
|---|
| 1039 | 1027 | } |
|---|
| 1040 | 1028 | |
|---|
| 1041 | | - /* If the do_fork test is run it will be the last test that is |
|---|
| 1029 | + /* If the kernel_clone test is run it will be the last test that is |
|---|
| 1042 | 1030 | * executed because a kernel thread will be spawned at the very |
|---|
| 1043 | 1031 | * end to unregister the debug hooks. |
|---|
| 1044 | 1032 | */ |
|---|
| 1045 | | - if (fork_test) { |
|---|
| 1046 | | - repeat_test = fork_test; |
|---|
| 1047 | | - printk(KERN_INFO "kgdbts:RUN do_fork for %i breakpoints\n", |
|---|
| 1033 | + if (clone_test) { |
|---|
| 1034 | + repeat_test = clone_test; |
|---|
| 1035 | + printk(KERN_INFO "kgdbts:RUN kernel_clone for %i breakpoints\n", |
|---|
| 1048 | 1036 | repeat_test); |
|---|
| 1049 | 1037 | kthread_run(kgdbts_unreg_thread, NULL, "kgdbts_unreg"); |
|---|
| 1050 | | - run_do_fork_test(); |
|---|
| 1038 | + run_kernel_clone_test(); |
|---|
| 1051 | 1039 | return; |
|---|
| 1052 | 1040 | } |
|---|
| 1053 | 1041 | |
|---|
| .. | .. |
|---|
| 1072 | 1060 | { |
|---|
| 1073 | 1061 | if (strlen(opt) >= MAX_CONFIG_LEN) { |
|---|
| 1074 | 1062 | printk(KERN_ERR "kgdbts: config string too long\n"); |
|---|
| 1075 | | - return -ENOSPC; |
|---|
| 1063 | + return 1; |
|---|
| 1076 | 1064 | } |
|---|
| 1077 | 1065 | strcpy(config, opt); |
|---|
| 1078 | | - return 0; |
|---|
| 1066 | + return 1; |
|---|
| 1079 | 1067 | } |
|---|
| 1080 | 1068 | |
|---|
| 1081 | 1069 | __setup("kgdbts=", kgdbts_option_setup); |
|---|