|
| 1 | +About |
| 2 | +===== |
| 3 | + |
| 4 | +This collection tests the ``ptrace()`` system call, specifically the |
| 5 | +ability of a tracer to set breakpoints (on functions) and watchpoints |
| 6 | +(on variables) in the tracee and whether they are correctly triggered |
| 7 | +when tracee hits them. |
| 8 | + |
| 9 | +The ``breakpoint_test`` test from the collection is chronologically the |
| 10 | +very first kernel selftest. |
| 11 | + |
| 12 | +Tests suite compilation and running |
| 13 | +=================================== |
| 14 | + |
| 15 | +The suite generally contains two tests: |
| 16 | + |
| 17 | +#. ``breakpoint_test`` (on x86\* platforms) or ``breakpoint_test_arm64`` |
| 18 | + (on the arm64 platforms), |
| 19 | +#. ``step_after_suspend_test``. |
| 20 | + |
| 21 | +For other platforms than x86\* and arm64 the suite contains only |
| 22 | +``step_after_suspend_test``. |
| 23 | + |
| 24 | +``breakpoint_test`` |
| 25 | +------------------- |
| 26 | + |
| 27 | +When compiling the ``breakpoints`` collection on *x86_64* beware not to |
| 28 | +set the ``ARCH`` variable explicitly, or the ``breakpoint_test`` test |
| 29 | +won't be produced. So, if your ``uname -m`` reports ``x86_64`` then this |
| 30 | +is ok: |
| 31 | + |
| 32 | +.. code:: shell |
| 33 | +
|
| 34 | + make -C tools/testing/selftests TARGETS=breakpoints |
| 35 | +
|
| 36 | +and this is **not** ok: |
| 37 | + |
| 38 | +.. code:: shell |
| 39 | +
|
| 40 | + make ARCH=x86_64 -C tools/testing/selftests TARGETS=breakpoints |
| 41 | +
|
| 42 | +It's obviously a bug in the |
| 43 | +``tools/testing/selftests/breakpoints/Makefile`` file, precisely in the |
| 44 | +way the ``ARCH`` variable is normalized with ``sed``, with this |
| 45 | +normalization being bound to setting default ``ARCH`` value instead of |
| 46 | +being general, |
| 47 | + |
| 48 | +.. code:: makefile |
| 49 | +
|
| 50 | + ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) |
| 51 | +
|
| 52 | +yet the conditional compilation of ``breakpoint_test`` assuming this |
| 53 | +normalization in all cases. |
| 54 | + |
| 55 | +If compiled successfully the test is expected to pass on all versions |
| 56 | +with a message similar to |
| 57 | + |
| 58 | +:: |
| 59 | + |
| 60 | + TAP version 13 |
| 61 | + 1..1 |
| 62 | + # timeout set to 45 |
| 63 | + # selftests: breakpoints: breakpoint_test |
| 64 | + # TAP version 13 |
| 65 | + # 1..110 |
| 66 | + # ok 1 Test breakpoint 0 with local: 0 global: 1 |
| 67 | + # ok 2 Test breakpoint 1 with local: 0 global: 1 |
| 68 | + # ok 3 Test breakpoint 2 with local: 0 global: 1 |
| 69 | + # ok 4 Test breakpoint 3 with local: 0 global: 1 |
| 70 | + # ok 5 Test breakpoint 0 with local: 1 global: 0 |
| 71 | + # ok 6 Test breakpoint 1 with local: 1 global: 0 |
| 72 | + … |
| 73 | + # ok 104 Test read watchpoint 3 with len: 8 local: 1 global: 0 |
| 74 | + # ok 105 Test read watchpoint 0 with len: 8 local: 1 global: 1 |
| 75 | + # ok 106 Test read watchpoint 1 with len: 8 local: 1 global: 1 |
| 76 | + # ok 107 Test read watchpoint 2 with len: 8 local: 1 global: 1 |
| 77 | + # ok 108 Test read watchpoint 3 with len: 8 local: 1 global: 1 |
| 78 | + # ok 109 Test icebp |
| 79 | + # ok 110 Test int 3 trap |
| 80 | + # # Totals: pass:110 fail:0 xfail:0 xpass:0 skip:0 error:0 |
| 81 | + ok 1 selftests: breakpoints: breakpoint_test |
| 82 | + |
| 83 | +``breakpoint_test_arm64`` |
| 84 | +------------------------- |
| 85 | + |
| 86 | +On versions ``ciqlts8_6``, ``ciqlts8_8`` the test contains a bug which |
| 87 | +prevents it from being compiled successfully for ``arm64``: |
| 88 | + |
| 89 | +:: |
| 90 | + |
| 91 | + gcc breakpoint_test_arm64.c /mnt/build_files/kernel-src-tree-kselftests-ciqlts8_8/tools/testing/selftests/kselftest_harness.h /mnt/build_files/kernel-src-tree-kselftests-ciqlts8_8/tools/testing/selftests/kselftest.h -o /mnt/build_files/kernel-src-tree-kselftests-ciqlts8_8/tools/testing/selftests/breakpoints/breakpoint_test_arm64 |
| 92 | + breakpoint_test_arm64.c: In function ‘main’: |
| 93 | + breakpoint_test_arm64.c:226:14: warning: implicit declaration of function ‘run_test’; did you mean ‘arun_test’? [-Wimplicit-function-declaration] |
| 94 | + result = run_test(size, MIN(size, 8), wr, wp); |
| 95 | + ^~~~~~~~ |
| 96 | + arun_test |
| 97 | + /tmp/cc5dMu7r.o: In function `main': |
| 98 | + breakpoint_test_arm64.c:(.text+0xb08): undefined reference to `run_test' |
| 99 | + breakpoint_test_arm64.c:(.text+0xc10): undefined reference to `run_test' |
| 100 | + collect2: error: ld returned 1 exit status |
| 101 | + |
| 102 | +This bug was fixed in the mainline with the |
| 103 | +``5b06eeae52c02dd0d9bc8488275a1207d410870b`` commit. It's in the process |
| 104 | +of backporting to ``ciqlts8_6``, ``ciqlts8_8`` at the time of this |
| 105 | +writing. |
| 106 | + |
| 107 | +Additionally, when compiling the test on base cloud images for |
| 108 | +``ciqlts8_6`` and ``ciqlts8_8``\ [1]_, and using Mountain-provided |
| 109 | +repositories, the following error may be encountered: |
| 110 | + |
| 111 | +:: |
| 112 | + |
| 113 | + breakpoint_test_arm64.c: In function ‘run_test’: |
| 114 | + breakpoint_test_arm64.c:188:25: error: ‘TRAP_HWBKPT’ undeclared (first use in this function); did you mean ‘TRAP_BRKPT’? |
| 115 | + if (siginfo.si_code != TRAP_HWBKPT) { |
| 116 | + ^~~~~~~~~~~ |
| 117 | + TRAP_BRKPT |
| 118 | + breakpoint_test_arm64.c:188:25: note: each undeclared identifier is reported only once for each function it appears in |
| 119 | + |
| 120 | +The ``TRAP_BRKPT`` constant is searched for in the |
| 121 | +``/usr/include/bits/siginfo-consts.h`` file, which in versions ≥ 9.2 |
| 122 | +contains |
| 123 | + |
| 124 | +.. code:: c |
| 125 | +
|
| 126 | + /* `si_code' values for SIGTRAP signal. */ |
| 127 | + enum |
| 128 | + { |
| 129 | + TRAP_BRKPT = 1, /* Process breakpoint. */ |
| 130 | + # define TRAP_BRKPT TRAP_BRKPT |
| 131 | + TRAP_TRACE, /* Process trace trap. */ |
| 132 | + # define TRAP_TRACE TRAP_TRACE |
| 133 | + TRAP_BRANCH, /* Process taken branch trap. */ |
| 134 | + # define TRAP_BRANCH TRAP_BRANCH |
| 135 | + TRAP_HWBKPT, /* Hardware breakpoint/watchpoint. */ |
| 136 | + # define TRAP_HWBKPT TRAP_HWBKPT |
| 137 | + TRAP_UNK /* Undiagnosed trap. */ |
| 138 | + # define TRAP_UNK TRAP_UNK |
| 139 | + }; |
| 140 | + # endif |
| 141 | +
|
| 142 | +while in versions < 9.2 contains |
| 143 | + |
| 144 | +.. code:: c |
| 145 | +
|
| 146 | + /* `si_code' values for SIGTRAP signal. */ |
| 147 | + enum |
| 148 | + { |
| 149 | + TRAP_BRKPT = 1, /* Process breakpoint. */ |
| 150 | + # define TRAP_BRKPT TRAP_BRKPT |
| 151 | + TRAP_TRACE /* Process trace trap. */ |
| 152 | + # define TRAP_TRACE TRAP_TRACE |
| 153 | + }; |
| 154 | + # endif |
| 155 | +
|
| 156 | +If the ``TRAP_HWBKPT`` constant can't be included in |
| 157 | +``/usr/include/bits/siginfo-consts.h`` in some civilised manner then |
| 158 | +simply expanding the set of known ``TRAP_*`` codes in the system to |
| 159 | +match those on ≥ 9.2 should work: |
| 160 | + |
| 161 | +.. code:: shell |
| 162 | +
|
| 163 | + sudo sed -e '144 d' -e 's/# define TRAP_TRACE\tTRAP_TRACE/ TRAP_TRACE,\n# define TRAP_TRACE\tTRAP_TRACE\n TRAP_BRANCH,\n# define TRAP_BRANCH\tTRAP_BRANCH\n TRAP_HWBKPT,\n# define TRAP_HWBKPT\tTRAP_HWBKPT\n TRAP_UNK\n# define TRAP_UNK\tTRAP_UNK/g' -i /usr/include/bits/siginfo-consts.h |
| 164 | +
|
| 165 | +No compilation problems for ``breakpoint_test_arm64`` were encountered |
| 166 | +on versions ``ciqlts9_2`` and ``ciqlts9_4``. |
| 167 | + |
| 168 | +If the test compiled successfully it's expected to pass with the message |
| 169 | +similar to the following |
| 170 | + |
| 171 | +:: |
| 172 | + |
| 173 | + # TAP version 13 |
| 174 | + # 1..213 |
| 175 | + # # child did not single-step |
| 176 | + # ok 1 Test size = 1 write offset = 0 watchpoint offset = -1 |
| 177 | + # ok 2 Test size = 1 write offset = 0 watchpoint offset = 0 |
| 178 | + # # child did not single-step |
| 179 | + # ok 3 Test size = 1 write offset = 0 watchpoint offset = 1 |
| 180 | + # # child did not single-step |
| 181 | + # ok 4 Test size = 1 write offset = 1 watchpoint offset = 0 |
| 182 | + # ok 5 Test size = 1 write offset = 1 watchpoint offset = 1 |
| 183 | + … |
| 184 | + # ok 206 Test size = 32 write offset = 32 watchpoint offset = 32 |
| 185 | + # # child did not single-step |
| 186 | + # ok 207 Test size = 32 write offset = 32 watchpoint offset = 64 |
| 187 | + # ok 208 Test size = 1 write offset = -1 watchpoint offset = -8 |
| 188 | + # ok 209 Test size = 2 write offset = -2 watchpoint offset = -8 |
| 189 | + # ok 210 Test size = 4 write offset = -4 watchpoint offset = -8 |
| 190 | + # ok 211 Test size = 8 write offset = -8 watchpoint offset = -8 |
| 191 | + # ok 212 Test size = 16 write offset = -16 watchpoint offset = -8 |
| 192 | + # ok 213 Test size = 32 write offset = -32 watchpoint offset = -8 |
| 193 | + # # Totals: pass:213 fail:0 xfail:0 xpass:0 skip:0 error:0 |
| 194 | + ok 1 selftests: breakpoints: breakpoint_test_arm64 |
| 195 | + |
| 196 | +``step_after_suspend_test`` |
| 197 | +--------------------------- |
| 198 | + |
| 199 | +No problems were encountered when compiling this test, on any of the |
| 200 | +versions ``ciqlts8_6``, ``ciqlts8_8``, ``ciqlts9_2``, ``ciqlts9_4``, |
| 201 | +archs ``x86_64``, ``aarch64``. However, for the test to run the system |
| 202 | +must provide the ability to suspend it, as it would be done with |
| 203 | + |
| 204 | +:: |
| 205 | + |
| 206 | + root@…# echo mem > /sys/power/state |
| 207 | + |
| 208 | +Can be checked with this command directly, that's what |
| 209 | +``step_after_suspend_test`` is doing internally. Unfortunately on the |
| 210 | +qemu-kvm virtual machines this fails with the ``virtio-pci`` device (the |
| 211 | +one connecting the machine with the hypervisor) refusing to cooperate: |
| 212 | + |
| 213 | +:: |
| 214 | + |
| 215 | + [root@ciqlts-9-2 pvts]# echo mem > /sys/power/state |
| 216 | + [ 24.434434] PM: suspend entry (s2idle) |
| 217 | + [ 24.498974] Filesystems sync: 0.062 seconds |
| 218 | + [ 24.501574] Freezing user space processes ... (elapsed 0.001 seconds) done. |
| 219 | + [ 24.507156] OOM killer disabled. |
| 220 | + [ 24.509062] Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done. |
| 221 | + [ 24.514480] printk: Suspending console(s) (use no_console_suspend to debug) |
| 222 | + [ 24.540895] virtio-fs: suspend/resume not yet supported |
| 223 | + [ 24.540906] virtio-pci 0000:03:00.0: PM: pci_pm_suspend(): virtio_pci_freeze+0x0/0x50 returns -95 |
| 224 | + [ 24.540970] virtio-pci 0000:03:00.0: PM: dpm_run_callback(): pci_pm_suspend+0x0/0x170 returns -95 |
| 225 | + [ 24.541011] virtio-pci 0000:03:00.0: PM: failed to suspend async: error -95 |
| 226 | + [ 24.554785] PM: Some devices failed to suspend, or early wake event detected |
| 227 | + [ 24.686487] OOM killer enabled. |
| 228 | + [ 24.687385] Restarting tasks ... done. |
| 229 | + [ 24.689834] PM: suspend exit |
| 230 | + bash: echo: write error: Operation not supported |
| 231 | + [root@ciqlts-9-2 pvts]# [ 24.886811] ata3: SATA link down (SStatus 0 SControl 300) |
| 232 | + [ 24.889470] ata5: SATA link down (SStatus 0 SControl 300) |
| 233 | + [ 24.892095] ata2: SATA link down (SStatus 0 SControl 300) |
| 234 | + [ 24.894956] ata4: SATA link down (SStatus 0 SControl 300) |
| 235 | + [ 24.897717] ata6: SATA link down (SStatus 0 SControl 300) |
| 236 | + |
| 237 | +When running selftests in qemu-kvm it's therefore best to omit this |
| 238 | +test, or else it will keep scaring with failures like |
| 239 | + |
| 240 | +:: |
| 241 | + |
| 242 | + # selftests: breakpoints: step_after_suspend_test |
| 243 | + # TAP version 13 |
| 244 | + # Bail out! Failed to enter Suspend state |
| 245 | + # # Totals: pass:0 fail:0 xfail:0 xpass:0 skip:0 error:0 |
| 246 | + not ok 1 selftests: breakpoints: step_after_suspend_test # exit=1 |
| 247 | + |
| 248 | +(Probably a better behavior would be for the test to ``# SKIP`` in this |
| 249 | +case.) |
| 250 | + |
| 251 | +.. [1] |
| 252 | + Referring to the images available at |
| 253 | + https://download.rockylinux.org/vault/rocky/8.6/images/Rocky-8-GenericCloud-8.6.20220702.0.aarch64.qcow2 |
| 254 | + for ``ciqlts8_6`` and at |
| 255 | + https://download.rockylinux.org/vault/rocky/8.8/images/aarch64/Rocky-8-GenericCloud-Base-8.8-20230518.0.aarch64.qcow2 |
| 256 | + for ``ciqlts8_8``, to be precise. |
0 commit comments