xref: /freebsd/sys/dev/hwt/hwt_thread.c (revision df114daef4c48548c3c2b86717612761185ae18f)
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