1/* $OpenBSD: xcall.h,v 1.2 2025/11/10 12:34:52 dlg Exp $ */
2
3/*
4 * Copyright (c) 2025 David Gwynne <dlg@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*
20 * CPU crosscall API
21 *
22 * Work to execute on a CPU is wrapped in a struct xcall, which is
23 * like a task or timeout. Each CPU (in an MP kernel) has an array
24 * of pointers to xcall structs. The local CPU uses CAS ops to try
25 * and swap their xcall onto one of the slots on the remote CPU,
26 * and will spin until space becomes available. Once the xcall has
27 * been added, an IPI is sent to the remote CPU to kick of processing
28 * of the array. The xcall IPI handler defers processing of the
29 * xcall array to a low IPL level using a softintr handler.
30 *
31 * To implement this API on an architecture requires the following:
32 *
33 * 1. A device has to depend on the xcall attribute to have the
34 * xcall code included in the kernel build. e.g., on amd64 the cpu
35 * device depends on the xcall attribute, as defined in
36 * src/sys/arch/amd64/conf/files.amd64:
37 *
38 * device cpu: xcall
39 *
40 * The rest of the changes are only necessary for MULTIPROCESSOR builds:
41 *
42 * 2. struct cpu_info has to have a `struct xcall_cpu ci_xcall` member.
43 *
44 * 3. cpu_xcall_establish has to be called against each cpu_info struct.
45 *
46 * 4. cpu_xcall_ipi has to be provided by machine/intr.h.
47 *
48 * 5. call cpu_xcall_dispatch at IPL_SOFTCLOCK on the target CPU.
49 */
50
51#ifndef _SYS_XCALL_H
52#define _SYS_XCALL_H
53
54struct xcall {
55 void (*xc_func)(void *);
56 void *xc_arg;
57};
58
59/* MD code adds this to struct cpu_info as ci_xcall */
60struct xcall_cpu {
61 struct xcall *xci_xcalls[4];
62 void *xci_softintr;
63};
64
65#ifdef _KERNEL
66#define XCALL_INITIALIZER(_f, _a) { \
67 .xc_func = _f, \
68 .xc_arg = _a, \
69}
70
71void cpu_xcall_set(struct xcall *, void (*)(void *), void *);
72void cpu_xcall(struct cpu_info *, struct xcall *);
73
74void cpu_xcall_sync(struct cpu_info *, void (*)(void *), void *,
75 const char *);
76
77/* MD cpu setup calls this */
78void cpu_xcall_establish(struct cpu_info *);
79/* MD ipi handler calls this */
80void cpu_xcall_dispatch(struct cpu_info *);
81
82#endif /* _KERNEL */
83
84#endif /* _SYS_XCALL_H */