1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2023-2025 Ruslan Bukin <br@bsdpad.com> 5 * 6 * This work was supported by Innovate UK project 105694, "Digital Security 7 * by Design (DSbD) Technology Platform Prototype". 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/param.h> 32 #include <sys/kernel.h> 33 #include <sys/malloc.h> 34 #include <sys/lock.h> 35 #include <sys/mutex.h> 36 #include <sys/refcount.h> 37 #include <sys/rwlock.h> 38 #include <sys/hwt.h> 39 40 #include <vm/vm.h> 41 #include <vm/vm_param.h> 42 #include <vm/vm_kern.h> 43 #include <vm/vm_page.h> 44 #include <vm/vm_object.h> 45 #include <vm/vm_pager.h> 46 #include <vm/vm_pageout.h> 47 #include <vm/vm_phys.h> 48 49 #include <dev/hwt/hwt_hook.h> 50 #include <dev/hwt/hwt_context.h> 51 #include <dev/hwt/hwt_contexthash.h> 52 #include <dev/hwt/hwt_config.h> 53 #include <dev/hwt/hwt_thread.h> 54 #include <dev/hwt/hwt_owner.h> 55 #include <dev/hwt/hwt_ownerhash.h> 56 #include <dev/hwt/hwt_backend.h> 57 #include <dev/hwt/hwt_vm.h> 58 #include <dev/hwt/hwt_record.h> 59 60 #define HWT_THREAD_DEBUG 61 #undef HWT_THREAD_DEBUG 62 63 #ifdef HWT_THREAD_DEBUG 64 #define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) 65 #else 66 #define dprintf(fmt, ...) 67 #endif 68 69 static MALLOC_DEFINE(M_HWT_THREAD, "hwt_thread", "Hardware Trace"); 70 71 struct hwt_thread * 72 hwt_thread_first(struct hwt_context *ctx) 73 { 74 struct hwt_thread *thr; 75 76 HWT_CTX_ASSERT_LOCKED(ctx); 77 78 thr = TAILQ_FIRST(&ctx->threads); 79 80 KASSERT(thr != NULL, ("thr is NULL")); 81 82 return (thr); 83 } 84 85 /* 86 * To use by hwt_switch_in/out() only. 87 */ 88 struct hwt_thread * 89 hwt_thread_lookup(struct hwt_context *ctx, struct thread *td) 90 { 91 struct hwt_thread *thr; 92 93 /* Caller of this func holds ctx refcnt right here. */ 94 95 HWT_CTX_LOCK(ctx); 96 TAILQ_FOREACH(thr, &ctx->threads, next) { 97 if (thr->td == td) { 98 HWT_CTX_UNLOCK(ctx); 99 return (thr); 100 } 101 } 102 HWT_CTX_UNLOCK(ctx); 103 104 /* 105 * We are here because the hook on thread creation failed to allocate 106 * a thread. 107 */ 108 109 return (NULL); 110 } 111 112 int 113 hwt_thread_alloc(struct hwt_thread **thr0, char *path, size_t bufsize, 114 int kva_req) 115 { 116 struct hwt_thread *thr; 117 struct hwt_vm *vm; 118 int error; 119 120 error = hwt_vm_alloc(bufsize, kva_req, path, &vm); 121 if (error) 122 return (error); 123 124 thr = malloc(sizeof(struct hwt_thread), M_HWT_THREAD, 125 M_WAITOK | M_ZERO); 126 thr->vm = vm; 127 128 mtx_init(&thr->mtx, "thr", NULL, MTX_DEF); 129 130 refcount_init(&thr->refcnt, 1); 131 132 vm->thr = thr; 133 134 *thr0 = thr; 135 136 return (0); 137 } 138 139 void 140 hwt_thread_free(struct hwt_thread *thr) 141 { 142 143 hwt_vm_free(thr->vm); 144 /* Free private backend data, if any. */ 145 if (thr->private != NULL) 146 hwt_backend_thread_free(thr); 147 free(thr, M_HWT_THREAD); 148 } 149 150 /* 151 * Inserts a new thread and a thread creation record into the 152 * context notifies userspace about the newly created thread. 153 */ 154 void 155 hwt_thread_insert(struct hwt_context *ctx, struct hwt_thread *thr, 156 struct hwt_record_entry *entry) 157 { 158 159 HWT_CTX_ASSERT_LOCKED(ctx); 160 TAILQ_INSERT_TAIL(&ctx->threads, thr, next); 161 TAILQ_INSERT_TAIL(&ctx->records, entry, next); 162 } 163