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