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