Index: sys/conf/files =================================================================== RCS file: /cvs/src/sys/conf/files,v diff -u -p -r1.745 files --- sys/conf/files 23 Apr 2025 21:40:22 -0000 1.745 +++ sys/conf/files 5 Jul 2025 10:43:42 -0000 @@ -23,6 +23,7 @@ define onewirebus {} define video {} define intrmap {} define fdt {[early = 0]} +define xcall # filesystem firmware loading attribute define firmload @@ -750,6 +751,7 @@ file kern/kern_uuid.c file kern/kern_watchdog.c !small_kernel file kern/kern_task.c file kern/kern_srp.c +file kern/kern_xcall.c xcall file kern/kern_xxx.c file kern/sched_bsd.c file kern/subr_autoconf.c Index: sys/sys/xcall.h =================================================================== RCS file: sys/sys/xcall.h diff -N sys/sys/xcall.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/sys/xcall.h 5 Jul 2025 10:43:42 -0000 @@ -0,0 +1,52 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2025 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_XCALL_H +#define _SYS_XCALL_H + +struct xcall { + void (*xc_func)(void *); + void *xc_arg; +}; + +/* MD code adds this to struct cpu_info as ci_xcall */ +struct xcall_cpu { + struct xcall *xci_xcalls[4]; + void *xci_softintr; +}; + +#ifdef _KERNEL +#define XCALL_INITIALIZER(_f, _a) { \ + .xc_func = _f, \ + .xc_arg = _a, \ +} + +void cpu_xcall_set(struct xcall *, void (*)(void *), void *); +void cpu_xcall(struct cpu_info *, struct xcall *); + +void cpu_xcall_sync(struct cpu_info *, void (*)(void *), void *, + const char *); + +/* MD cpu setup calls this */ +void cpu_xcall_establish(struct cpu_info *); +/* MD ipi handler calls this */ +void cpu_xcall_dispatch(struct cpu_info *); + +#endif /* _KERNEL */ + +#endif /* _SYS_XCALL_H */ Index: sys/kern/kern_xcall.c =================================================================== RCS file: sys/kern/kern_xcall.c diff -N sys/kern/kern_xcall.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/kern/kern_xcall.c 5 Jul 2025 10:43:42 -0000 @@ -0,0 +1,168 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2025 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include + +#include + +#define IPL_XCALL IPL_SOFTCLOCK + +void +cpu_xcall_set(struct xcall *xc, void (*func)(void *), void *arg) +{ + xc->xc_func = func; + xc->xc_arg = arg; +} + +static inline void +cpu_xcall_self(struct xcall *xc) +{ + int s; + + s = splraise(IPL_XCALL); + xc->xc_func(xc->xc_arg); + splx(s); +} + +#ifdef MULTIPROCESSOR + +void +cpu_xcall(struct cpu_info *ci, struct xcall *xc) +{ + struct xcall_cpu *xci = &ci->ci_xcall; + size_t i; + + if (ci == curcpu()) { + /* execute the task immediately on the local cpu */ + cpu_xcall_self(xc); + return; + } + + for (;;) { + for (i = 0; i < nitems(xci->xci_xcalls); i++) { + if (atomic_cas_ptr(&xci->xci_xcalls[i], + NULL, xc) != NULL) + continue; + + cpu_xcall_ipi(ci); + return; + } + + CPU_BUSY_CYCLE(); + } +} + +struct xcall_sync { + struct xcall xcs_xc; + struct cond xcs_c; +}; + +static void +cpu_xcall_done(void *arg) +{ + struct xcall_sync *xcs = arg; + struct xcall *xc = &xcs->xcs_xc; + + xc->xc_func(xc->xc_arg); + + cond_signal(&xcs->xcs_c); +} + +void +cpu_xcall_sync(struct cpu_info *ci, void (*func)(void *), void *arg, + const char *wmesg) +{ + struct xcall_sync xcs = { + .xcs_xc = XCALL_INITIALIZER(func, arg), + .xcs_c = COND_INITIALIZER(), + }; + struct xcall xc = XCALL_INITIALIZER(cpu_xcall_done, &xcs); + + cpu_xcall(ci, &xc); + + cond_wait(&xcs.xcs_c, wmesg); +} + +/* + * This is the glue between the MD IPI code and the calling of xcalls + */ +static void +cpu_xcall_handler(void *arg) +{ + struct xcall_cpu *xci = arg; + struct xcall *xc; + size_t i; + + for (i = 0; i < nitems(xci->xci_xcalls); i++) { + xc = xci->xci_xcalls[i]; + if (xc != NULL) { + xci->xci_xcalls[i] = NULL; + (*xc->xc_func)(xc->xc_arg); + } + } +} + +void +cpu_xcall_establish(struct cpu_info *ci) +{ + struct xcall_cpu *xci = &ci->ci_xcall; + size_t i; + + for (i = 0; i < nitems(xci->xci_xcalls); i++) + xci->xci_xcalls[i] = NULL; + + xci->xci_softintr = softintr_establish(IPL_XCALL | IPL_MPSAFE, + cpu_xcall_handler, xci); +} + +void +cpu_xcall_dispatch(struct cpu_info *ci) +{ + struct xcall_cpu *xci = &ci->ci_xcall; + + softintr_schedule(xci->xci_softintr); +} + +#else /* MULTIPROCESSOR */ + +/* + * uniprocessor implementation + */ + +void +cpu_xcall(struct cpu_info *ci, struct xcall *xc) +{ + cpu_xcall_self(xc); +} + +void +cpu_xcall_sync(struct cpu_info *ci, void (*func)(void *), void *arg, + const char *wmesg) +{ + int s; + + s = splraise(IPL_XCALL); + func(arg); + splx(s); +} +#endif /* MULTIPROCESSOR */ Index: share/man/man9/Makefile =================================================================== RCS file: /cvs/src/share/man/man9/Makefile,v diff -u -p -r1.310 Makefile --- share/man/man9/Makefile 24 Feb 2024 16:21:32 -0000 1.310 +++ share/man/man9/Makefile 5 Jul 2025 10:43:42 -0000 @@ -11,7 +11,7 @@ MAN= aml_evalnode.9 atomic_add_int.9 ato bufq_init.9 bus_dma.9 bus_space.9 \ clockintr.9 clockintr_bind.9 \ copy.9 cond_init.9 config_attach.9 config_defer.9 counters_alloc.9 \ - cpumem_get.9 crypto.9 \ + cpumem_get.9 cpu_xcall.9 crypto.9 \ delay.9 disk.9 disklabel.9 dma_alloc.9 dohooks.9 \ dostartuphooks.9 \ evcount.9 extent.9 fb_setup.9 file.9 fork1.9 ffs.9 \ Index: share/man/man9/cpu_xcall.9 =================================================================== RCS file: share/man/man9/cpu_xcall.9 diff -N share/man/man9/cpu_xcall.9 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ share/man/man9/cpu_xcall.9 5 Jul 2025 10:43:42 -0000 @@ -0,0 +1,114 @@ +.\" $OpenBSD$ +.\" +.\" Copyright (c) 2025 David Gwynne +.\" All rights reserved. +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: January 29 2025 $ +.Dt CPU_XCALL 9 +.Os +.Sh NAME +.Nm cpu_xcall_set , +.Nm cpu_xcall , +.Nm cpu_xcall_sync , +.Nm XCALL_INITIALIZER +.Nd CPU crosscall API +.Sh SYNOPSIS +.In sys/xcall.h +.Ft void +.Fn cpu_xcall_set "struct xcall *xc" "void (*func)(void *)" "void *arg" +.Ft void +.Fn cpu_xcall "struct cpu_info *ci" "struct xcall *xc" +.Ft void +.Fo cpu_xcall_sync +.Fa "struct cpu_info *ci" +.Fa "void (*func)(void *)" +.Fa "void *arg" +.Fa "const char *wmesg" +.Fc +.Fn XCALL_INITIALIZER "void (*func)(void *)" "void *arg" +.Sh DESCRIPTION +The +CPU crosscall API +supports the dispatch of function execution to a specific CPU +in the kernel. +The functions are run in a software interrupt context at +.Dv IPL_SOFTCLOCK . +.Pp +The +.Fn cpu_xcall_set +function prepares the xcall structure +.Fa xc +to call the function +.Fa func +with argument +.Fa arg +via future calls to +.Fn cpu_xcall . +.Pp +.Fn cpu_xcall +dispatches a call to a function with an argument represented by +.Fa xc +on the CPU specified by the +.Fa ci +cpu_info structure. +The same +.Fa xc +may be scheduled for execution on multiple CPUs concurrently. +.Pp +.Fn cpu_xcall_sync +dispatches a call to the function +.Fa func +with argument +.Fa arg +on the CPU specified by the +.Fa ci +cpu_info structure, and waits for that function to complete. +.Fn cpu_xcall_sync +may sleep waiting for the call to +.Fa func +to complete with +.Fa wmesg +as the wait message. +.Pp +.Fn XCALL_INITIALIZER +initialises a +.Vt xcall +structure to call the function +.Fa func +with argument +.Fa arg +via future calls to +.Fn cpu_xcall . +.Sh CONTEXT +.Fn cpu_xcall_set , +and +.Fn cpu_xcall +can be called from process context, or from interrupt context. +.Pp +.Fn cpu_xcall_sync +can be called from process context. +.Sh SEE ALSO +.Xr spl 9 , +.Xr tsleep 9 +.Sh HISTORY +The +.Nm +functions first appeared in +.Ox 7.8 . +.Sh AUTHORS +The +.Nm +functions were written by +.An David Gwynne Aq Mt dlg@openbsd.org .