1f0bc4ed1SChristos Margiolis /*
2f0bc4ed1SChristos Margiolis * SPDX-License-Identifier: CDDL 1.0
3f0bc4ed1SChristos Margiolis *
49310bf54SChristos Margiolis * Copyright (c) 2022 Christos Margiolis <christos@FreeBSD.org>
59310bf54SChristos Margiolis * Copyright (c) 2022 Mark Johnston <markj@FreeBSD.org>
69310bf54SChristos Margiolis * Copyright (c) 2023 The FreeBSD Foundation
79310bf54SChristos Margiolis *
89310bf54SChristos Margiolis * Portions of this software were developed by Christos Margiolis
99310bf54SChristos Margiolis * <christos@FreeBSD.org> under sponsorship from the FreeBSD Foundation.
10f0bc4ed1SChristos Margiolis */
11f0bc4ed1SChristos Margiolis
12f0bc4ed1SChristos Margiolis #include <sys/param.h>
13f0bc4ed1SChristos Margiolis #include <sys/bitset.h>
14f0bc4ed1SChristos Margiolis #include <sys/cred.h>
15f0bc4ed1SChristos Margiolis #include <sys/eventhandler.h>
16f0bc4ed1SChristos Margiolis #include <sys/kernel.h>
17f0bc4ed1SChristos Margiolis #include <sys/lock.h>
18f0bc4ed1SChristos Margiolis #include <sys/malloc.h>
19f0bc4ed1SChristos Margiolis #include <sys/proc.h>
20f0bc4ed1SChristos Margiolis #include <sys/queue.h>
21f0bc4ed1SChristos Margiolis #include <sys/sx.h>
22f0bc4ed1SChristos Margiolis
23f0bc4ed1SChristos Margiolis #include <vm/vm.h>
24f0bc4ed1SChristos Margiolis #include <vm/vm_param.h>
25f0bc4ed1SChristos Margiolis #include <vm/pmap.h>
26f0bc4ed1SChristos Margiolis #include <vm/vm_map.h>
27f0bc4ed1SChristos Margiolis #include <vm/vm_kern.h>
28f0bc4ed1SChristos Margiolis #include <vm/vm_object.h>
29f0bc4ed1SChristos Margiolis
30f0bc4ed1SChristos Margiolis #include <cddl/dev/dtrace/dtrace_cddl.h>
31f0bc4ed1SChristos Margiolis
32f0bc4ed1SChristos Margiolis #include "kinst.h"
33f0bc4ed1SChristos Margiolis #include "kinst_isa.h"
34f0bc4ed1SChristos Margiolis
359b091f12SChristos Margiolis #define KINST_TRAMP_FILL_PATTERN ((kinst_patchval_t []){KINST_PATCHVAL})
369b091f12SChristos Margiolis #define KINST_TRAMP_FILL_SIZE sizeof(kinst_patchval_t)
379b091f12SChristos Margiolis
3833373127SChristos Margiolis #define KINST_TRAMPCHUNK_SIZE PAGE_SIZE
39f0bc4ed1SChristos Margiolis #define KINST_TRAMPS_PER_CHUNK (KINST_TRAMPCHUNK_SIZE / KINST_TRAMP_SIZE)
40f0bc4ed1SChristos Margiolis
41f0bc4ed1SChristos Margiolis struct trampchunk {
42f0bc4ed1SChristos Margiolis TAILQ_ENTRY(trampchunk) next;
43f0bc4ed1SChristos Margiolis uint8_t *addr;
44f0bc4ed1SChristos Margiolis /* 0 -> allocated, 1 -> free */
45f0bc4ed1SChristos Margiolis BITSET_DEFINE(, KINST_TRAMPS_PER_CHUNK) free;
46f0bc4ed1SChristos Margiolis };
47f0bc4ed1SChristos Margiolis
48f0bc4ed1SChristos Margiolis static TAILQ_HEAD(, trampchunk) kinst_trampchunks =
49f0bc4ed1SChristos Margiolis TAILQ_HEAD_INITIALIZER(kinst_trampchunks);
50f0bc4ed1SChristos Margiolis static struct sx kinst_tramp_sx;
51f0bc4ed1SChristos Margiolis SX_SYSINIT(kinst_tramp_sx, &kinst_tramp_sx, "kinst tramp");
52*5b701ed1SChristos Margiolis #ifdef __amd64__
53f0bc4ed1SChristos Margiolis static eventhandler_tag kinst_thread_ctor_handler;
54f0bc4ed1SChristos Margiolis static eventhandler_tag kinst_thread_dtor_handler;
55*5b701ed1SChristos Margiolis #endif
56f0bc4ed1SChristos Margiolis
57ecca3180SChristos Margiolis /*
58ecca3180SChristos Margiolis * Fill the trampolines with KINST_TRAMP_FILL_PATTERN so that the kernel will
59ecca3180SChristos Margiolis * crash cleanly if things somehow go wrong.
60ecca3180SChristos Margiolis */
61ecca3180SChristos Margiolis static void
kinst_trampoline_fill(uint8_t * addr,int size)62ecca3180SChristos Margiolis kinst_trampoline_fill(uint8_t *addr, int size)
63ecca3180SChristos Margiolis {
64ecca3180SChristos Margiolis int i;
65ecca3180SChristos Margiolis
66ecca3180SChristos Margiolis for (i = 0; i < size; i += KINST_TRAMP_FILL_SIZE) {
67ecca3180SChristos Margiolis memcpy(&addr[i], KINST_TRAMP_FILL_PATTERN,
68ecca3180SChristos Margiolis KINST_TRAMP_FILL_SIZE);
69ecca3180SChristos Margiolis }
70ecca3180SChristos Margiolis }
71ecca3180SChristos Margiolis
72f0bc4ed1SChristos Margiolis static struct trampchunk *
kinst_trampchunk_alloc(void)73f0bc4ed1SChristos Margiolis kinst_trampchunk_alloc(void)
74f0bc4ed1SChristos Margiolis {
75f0bc4ed1SChristos Margiolis struct trampchunk *chunk;
76f0bc4ed1SChristos Margiolis vm_offset_t trampaddr;
77f0bc4ed1SChristos Margiolis int error __diagused;
78f0bc4ed1SChristos Margiolis
79f0bc4ed1SChristos Margiolis sx_assert(&kinst_tramp_sx, SX_XLOCKED);
80f0bc4ed1SChristos Margiolis
81855ade9eSChristos Margiolis #ifdef __amd64__
82f0bc4ed1SChristos Margiolis /*
83855ade9eSChristos Margiolis * To simplify population of trampolines, we follow the amd64 kernel's
84855ade9eSChristos Margiolis * code model and allocate them above KERNBASE, i.e., in the top 2GB of
85855ade9eSChristos Margiolis * the kernel's virtual address space (not the case for other
86855ade9eSChristos Margiolis * platforms).
87f0bc4ed1SChristos Margiolis */
88f0bc4ed1SChristos Margiolis trampaddr = KERNBASE;
89855ade9eSChristos Margiolis #else
90855ade9eSChristos Margiolis trampaddr = VM_MIN_KERNEL_ADDRESS;
91855ade9eSChristos Margiolis #endif
92855ade9eSChristos Margiolis /*
93855ade9eSChristos Margiolis * Allocate virtual memory for the trampoline chunk. The returned
94855ade9eSChristos Margiolis * address is saved in "trampaddr". Trampolines must be executable so
95855ade9eSChristos Margiolis * max_prot must include VM_PROT_EXECUTE.
96855ade9eSChristos Margiolis */
97f0bc4ed1SChristos Margiolis error = vm_map_find(kernel_map, NULL, 0, &trampaddr,
98f0bc4ed1SChristos Margiolis KINST_TRAMPCHUNK_SIZE, 0, VMFS_ANY_SPACE, VM_PROT_ALL, VM_PROT_ALL,
99f0bc4ed1SChristos Margiolis 0);
100f0bc4ed1SChristos Margiolis if (error != KERN_SUCCESS) {
101f0bc4ed1SChristos Margiolis KINST_LOG("trampoline chunk allocation failed: %d", error);
102f0bc4ed1SChristos Margiolis return (NULL);
103f0bc4ed1SChristos Margiolis }
104f0bc4ed1SChristos Margiolis
105f0bc4ed1SChristos Margiolis error = kmem_back(kernel_object, trampaddr, KINST_TRAMPCHUNK_SIZE,
106f0bc4ed1SChristos Margiolis M_WAITOK | M_EXEC);
107f0bc4ed1SChristos Margiolis KASSERT(error == KERN_SUCCESS, ("kmem_back failed: %d", error));
108f0bc4ed1SChristos Margiolis
109ecca3180SChristos Margiolis kinst_trampoline_fill((uint8_t *)trampaddr, KINST_TRAMPCHUNK_SIZE);
110f0bc4ed1SChristos Margiolis
111f0bc4ed1SChristos Margiolis /* Allocate a tracker for this chunk. */
112f0bc4ed1SChristos Margiolis chunk = malloc(sizeof(*chunk), M_KINST, M_WAITOK);
113f0bc4ed1SChristos Margiolis chunk->addr = (void *)trampaddr;
114f0bc4ed1SChristos Margiolis BIT_FILL(KINST_TRAMPS_PER_CHUNK, &chunk->free);
115f0bc4ed1SChristos Margiolis
116f0bc4ed1SChristos Margiolis TAILQ_INSERT_HEAD(&kinst_trampchunks, chunk, next);
117f0bc4ed1SChristos Margiolis
118f0bc4ed1SChristos Margiolis return (chunk);
119f0bc4ed1SChristos Margiolis }
120f0bc4ed1SChristos Margiolis
121f0bc4ed1SChristos Margiolis static void
kinst_trampchunk_free(struct trampchunk * chunk)122f0bc4ed1SChristos Margiolis kinst_trampchunk_free(struct trampchunk *chunk)
123f0bc4ed1SChristos Margiolis {
124f0bc4ed1SChristos Margiolis sx_assert(&kinst_tramp_sx, SX_XLOCKED);
125f0bc4ed1SChristos Margiolis
126f0bc4ed1SChristos Margiolis TAILQ_REMOVE(&kinst_trampchunks, chunk, next);
127f0bc4ed1SChristos Margiolis kmem_unback(kernel_object, (vm_offset_t)chunk->addr,
128f0bc4ed1SChristos Margiolis KINST_TRAMPCHUNK_SIZE);
129f0bc4ed1SChristos Margiolis (void)vm_map_remove(kernel_map, (vm_offset_t)chunk->addr,
130f0bc4ed1SChristos Margiolis (vm_offset_t)(chunk->addr + KINST_TRAMPCHUNK_SIZE));
131f0bc4ed1SChristos Margiolis free(chunk, M_KINST);
132f0bc4ed1SChristos Margiolis }
133f0bc4ed1SChristos Margiolis
134f0bc4ed1SChristos Margiolis static uint8_t *
kinst_trampoline_alloc_locked(int how)135f0bc4ed1SChristos Margiolis kinst_trampoline_alloc_locked(int how)
136f0bc4ed1SChristos Margiolis {
137f0bc4ed1SChristos Margiolis struct trampchunk *chunk;
138f0bc4ed1SChristos Margiolis uint8_t *tramp;
139f0bc4ed1SChristos Margiolis int off;
140f0bc4ed1SChristos Margiolis
141f0bc4ed1SChristos Margiolis sx_assert(&kinst_tramp_sx, SX_XLOCKED);
142f0bc4ed1SChristos Margiolis
143f0bc4ed1SChristos Margiolis TAILQ_FOREACH(chunk, &kinst_trampchunks, next) {
144f0bc4ed1SChristos Margiolis /* All trampolines from this chunk are already allocated. */
145f0bc4ed1SChristos Margiolis if ((off = BIT_FFS(KINST_TRAMPS_PER_CHUNK, &chunk->free)) == 0)
146f0bc4ed1SChristos Margiolis continue;
147f0bc4ed1SChristos Margiolis /* BIT_FFS() returns indices starting at 1 instead of 0. */
148f0bc4ed1SChristos Margiolis off--;
149f0bc4ed1SChristos Margiolis break;
150f0bc4ed1SChristos Margiolis }
151f0bc4ed1SChristos Margiolis if (chunk == NULL) {
152f0bc4ed1SChristos Margiolis if ((how & M_NOWAIT) != 0)
153f0bc4ed1SChristos Margiolis return (NULL);
154f0bc4ed1SChristos Margiolis
155f0bc4ed1SChristos Margiolis if ((chunk = kinst_trampchunk_alloc()) == NULL) {
156*5b701ed1SChristos Margiolis #ifdef __amd64__
157*5b701ed1SChristos Margiolis /*
158*5b701ed1SChristos Margiolis * We didn't find any free trampoline in the current
159*5b701ed1SChristos Margiolis * list, allocate a new one. If that fails the
160*5b701ed1SChristos Margiolis * provider will no longer be reliable, so try to warn
161*5b701ed1SChristos Margiolis * the user.
162*5b701ed1SChristos Margiolis */
163f0bc4ed1SChristos Margiolis static bool once = true;
164f0bc4ed1SChristos Margiolis
165f0bc4ed1SChristos Margiolis if (once) {
166f0bc4ed1SChristos Margiolis once = false;
167f0bc4ed1SChristos Margiolis KINST_LOG(
168f0bc4ed1SChristos Margiolis "kinst: failed to allocate trampoline, "
169f0bc4ed1SChristos Margiolis "probes may not fire");
170f0bc4ed1SChristos Margiolis }
171*5b701ed1SChristos Margiolis #endif
172f0bc4ed1SChristos Margiolis return (NULL);
173f0bc4ed1SChristos Margiolis }
174f0bc4ed1SChristos Margiolis off = 0;
175f0bc4ed1SChristos Margiolis }
176f0bc4ed1SChristos Margiolis BIT_CLR(KINST_TRAMPS_PER_CHUNK, off, &chunk->free);
177f0bc4ed1SChristos Margiolis tramp = chunk->addr + off * KINST_TRAMP_SIZE;
178f0bc4ed1SChristos Margiolis return (tramp);
179f0bc4ed1SChristos Margiolis }
180f0bc4ed1SChristos Margiolis
181f0bc4ed1SChristos Margiolis uint8_t *
kinst_trampoline_alloc(int how)182f0bc4ed1SChristos Margiolis kinst_trampoline_alloc(int how)
183f0bc4ed1SChristos Margiolis {
184f0bc4ed1SChristos Margiolis uint8_t *tramp;
185f0bc4ed1SChristos Margiolis
186f0bc4ed1SChristos Margiolis sx_xlock(&kinst_tramp_sx);
187f0bc4ed1SChristos Margiolis tramp = kinst_trampoline_alloc_locked(how);
188f0bc4ed1SChristos Margiolis sx_xunlock(&kinst_tramp_sx);
189f0bc4ed1SChristos Margiolis return (tramp);
190f0bc4ed1SChristos Margiolis }
191f0bc4ed1SChristos Margiolis
192f0bc4ed1SChristos Margiolis static void
kinst_trampoline_dealloc_locked(uint8_t * tramp,bool freechunks)193f0bc4ed1SChristos Margiolis kinst_trampoline_dealloc_locked(uint8_t *tramp, bool freechunks)
194f0bc4ed1SChristos Margiolis {
195f0bc4ed1SChristos Margiolis struct trampchunk *chunk;
196f0bc4ed1SChristos Margiolis int off;
197f0bc4ed1SChristos Margiolis
198e11d11c5SChristos Margiolis sx_assert(&kinst_tramp_sx, SX_XLOCKED);
199e11d11c5SChristos Margiolis
200f0bc4ed1SChristos Margiolis if (tramp == NULL)
201f0bc4ed1SChristos Margiolis return;
202f0bc4ed1SChristos Margiolis
203f0bc4ed1SChristos Margiolis TAILQ_FOREACH(chunk, &kinst_trampchunks, next) {
204f0bc4ed1SChristos Margiolis for (off = 0; off < KINST_TRAMPS_PER_CHUNK; off++) {
205f0bc4ed1SChristos Margiolis if (chunk->addr + off * KINST_TRAMP_SIZE == tramp) {
206ecca3180SChristos Margiolis kinst_trampoline_fill(tramp, KINST_TRAMP_SIZE);
207f0bc4ed1SChristos Margiolis BIT_SET(KINST_TRAMPS_PER_CHUNK, off,
208f0bc4ed1SChristos Margiolis &chunk->free);
209f0bc4ed1SChristos Margiolis if (freechunks &&
210f0bc4ed1SChristos Margiolis BIT_ISFULLSET(KINST_TRAMPS_PER_CHUNK,
211f0bc4ed1SChristos Margiolis &chunk->free))
212f0bc4ed1SChristos Margiolis kinst_trampchunk_free(chunk);
213f0bc4ed1SChristos Margiolis return;
214f0bc4ed1SChristos Margiolis }
215f0bc4ed1SChristos Margiolis }
216f0bc4ed1SChristos Margiolis }
217f0bc4ed1SChristos Margiolis panic("%s: did not find trampoline chunk for %p", __func__, tramp);
218f0bc4ed1SChristos Margiolis }
219f0bc4ed1SChristos Margiolis
220f0bc4ed1SChristos Margiolis void
kinst_trampoline_dealloc(uint8_t * tramp)221f0bc4ed1SChristos Margiolis kinst_trampoline_dealloc(uint8_t *tramp)
222f0bc4ed1SChristos Margiolis {
223f0bc4ed1SChristos Margiolis sx_xlock(&kinst_tramp_sx);
224f0bc4ed1SChristos Margiolis kinst_trampoline_dealloc_locked(tramp, true);
225f0bc4ed1SChristos Margiolis sx_xunlock(&kinst_tramp_sx);
226f0bc4ed1SChristos Margiolis }
227f0bc4ed1SChristos Margiolis
228*5b701ed1SChristos Margiolis #ifdef __amd64__
229f0bc4ed1SChristos Margiolis static void
kinst_thread_ctor(void * arg __unused,struct thread * td)230f0bc4ed1SChristos Margiolis kinst_thread_ctor(void *arg __unused, struct thread *td)
231f0bc4ed1SChristos Margiolis {
2321aa48621SChristos Margiolis td->t_kinst_tramp = kinst_trampoline_alloc(M_WAITOK);
233f0bc4ed1SChristos Margiolis }
234f0bc4ed1SChristos Margiolis
235f0bc4ed1SChristos Margiolis static void
kinst_thread_dtor(void * arg __unused,struct thread * td)236f0bc4ed1SChristos Margiolis kinst_thread_dtor(void *arg __unused, struct thread *td)
237f0bc4ed1SChristos Margiolis {
238f0bc4ed1SChristos Margiolis void *tramp;
239f0bc4ed1SChristos Margiolis
2401aa48621SChristos Margiolis tramp = td->t_kinst_tramp;
2411aa48621SChristos Margiolis td->t_kinst_tramp = NULL;
242f0bc4ed1SChristos Margiolis
243f0bc4ed1SChristos Margiolis /*
244f0bc4ed1SChristos Margiolis * This assumes that the thread_dtor event permits sleeping, which
245f0bc4ed1SChristos Margiolis * appears to be true for the time being.
246f0bc4ed1SChristos Margiolis */
247f0bc4ed1SChristos Margiolis kinst_trampoline_dealloc(tramp);
248f0bc4ed1SChristos Margiolis }
249*5b701ed1SChristos Margiolis #endif
250f0bc4ed1SChristos Margiolis
251f0bc4ed1SChristos Margiolis int
kinst_trampoline_init(void)252f0bc4ed1SChristos Margiolis kinst_trampoline_init(void)
253f0bc4ed1SChristos Margiolis {
254*5b701ed1SChristos Margiolis #ifdef __amd64__
255f0bc4ed1SChristos Margiolis struct proc *p;
256f0bc4ed1SChristos Margiolis struct thread *td;
257f0bc4ed1SChristos Margiolis void *tramp;
258f0bc4ed1SChristos Margiolis int error;
259f0bc4ed1SChristos Margiolis
260f0bc4ed1SChristos Margiolis kinst_thread_ctor_handler = EVENTHANDLER_REGISTER(thread_ctor,
261f0bc4ed1SChristos Margiolis kinst_thread_ctor, NULL, EVENTHANDLER_PRI_ANY);
262f0bc4ed1SChristos Margiolis kinst_thread_dtor_handler = EVENTHANDLER_REGISTER(thread_dtor,
263f0bc4ed1SChristos Margiolis kinst_thread_dtor, NULL, EVENTHANDLER_PRI_ANY);
264f0bc4ed1SChristos Margiolis
265f0bc4ed1SChristos Margiolis error = 0;
266f0bc4ed1SChristos Margiolis tramp = NULL;
267f0bc4ed1SChristos Margiolis
268f0bc4ed1SChristos Margiolis sx_slock(&allproc_lock);
269f0bc4ed1SChristos Margiolis sx_xlock(&kinst_tramp_sx);
270f0bc4ed1SChristos Margiolis FOREACH_PROC_IN_SYSTEM(p) {
271f0bc4ed1SChristos Margiolis retry:
272f0bc4ed1SChristos Margiolis PROC_LOCK(p);
273f0bc4ed1SChristos Margiolis FOREACH_THREAD_IN_PROC(p, td) {
2741aa48621SChristos Margiolis if (td->t_kinst_tramp != NULL)
275f0bc4ed1SChristos Margiolis continue;
276f0bc4ed1SChristos Margiolis if (tramp == NULL) {
277f0bc4ed1SChristos Margiolis /*
278f0bc4ed1SChristos Margiolis * Try to allocate a trampoline without dropping
279f0bc4ed1SChristos Margiolis * the process lock. If all chunks are fully
280f0bc4ed1SChristos Margiolis * utilized, we must release the lock and try
281f0bc4ed1SChristos Margiolis * again.
282f0bc4ed1SChristos Margiolis */
283f0bc4ed1SChristos Margiolis tramp = kinst_trampoline_alloc_locked(M_NOWAIT);
284f0bc4ed1SChristos Margiolis if (tramp == NULL) {
285f0bc4ed1SChristos Margiolis PROC_UNLOCK(p);
286f0bc4ed1SChristos Margiolis tramp = kinst_trampoline_alloc_locked(
287f0bc4ed1SChristos Margiolis M_WAITOK);
288f0bc4ed1SChristos Margiolis if (tramp == NULL) {
289f0bc4ed1SChristos Margiolis /*
290f0bc4ed1SChristos Margiolis * Let the unload handler clean
291f0bc4ed1SChristos Margiolis * up.
292f0bc4ed1SChristos Margiolis */
293f0bc4ed1SChristos Margiolis error = ENOMEM;
294f0bc4ed1SChristos Margiolis goto out;
295f0bc4ed1SChristos Margiolis } else
296f0bc4ed1SChristos Margiolis goto retry;
297f0bc4ed1SChristos Margiolis }
298f0bc4ed1SChristos Margiolis }
2991aa48621SChristos Margiolis td->t_kinst_tramp = tramp;
300f0bc4ed1SChristos Margiolis tramp = NULL;
301f0bc4ed1SChristos Margiolis }
302f0bc4ed1SChristos Margiolis PROC_UNLOCK(p);
303f0bc4ed1SChristos Margiolis }
304f0bc4ed1SChristos Margiolis out:
305f0bc4ed1SChristos Margiolis sx_xunlock(&kinst_tramp_sx);
306f0bc4ed1SChristos Margiolis sx_sunlock(&allproc_lock);
307*5b701ed1SChristos Margiolis #else
308*5b701ed1SChristos Margiolis int error = 0;
309*5b701ed1SChristos Margiolis
310*5b701ed1SChristos Margiolis sx_xlock(&kinst_tramp_sx);
311*5b701ed1SChristos Margiolis TAILQ_INIT(&kinst_trampchunks);
312*5b701ed1SChristos Margiolis sx_xunlock(&kinst_tramp_sx);
313*5b701ed1SChristos Margiolis #endif
314*5b701ed1SChristos Margiolis
315f0bc4ed1SChristos Margiolis return (error);
316f0bc4ed1SChristos Margiolis }
317f0bc4ed1SChristos Margiolis
318f0bc4ed1SChristos Margiolis int
kinst_trampoline_deinit(void)319f0bc4ed1SChristos Margiolis kinst_trampoline_deinit(void)
320f0bc4ed1SChristos Margiolis {
321*5b701ed1SChristos Margiolis #ifdef __amd64__
322f0bc4ed1SChristos Margiolis struct trampchunk *chunk, *tmp;
323f0bc4ed1SChristos Margiolis struct proc *p;
324f0bc4ed1SChristos Margiolis struct thread *td;
325f0bc4ed1SChristos Margiolis
326f0bc4ed1SChristos Margiolis EVENTHANDLER_DEREGISTER(thread_ctor, kinst_thread_ctor_handler);
327f0bc4ed1SChristos Margiolis EVENTHANDLER_DEREGISTER(thread_dtor, kinst_thread_dtor_handler);
328f0bc4ed1SChristos Margiolis
329f0bc4ed1SChristos Margiolis sx_slock(&allproc_lock);
330f0bc4ed1SChristos Margiolis sx_xlock(&kinst_tramp_sx);
331f0bc4ed1SChristos Margiolis FOREACH_PROC_IN_SYSTEM(p) {
332f0bc4ed1SChristos Margiolis PROC_LOCK(p);
333f0bc4ed1SChristos Margiolis FOREACH_THREAD_IN_PROC(p, td) {
3341aa48621SChristos Margiolis kinst_trampoline_dealloc_locked(td->t_kinst_tramp,
3351aa48621SChristos Margiolis false);
3361aa48621SChristos Margiolis td->t_kinst_tramp = NULL;
337f0bc4ed1SChristos Margiolis }
338f0bc4ed1SChristos Margiolis PROC_UNLOCK(p);
339f0bc4ed1SChristos Margiolis }
340f0bc4ed1SChristos Margiolis sx_sunlock(&allproc_lock);
341f0bc4ed1SChristos Margiolis TAILQ_FOREACH_SAFE(chunk, &kinst_trampchunks, next, tmp)
342f0bc4ed1SChristos Margiolis kinst_trampchunk_free(chunk);
343f0bc4ed1SChristos Margiolis sx_xunlock(&kinst_tramp_sx);
344*5b701ed1SChristos Margiolis #else
345*5b701ed1SChristos Margiolis struct trampchunk *chunk, *tmp;
346*5b701ed1SChristos Margiolis
347*5b701ed1SChristos Margiolis sx_xlock(&kinst_tramp_sx);
348*5b701ed1SChristos Margiolis TAILQ_FOREACH_SAFE(chunk, &kinst_trampchunks, next, tmp)
349*5b701ed1SChristos Margiolis kinst_trampchunk_free(chunk);
350*5b701ed1SChristos Margiolis sx_xunlock(&kinst_tramp_sx);
351*5b701ed1SChristos Margiolis #endif
352f0bc4ed1SChristos Margiolis
353f0bc4ed1SChristos Margiolis return (0);
354f0bc4ed1SChristos Margiolis }
355