1*b3c0d957SAndrew Turner /*- 2*b3c0d957SAndrew Turner * SPDX-License-Identifier: BSD-2-Clause 3*b3c0d957SAndrew Turner * 4*b3c0d957SAndrew Turner * Copyright (c) 2018, 2019 Andrew Turner 5*b3c0d957SAndrew Turner * 6*b3c0d957SAndrew Turner * This software was developed by SRI International and the University of 7*b3c0d957SAndrew Turner * Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237 8*b3c0d957SAndrew Turner * ("CTSRD"), as part of the DARPA CRASH research programme. 9*b3c0d957SAndrew Turner * 10*b3c0d957SAndrew Turner * Redistribution and use in source and binary forms, with or without 11*b3c0d957SAndrew Turner * modification, are permitted provided that the following conditions 12*b3c0d957SAndrew Turner * are met: 13*b3c0d957SAndrew Turner * 1. Redistributions of source code must retain the above copyright 14*b3c0d957SAndrew Turner * notice, this list of conditions and the following disclaimer. 15*b3c0d957SAndrew Turner * 2. Redistributions in binary form must reproduce the above copyright 16*b3c0d957SAndrew Turner * notice, this list of conditions and the following disclaimer in the 17*b3c0d957SAndrew Turner * documentation and/or other materials provided with the distribution. 18*b3c0d957SAndrew Turner * 19*b3c0d957SAndrew Turner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20*b3c0d957SAndrew Turner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21*b3c0d957SAndrew Turner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22*b3c0d957SAndrew Turner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23*b3c0d957SAndrew Turner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24*b3c0d957SAndrew Turner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25*b3c0d957SAndrew Turner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26*b3c0d957SAndrew Turner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27*b3c0d957SAndrew Turner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28*b3c0d957SAndrew Turner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29*b3c0d957SAndrew Turner * SUCH DAMAGE. 30*b3c0d957SAndrew Turner */ 31*b3c0d957SAndrew Turner 32*b3c0d957SAndrew Turner #include <sys/cdefs.h> 33*b3c0d957SAndrew Turner __FBSDID("$FreeBSD$"); 34*b3c0d957SAndrew Turner 35*b3c0d957SAndrew Turner #include <sys/param.h> 36*b3c0d957SAndrew Turner #include <sys/ioctl.h> 37*b3c0d957SAndrew Turner #include <sys/kcov.h> 38*b3c0d957SAndrew Turner #include <sys/mman.h> 39*b3c0d957SAndrew Turner 40*b3c0d957SAndrew Turner #include <machine/atomic.h> 41*b3c0d957SAndrew Turner 42*b3c0d957SAndrew Turner #include <fcntl.h> 43*b3c0d957SAndrew Turner #include <pthread.h> 44*b3c0d957SAndrew Turner #include <semaphore.h> 45*b3c0d957SAndrew Turner 46*b3c0d957SAndrew Turner #include <atf-c.h> 47*b3c0d957SAndrew Turner 48*b3c0d957SAndrew Turner static const char *modes[] = { 49*b3c0d957SAndrew Turner "PC tracing", 50*b3c0d957SAndrew Turner "comparison tracing", 51*b3c0d957SAndrew Turner }; 52*b3c0d957SAndrew Turner 53*b3c0d957SAndrew Turner static int 54*b3c0d957SAndrew Turner open_kcov(void) 55*b3c0d957SAndrew Turner { 56*b3c0d957SAndrew Turner int fd; 57*b3c0d957SAndrew Turner 58*b3c0d957SAndrew Turner fd = open("/dev/kcov", O_RDWR); 59*b3c0d957SAndrew Turner if (fd == -1) 60*b3c0d957SAndrew Turner atf_tc_skip("Failed to open /dev/kcov"); 61*b3c0d957SAndrew Turner 62*b3c0d957SAndrew Turner return (fd); 63*b3c0d957SAndrew Turner } 64*b3c0d957SAndrew Turner 65*b3c0d957SAndrew Turner ATF_TC_WITHOUT_HEAD(kcov_bufsize); 66*b3c0d957SAndrew Turner ATF_TC_BODY(kcov_bufsize, tc) 67*b3c0d957SAndrew Turner { 68*b3c0d957SAndrew Turner int fd; 69*b3c0d957SAndrew Turner 70*b3c0d957SAndrew Turner fd = open_kcov(); 71*b3c0d957SAndrew Turner 72*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIOSETBUFSIZE, 0) == -1); 73*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIOSETBUFSIZE, 1) == -1); 74*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIOSETBUFSIZE, 2) == 0); 75*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIOSETBUFSIZE, 2) == -1); 76*b3c0d957SAndrew Turner 77*b3c0d957SAndrew Turner close(fd); 78*b3c0d957SAndrew Turner } 79*b3c0d957SAndrew Turner 80*b3c0d957SAndrew Turner ATF_TC_WITHOUT_HEAD(kcov_mmap); 81*b3c0d957SAndrew Turner ATF_TC_BODY(kcov_mmap, tc) 82*b3c0d957SAndrew Turner { 83*b3c0d957SAndrew Turner void *data; 84*b3c0d957SAndrew Turner int fd; 85*b3c0d957SAndrew Turner 86*b3c0d957SAndrew Turner fd = open_kcov(); 87*b3c0d957SAndrew Turner 88*b3c0d957SAndrew Turner ATF_CHECK(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, 89*b3c0d957SAndrew Turner fd, 0) == MAP_FAILED); 90*b3c0d957SAndrew Turner 91*b3c0d957SAndrew Turner ATF_REQUIRE(ioctl(fd, KIOSETBUFSIZE, 92*b3c0d957SAndrew Turner 2 * PAGE_SIZE / sizeof(uint64_t)) == 0); 93*b3c0d957SAndrew Turner 94*b3c0d957SAndrew Turner ATF_CHECK(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, 95*b3c0d957SAndrew Turner fd, 0) == MAP_FAILED); 96*b3c0d957SAndrew Turner ATF_CHECK(mmap(NULL, 3 * PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, 97*b3c0d957SAndrew Turner fd, 0) == MAP_FAILED); 98*b3c0d957SAndrew Turner ATF_REQUIRE((data = mmap(NULL, 2 * PAGE_SIZE, PROT_READ | PROT_WRITE, 99*b3c0d957SAndrew Turner MAP_SHARED, fd, 0)) != MAP_FAILED); 100*b3c0d957SAndrew Turner ATF_CHECK(mmap(NULL, 2 * PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, 101*b3c0d957SAndrew Turner fd, 0) == MAP_FAILED); 102*b3c0d957SAndrew Turner 103*b3c0d957SAndrew Turner munmap(data, 2 * PAGE_SIZE); 104*b3c0d957SAndrew Turner 105*b3c0d957SAndrew Turner close(fd); 106*b3c0d957SAndrew Turner } 107*b3c0d957SAndrew Turner 108*b3c0d957SAndrew Turner /* This shouldn't panic */ 109*b3c0d957SAndrew Turner ATF_TC_WITHOUT_HEAD(kcov_mmap_no_munmap); 110*b3c0d957SAndrew Turner ATF_TC_BODY(kcov_mmap_no_munmap, tc) 111*b3c0d957SAndrew Turner { 112*b3c0d957SAndrew Turner int fd; 113*b3c0d957SAndrew Turner 114*b3c0d957SAndrew Turner fd = open_kcov(); 115*b3c0d957SAndrew Turner 116*b3c0d957SAndrew Turner ATF_REQUIRE(ioctl(fd, KIOSETBUFSIZE, PAGE_SIZE / sizeof(uint64_t)) ==0); 117*b3c0d957SAndrew Turner 118*b3c0d957SAndrew Turner ATF_CHECK(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, 119*b3c0d957SAndrew Turner fd, 0) != MAP_FAILED); 120*b3c0d957SAndrew Turner 121*b3c0d957SAndrew Turner close(fd); 122*b3c0d957SAndrew Turner } 123*b3c0d957SAndrew Turner 124*b3c0d957SAndrew Turner ATF_TC_WITHOUT_HEAD(kcov_mmap_no_munmap_no_close); 125*b3c0d957SAndrew Turner ATF_TC_BODY(kcov_mmap_no_munmap_no_close, tc) 126*b3c0d957SAndrew Turner { 127*b3c0d957SAndrew Turner int fd; 128*b3c0d957SAndrew Turner 129*b3c0d957SAndrew Turner fd = open_kcov(); 130*b3c0d957SAndrew Turner 131*b3c0d957SAndrew Turner ATF_REQUIRE(ioctl(fd, KIOSETBUFSIZE, PAGE_SIZE / sizeof(uint64_t)) ==0); 132*b3c0d957SAndrew Turner 133*b3c0d957SAndrew Turner ATF_CHECK(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, 134*b3c0d957SAndrew Turner fd, 0) != MAP_FAILED); 135*b3c0d957SAndrew Turner } 136*b3c0d957SAndrew Turner 137*b3c0d957SAndrew Turner static sem_t sem1, sem2; 138*b3c0d957SAndrew Turner 139*b3c0d957SAndrew Turner static void * 140*b3c0d957SAndrew Turner kcov_mmap_enable_thread(void *data) 141*b3c0d957SAndrew Turner { 142*b3c0d957SAndrew Turner int fd; 143*b3c0d957SAndrew Turner 144*b3c0d957SAndrew Turner fd = open_kcov(); 145*b3c0d957SAndrew Turner *(int *)data = fd; 146*b3c0d957SAndrew Turner 147*b3c0d957SAndrew Turner ATF_REQUIRE(ioctl(fd, KIOSETBUFSIZE, PAGE_SIZE / sizeof(uint64_t)) ==0); 148*b3c0d957SAndrew Turner ATF_CHECK(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, 149*b3c0d957SAndrew Turner fd, 0) != MAP_FAILED); 150*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIOENABLE, KCOV_MODE_TRACE_PC) == 0); 151*b3c0d957SAndrew Turner 152*b3c0d957SAndrew Turner sem_post(&sem1); 153*b3c0d957SAndrew Turner sem_wait(&sem2); 154*b3c0d957SAndrew Turner 155*b3c0d957SAndrew Turner return (NULL); 156*b3c0d957SAndrew Turner } 157*b3c0d957SAndrew Turner 158*b3c0d957SAndrew Turner ATF_TC_WITHOUT_HEAD(kcov_mmap_enable_thread_close); 159*b3c0d957SAndrew Turner ATF_TC_BODY(kcov_mmap_enable_thread_close, tc) 160*b3c0d957SAndrew Turner { 161*b3c0d957SAndrew Turner pthread_t thread; 162*b3c0d957SAndrew Turner int fd; 163*b3c0d957SAndrew Turner 164*b3c0d957SAndrew Turner sem_init(&sem1, 0, 0); 165*b3c0d957SAndrew Turner sem_init(&sem2, 0, 0); 166*b3c0d957SAndrew Turner pthread_create(&thread, NULL, 167*b3c0d957SAndrew Turner kcov_mmap_enable_thread, &fd); 168*b3c0d957SAndrew Turner sem_wait(&sem1); 169*b3c0d957SAndrew Turner close(fd); 170*b3c0d957SAndrew Turner sem_post(&sem2); 171*b3c0d957SAndrew Turner pthread_join(thread, NULL); 172*b3c0d957SAndrew Turner } 173*b3c0d957SAndrew Turner 174*b3c0d957SAndrew Turner ATF_TC_WITHOUT_HEAD(kcov_enable); 175*b3c0d957SAndrew Turner ATF_TC_BODY(kcov_enable, tc) 176*b3c0d957SAndrew Turner { 177*b3c0d957SAndrew Turner int fd; 178*b3c0d957SAndrew Turner 179*b3c0d957SAndrew Turner fd = open_kcov(); 180*b3c0d957SAndrew Turner 181*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIOENABLE, KCOV_MODE_TRACE_PC) == -1); 182*b3c0d957SAndrew Turner 183*b3c0d957SAndrew Turner ATF_REQUIRE(ioctl(fd, KIOSETBUFSIZE, PAGE_SIZE / sizeof(uint64_t)) ==0); 184*b3c0d957SAndrew Turner 185*b3c0d957SAndrew Turner /* We need to enable before disable */ 186*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIODISABLE, 0) == -1); 187*b3c0d957SAndrew Turner 188*b3c0d957SAndrew Turner /* Check enabling works only with a valid trace method */ 189*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIOENABLE, -1) == -1); 190*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIOENABLE, KCOV_MODE_TRACE_PC) == 0); 191*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIOENABLE, KCOV_MODE_TRACE_PC) == -1); 192*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIOENABLE, KCOV_MODE_TRACE_CMP) == -1); 193*b3c0d957SAndrew Turner 194*b3c0d957SAndrew Turner /* Disable should only be called once */ 195*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIODISABLE, 0) == 0); 196*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIODISABLE, 0) == -1); 197*b3c0d957SAndrew Turner 198*b3c0d957SAndrew Turner /* Re-enabling should also work */ 199*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIOENABLE, KCOV_MODE_TRACE_CMP) == 0); 200*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIODISABLE, 0) == 0); 201*b3c0d957SAndrew Turner 202*b3c0d957SAndrew Turner close(fd); 203*b3c0d957SAndrew Turner } 204*b3c0d957SAndrew Turner 205*b3c0d957SAndrew Turner ATF_TC_WITHOUT_HEAD(kcov_enable_no_disable); 206*b3c0d957SAndrew Turner ATF_TC_BODY(kcov_enable_no_disable, tc) 207*b3c0d957SAndrew Turner { 208*b3c0d957SAndrew Turner int fd; 209*b3c0d957SAndrew Turner 210*b3c0d957SAndrew Turner fd = open_kcov(); 211*b3c0d957SAndrew Turner ATF_REQUIRE(ioctl(fd, KIOSETBUFSIZE, PAGE_SIZE / sizeof(uint64_t)) ==0); 212*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIOENABLE, KCOV_MODE_TRACE_PC) == 0); 213*b3c0d957SAndrew Turner close(fd); 214*b3c0d957SAndrew Turner } 215*b3c0d957SAndrew Turner 216*b3c0d957SAndrew Turner ATF_TC_WITHOUT_HEAD(kcov_enable_no_disable_no_close); 217*b3c0d957SAndrew Turner ATF_TC_BODY(kcov_enable_no_disable_no_close, tc) 218*b3c0d957SAndrew Turner { 219*b3c0d957SAndrew Turner int fd; 220*b3c0d957SAndrew Turner 221*b3c0d957SAndrew Turner fd = open_kcov(); 222*b3c0d957SAndrew Turner ATF_REQUIRE(ioctl(fd, KIOSETBUFSIZE, PAGE_SIZE / sizeof(uint64_t)) ==0); 223*b3c0d957SAndrew Turner ATF_CHECK(ioctl(fd, KIOENABLE, KCOV_MODE_TRACE_PC) == 0); 224*b3c0d957SAndrew Turner } 225*b3c0d957SAndrew Turner 226*b3c0d957SAndrew Turner static void * 227*b3c0d957SAndrew Turner common_head(int *fdp) 228*b3c0d957SAndrew Turner { 229*b3c0d957SAndrew Turner void *data; 230*b3c0d957SAndrew Turner int fd; 231*b3c0d957SAndrew Turner 232*b3c0d957SAndrew Turner fd = open_kcov(); 233*b3c0d957SAndrew Turner 234*b3c0d957SAndrew Turner ATF_REQUIRE_MSG(ioctl(fd, KIOSETBUFSIZE, 235*b3c0d957SAndrew Turner PAGE_SIZE / sizeof(uint64_t)) == 0, 236*b3c0d957SAndrew Turner "Unable to set the kcov buffer size"); 237*b3c0d957SAndrew Turner 238*b3c0d957SAndrew Turner data = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 239*b3c0d957SAndrew Turner ATF_REQUIRE_MSG(data != MAP_FAILED, "Unable to mmap the kcov buffer"); 240*b3c0d957SAndrew Turner 241*b3c0d957SAndrew Turner *fdp = fd; 242*b3c0d957SAndrew Turner return (data); 243*b3c0d957SAndrew Turner } 244*b3c0d957SAndrew Turner 245*b3c0d957SAndrew Turner static void 246*b3c0d957SAndrew Turner common_tail(int fd, void *data) 247*b3c0d957SAndrew Turner { 248*b3c0d957SAndrew Turner 249*b3c0d957SAndrew Turner ATF_REQUIRE_MSG(munmap(data, PAGE_SIZE) == 0, 250*b3c0d957SAndrew Turner "Unable to unmap the kcov buffer"); 251*b3c0d957SAndrew Turner 252*b3c0d957SAndrew Turner close(fd); 253*b3c0d957SAndrew Turner } 254*b3c0d957SAndrew Turner 255*b3c0d957SAndrew Turner static void 256*b3c0d957SAndrew Turner basic_test(u_int mode) 257*b3c0d957SAndrew Turner { 258*b3c0d957SAndrew Turner uint64_t *buf; 259*b3c0d957SAndrew Turner int fd; 260*b3c0d957SAndrew Turner 261*b3c0d957SAndrew Turner buf = common_head(&fd); 262*b3c0d957SAndrew Turner ATF_REQUIRE_MSG(ioctl(fd, KIOENABLE, mode) == 0, 263*b3c0d957SAndrew Turner "Unable to enable kcov %s", 264*b3c0d957SAndrew Turner mode < nitems(modes) ? modes[mode] : "unknown mode"); 265*b3c0d957SAndrew Turner 266*b3c0d957SAndrew Turner atomic_store_64(&buf[0], 0); 267*b3c0d957SAndrew Turner 268*b3c0d957SAndrew Turner sleep(0); 269*b3c0d957SAndrew Turner ATF_REQUIRE_MSG(atomic_load_64(&buf[0]) != 0, "No records found"); 270*b3c0d957SAndrew Turner 271*b3c0d957SAndrew Turner ATF_REQUIRE_MSG(ioctl(fd, KIODISABLE, 0) == 0, 272*b3c0d957SAndrew Turner "Unable to disable kcov"); 273*b3c0d957SAndrew Turner 274*b3c0d957SAndrew Turner common_tail(fd, buf); 275*b3c0d957SAndrew Turner } 276*b3c0d957SAndrew Turner 277*b3c0d957SAndrew Turner ATF_TC_WITHOUT_HEAD(kcov_basic_pc); 278*b3c0d957SAndrew Turner ATF_TC_BODY(kcov_basic_pc, tc) 279*b3c0d957SAndrew Turner { 280*b3c0d957SAndrew Turner basic_test(KCOV_MODE_TRACE_PC); 281*b3c0d957SAndrew Turner } 282*b3c0d957SAndrew Turner 283*b3c0d957SAndrew Turner ATF_TC_WITHOUT_HEAD(kcov_basic_cmp); 284*b3c0d957SAndrew Turner ATF_TC_BODY(kcov_basic_cmp, tc) 285*b3c0d957SAndrew Turner { 286*b3c0d957SAndrew Turner basic_test(KCOV_MODE_TRACE_CMP); 287*b3c0d957SAndrew Turner } 288*b3c0d957SAndrew Turner 289*b3c0d957SAndrew Turner static void * 290*b3c0d957SAndrew Turner thread_test_helper(void *ptr) 291*b3c0d957SAndrew Turner { 292*b3c0d957SAndrew Turner uint64_t *buf = ptr; 293*b3c0d957SAndrew Turner 294*b3c0d957SAndrew Turner atomic_store_64(&buf[0], 0); 295*b3c0d957SAndrew Turner sleep(0); 296*b3c0d957SAndrew Turner ATF_REQUIRE_MSG(atomic_load_64(&buf[0]) == 0, 297*b3c0d957SAndrew Turner "Records changed in blocked thread"); 298*b3c0d957SAndrew Turner 299*b3c0d957SAndrew Turner return (NULL); 300*b3c0d957SAndrew Turner } 301*b3c0d957SAndrew Turner 302*b3c0d957SAndrew Turner static void 303*b3c0d957SAndrew Turner thread_test(u_int mode) 304*b3c0d957SAndrew Turner { 305*b3c0d957SAndrew Turner pthread_t thread; 306*b3c0d957SAndrew Turner uint64_t *buf; 307*b3c0d957SAndrew Turner int fd; 308*b3c0d957SAndrew Turner 309*b3c0d957SAndrew Turner buf = common_head(&fd); 310*b3c0d957SAndrew Turner 311*b3c0d957SAndrew Turner ATF_REQUIRE_MSG(ioctl(fd, KIOENABLE, mode) == 0, 312*b3c0d957SAndrew Turner "Unable to enable kcov %s", 313*b3c0d957SAndrew Turner mode < nitems(modes) ? modes[mode] : "unknown mode"); 314*b3c0d957SAndrew Turner 315*b3c0d957SAndrew Turner pthread_create(&thread, NULL, thread_test_helper, buf); 316*b3c0d957SAndrew Turner pthread_join(thread, NULL); 317*b3c0d957SAndrew Turner 318*b3c0d957SAndrew Turner ATF_REQUIRE_MSG(ioctl(fd, KIODISABLE, 0) == 0, 319*b3c0d957SAndrew Turner "Unable to disable kcov"); 320*b3c0d957SAndrew Turner 321*b3c0d957SAndrew Turner common_tail(fd, buf); 322*b3c0d957SAndrew Turner } 323*b3c0d957SAndrew Turner 324*b3c0d957SAndrew Turner ATF_TC_WITHOUT_HEAD(kcov_thread_pc); 325*b3c0d957SAndrew Turner ATF_TC_BODY(kcov_thread_pc, tc) 326*b3c0d957SAndrew Turner { 327*b3c0d957SAndrew Turner thread_test(KCOV_MODE_TRACE_PC); 328*b3c0d957SAndrew Turner } 329*b3c0d957SAndrew Turner 330*b3c0d957SAndrew Turner ATF_TC_WITHOUT_HEAD(kcov_thread_cmp); 331*b3c0d957SAndrew Turner ATF_TC_BODY(kcov_thread_cmp, tc) 332*b3c0d957SAndrew Turner { 333*b3c0d957SAndrew Turner thread_test(KCOV_MODE_TRACE_CMP); 334*b3c0d957SAndrew Turner } 335*b3c0d957SAndrew Turner 336*b3c0d957SAndrew Turner struct multi_thread_data { 337*b3c0d957SAndrew Turner char *buf; 338*b3c0d957SAndrew Turner int fd; 339*b3c0d957SAndrew Turner u_int mode; 340*b3c0d957SAndrew Turner int thread; 341*b3c0d957SAndrew Turner }; 342*b3c0d957SAndrew Turner 343*b3c0d957SAndrew Turner static void * 344*b3c0d957SAndrew Turner multi_thread_test_helper(void *ptr) 345*b3c0d957SAndrew Turner { 346*b3c0d957SAndrew Turner struct multi_thread_data *data = ptr; 347*b3c0d957SAndrew Turner 348*b3c0d957SAndrew Turner ATF_REQUIRE_MSG(ioctl(data->fd, KIOENABLE, data->mode) == 0, 349*b3c0d957SAndrew Turner "Unable to enable kcov %s in thread %d", 350*b3c0d957SAndrew Turner data->mode < nitems(modes) ? modes[data->mode] : "unknown mode", 351*b3c0d957SAndrew Turner data->thread); 352*b3c0d957SAndrew Turner 353*b3c0d957SAndrew Turner atomic_store_64(&data->buf[0], 0); 354*b3c0d957SAndrew Turner sleep(0); 355*b3c0d957SAndrew Turner ATF_REQUIRE_MSG(atomic_load_64(&data->buf[0]) != 0, 356*b3c0d957SAndrew Turner "No records found in thread %d", data->thread); 357*b3c0d957SAndrew Turner 358*b3c0d957SAndrew Turner return (NULL); 359*b3c0d957SAndrew Turner } 360*b3c0d957SAndrew Turner 361*b3c0d957SAndrew Turner ATF_TC_WITHOUT_HEAD(kcov_enable_multi_thread); 362*b3c0d957SAndrew Turner ATF_TC_BODY(kcov_enable_multi_thread, t) 363*b3c0d957SAndrew Turner { 364*b3c0d957SAndrew Turner struct multi_thread_data data; 365*b3c0d957SAndrew Turner pthread_t thread; 366*b3c0d957SAndrew Turner 367*b3c0d957SAndrew Turner data.buf = common_head(&data.fd); 368*b3c0d957SAndrew Turner 369*b3c0d957SAndrew Turner /* Run the thread to completion */ 370*b3c0d957SAndrew Turner data.thread = 1; 371*b3c0d957SAndrew Turner data.mode = KCOV_MODE_TRACE_PC; 372*b3c0d957SAndrew Turner pthread_create(&thread, NULL, multi_thread_test_helper, &data); 373*b3c0d957SAndrew Turner pthread_join(thread, NULL); 374*b3c0d957SAndrew Turner 375*b3c0d957SAndrew Turner /* Run it again to check enable works on the same fd */ 376*b3c0d957SAndrew Turner data.thread = 2; 377*b3c0d957SAndrew Turner data.mode = KCOV_MODE_TRACE_CMP; 378*b3c0d957SAndrew Turner pthread_create(&thread, NULL, multi_thread_test_helper, &data); 379*b3c0d957SAndrew Turner pthread_join(thread, NULL); 380*b3c0d957SAndrew Turner 381*b3c0d957SAndrew Turner common_tail(data.fd, data.buf); 382*b3c0d957SAndrew Turner } 383*b3c0d957SAndrew Turner 384*b3c0d957SAndrew Turner ATF_TP_ADD_TCS(tp) 385*b3c0d957SAndrew Turner { 386*b3c0d957SAndrew Turner 387*b3c0d957SAndrew Turner ATF_TP_ADD_TC(tp, kcov_bufsize); 388*b3c0d957SAndrew Turner ATF_TP_ADD_TC(tp, kcov_mmap); 389*b3c0d957SAndrew Turner ATF_TP_ADD_TC(tp, kcov_mmap_no_munmap); 390*b3c0d957SAndrew Turner ATF_TP_ADD_TC(tp, kcov_mmap_no_munmap_no_close); 391*b3c0d957SAndrew Turner ATF_TP_ADD_TC(tp, kcov_enable); 392*b3c0d957SAndrew Turner ATF_TP_ADD_TC(tp, kcov_enable_no_disable); 393*b3c0d957SAndrew Turner ATF_TP_ADD_TC(tp, kcov_enable_no_disable_no_close); 394*b3c0d957SAndrew Turner ATF_TP_ADD_TC(tp, kcov_mmap_enable_thread_close); 395*b3c0d957SAndrew Turner ATF_TP_ADD_TC(tp, kcov_basic_pc); 396*b3c0d957SAndrew Turner ATF_TP_ADD_TC(tp, kcov_basic_cmp); 397*b3c0d957SAndrew Turner ATF_TP_ADD_TC(tp, kcov_thread_pc); 398*b3c0d957SAndrew Turner ATF_TP_ADD_TC(tp, kcov_thread_cmp); 399*b3c0d957SAndrew Turner ATF_TP_ADD_TC(tp, kcov_enable_multi_thread); 400*b3c0d957SAndrew Turner return (atf_no_error()); 401*b3c0d957SAndrew Turner } 402