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 *
hwt_thread_first(struct hwt_context * ctx)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 *
hwt_thread_lookup(struct hwt_context * ctx,struct thread * td)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
hwt_thread_alloc(struct hwt_thread ** thr0,char * path,size_t bufsize,int kva_req)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
hwt_thread_free(struct hwt_thread * thr)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
hwt_thread_insert(struct hwt_context * ctx,struct hwt_thread * thr,struct hwt_record_entry * entry)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