xref: /freebsd/sys/dev/hwt/hwt_owner.c (revision df114daef4c48548c3c2b86717612761185ae18f)
1*df114daeSRuslan Bukin /*-
2*df114daeSRuslan Bukin  * SPDX-License-Identifier: BSD-2-Clause
3*df114daeSRuslan Bukin  *
4*df114daeSRuslan Bukin  * Copyright (c) 2023-2025 Ruslan Bukin <br@bsdpad.com>
5*df114daeSRuslan Bukin  *
6*df114daeSRuslan Bukin  * This work was supported by Innovate UK project 105694, "Digital Security
7*df114daeSRuslan Bukin  * by Design (DSbD) Technology Platform Prototype".
8*df114daeSRuslan Bukin  *
9*df114daeSRuslan Bukin  * Redistribution and use in source and binary forms, with or without
10*df114daeSRuslan Bukin  * modification, are permitted provided that the following conditions
11*df114daeSRuslan Bukin  * are met:
12*df114daeSRuslan Bukin  * 1. Redistributions of source code must retain the above copyright
13*df114daeSRuslan Bukin  *    notice, this list of conditions and the following disclaimer.
14*df114daeSRuslan Bukin  * 2. Redistributions in binary form must reproduce the above copyright
15*df114daeSRuslan Bukin  *    notice, this list of conditions and the following disclaimer in the
16*df114daeSRuslan Bukin  *    documentation and/or other materials provided with the distribution.
17*df114daeSRuslan Bukin  *
18*df114daeSRuslan Bukin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19*df114daeSRuslan Bukin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*df114daeSRuslan Bukin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*df114daeSRuslan Bukin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22*df114daeSRuslan Bukin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*df114daeSRuslan Bukin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*df114daeSRuslan Bukin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*df114daeSRuslan Bukin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*df114daeSRuslan Bukin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*df114daeSRuslan Bukin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*df114daeSRuslan Bukin  * SUCH DAMAGE.
29*df114daeSRuslan Bukin  */
30*df114daeSRuslan Bukin 
31*df114daeSRuslan Bukin #include <sys/param.h>
32*df114daeSRuslan Bukin #include <sys/kernel.h>
33*df114daeSRuslan Bukin #include <sys/malloc.h>
34*df114daeSRuslan Bukin #include <sys/mman.h>
35*df114daeSRuslan Bukin #include <sys/mutex.h>
36*df114daeSRuslan Bukin #include <sys/refcount.h>
37*df114daeSRuslan Bukin #include <sys/rwlock.h>
38*df114daeSRuslan Bukin #include <sys/hwt.h>
39*df114daeSRuslan Bukin 
40*df114daeSRuslan Bukin #include <dev/hwt/hwt_hook.h>
41*df114daeSRuslan Bukin #include <dev/hwt/hwt_context.h>
42*df114daeSRuslan Bukin #include <dev/hwt/hwt_contexthash.h>
43*df114daeSRuslan Bukin #include <dev/hwt/hwt_config.h>
44*df114daeSRuslan Bukin #include <dev/hwt/hwt_cpu.h>
45*df114daeSRuslan Bukin #include <dev/hwt/hwt_thread.h>
46*df114daeSRuslan Bukin #include <dev/hwt/hwt_owner.h>
47*df114daeSRuslan Bukin #include <dev/hwt/hwt_ownerhash.h>
48*df114daeSRuslan Bukin #include <dev/hwt/hwt_backend.h>
49*df114daeSRuslan Bukin #include <dev/hwt/hwt_vm.h>
50*df114daeSRuslan Bukin #include <dev/hwt/hwt_record.h>
51*df114daeSRuslan Bukin 
52*df114daeSRuslan Bukin #define	HWT_DEBUG
53*df114daeSRuslan Bukin #undef	HWT_DEBUG
54*df114daeSRuslan Bukin 
55*df114daeSRuslan Bukin #ifdef	HWT_DEBUG
56*df114daeSRuslan Bukin #define	dprintf(fmt, ...)	printf(fmt, ##__VA_ARGS__)
57*df114daeSRuslan Bukin #else
58*df114daeSRuslan Bukin #define	dprintf(fmt, ...)
59*df114daeSRuslan Bukin #endif
60*df114daeSRuslan Bukin 
61*df114daeSRuslan Bukin static MALLOC_DEFINE(M_HWT_OWNER, "hwt_owner", "Hardware Trace");
62*df114daeSRuslan Bukin 
63*df114daeSRuslan Bukin struct hwt_context *
hwt_owner_lookup_ctx(struct hwt_owner * ho,pid_t pid)64*df114daeSRuslan Bukin hwt_owner_lookup_ctx(struct hwt_owner *ho, pid_t pid)
65*df114daeSRuslan Bukin {
66*df114daeSRuslan Bukin 	struct hwt_context *ctx;
67*df114daeSRuslan Bukin 
68*df114daeSRuslan Bukin 	mtx_lock(&ho->mtx);
69*df114daeSRuslan Bukin 	LIST_FOREACH(ctx, &ho->hwts, next_hwts) {
70*df114daeSRuslan Bukin 		if (ctx->pid == pid) {
71*df114daeSRuslan Bukin 			mtx_unlock(&ho->mtx);
72*df114daeSRuslan Bukin 			return (ctx);
73*df114daeSRuslan Bukin 		}
74*df114daeSRuslan Bukin 	}
75*df114daeSRuslan Bukin 	mtx_unlock(&ho->mtx);
76*df114daeSRuslan Bukin 
77*df114daeSRuslan Bukin 	return (NULL);
78*df114daeSRuslan Bukin }
79*df114daeSRuslan Bukin 
80*df114daeSRuslan Bukin #if 0
81*df114daeSRuslan Bukin struct hwt_context *
82*df114daeSRuslan Bukin hwt_owner_lookup_ctx_by_cpu(struct hwt_owner *ho, int cpu)
83*df114daeSRuslan Bukin {
84*df114daeSRuslan Bukin 	struct hwt_context *ctx;
85*df114daeSRuslan Bukin 
86*df114daeSRuslan Bukin 	mtx_lock(&ho->mtx);
87*df114daeSRuslan Bukin 	LIST_FOREACH(ctx, &ho->hwts, next_hwts) {
88*df114daeSRuslan Bukin 		if (ctx->cpu == cpu) {
89*df114daeSRuslan Bukin 			mtx_unlock(&ho->mtx);
90*df114daeSRuslan Bukin 			return (ctx);
91*df114daeSRuslan Bukin 		}
92*df114daeSRuslan Bukin 	}
93*df114daeSRuslan Bukin 	mtx_unlock(&ho->mtx);
94*df114daeSRuslan Bukin 
95*df114daeSRuslan Bukin 	return (NULL);
96*df114daeSRuslan Bukin }
97*df114daeSRuslan Bukin #endif
98*df114daeSRuslan Bukin 
99*df114daeSRuslan Bukin struct hwt_owner *
hwt_owner_alloc(struct proc * p)100*df114daeSRuslan Bukin hwt_owner_alloc(struct proc *p)
101*df114daeSRuslan Bukin {
102*df114daeSRuslan Bukin 	struct hwt_owner *ho;
103*df114daeSRuslan Bukin 
104*df114daeSRuslan Bukin 	ho = malloc(sizeof(struct hwt_owner), M_HWT_OWNER,
105*df114daeSRuslan Bukin 	    M_WAITOK | M_ZERO);
106*df114daeSRuslan Bukin 	ho->p = p;
107*df114daeSRuslan Bukin 
108*df114daeSRuslan Bukin 	LIST_INIT(&ho->hwts);
109*df114daeSRuslan Bukin 	mtx_init(&ho->mtx, "hwts", NULL, MTX_DEF);
110*df114daeSRuslan Bukin 
111*df114daeSRuslan Bukin 	return (ho);
112*df114daeSRuslan Bukin }
113*df114daeSRuslan Bukin 
114*df114daeSRuslan Bukin void
hwt_owner_shutdown(struct hwt_owner * ho)115*df114daeSRuslan Bukin hwt_owner_shutdown(struct hwt_owner *ho)
116*df114daeSRuslan Bukin {
117*df114daeSRuslan Bukin 	struct hwt_context *ctx;
118*df114daeSRuslan Bukin 
119*df114daeSRuslan Bukin 	dprintf("%s: stopping hwt owner\n", __func__);
120*df114daeSRuslan Bukin 
121*df114daeSRuslan Bukin 	while (1) {
122*df114daeSRuslan Bukin 		mtx_lock(&ho->mtx);
123*df114daeSRuslan Bukin 		ctx = LIST_FIRST(&ho->hwts);
124*df114daeSRuslan Bukin 		if (ctx)
125*df114daeSRuslan Bukin 			LIST_REMOVE(ctx, next_hwts);
126*df114daeSRuslan Bukin 		mtx_unlock(&ho->mtx);
127*df114daeSRuslan Bukin 
128*df114daeSRuslan Bukin 		if (ctx == NULL)
129*df114daeSRuslan Bukin 			break;
130*df114daeSRuslan Bukin 
131*df114daeSRuslan Bukin 		if (ctx->mode == HWT_MODE_THREAD)
132*df114daeSRuslan Bukin 			hwt_contexthash_remove(ctx);
133*df114daeSRuslan Bukin 
134*df114daeSRuslan Bukin 		/*
135*df114daeSRuslan Bukin 		 * A hook could be still dealing with this ctx right here.
136*df114daeSRuslan Bukin 		 */
137*df114daeSRuslan Bukin 
138*df114daeSRuslan Bukin 		HWT_CTX_LOCK(ctx);
139*df114daeSRuslan Bukin 		ctx->state = 0;
140*df114daeSRuslan Bukin 		HWT_CTX_UNLOCK(ctx);
141*df114daeSRuslan Bukin 
142*df114daeSRuslan Bukin 		/* Ensure hooks invocation is now completed. */
143*df114daeSRuslan Bukin 		while (refcount_load(&ctx->refcnt) > 0)
144*df114daeSRuslan Bukin 			continue;
145*df114daeSRuslan Bukin 
146*df114daeSRuslan Bukin 		/*
147*df114daeSRuslan Bukin 		 * Note that a thread could be still sleeping on msleep(9).
148*df114daeSRuslan Bukin 		 */
149*df114daeSRuslan Bukin 
150*df114daeSRuslan Bukin 		hwt_backend_deinit(ctx);
151*df114daeSRuslan Bukin 		hwt_record_free_all(ctx);
152*df114daeSRuslan Bukin 		hwt_ctx_free(ctx);
153*df114daeSRuslan Bukin 	}
154*df114daeSRuslan Bukin 
155*df114daeSRuslan Bukin 	hwt_ownerhash_remove(ho);
156*df114daeSRuslan Bukin 	free(ho, M_HWT_OWNER);
157*df114daeSRuslan Bukin }
158