You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 85722de
Browse filesBrowse the repository at this point in the historyBrowse files
<pclass="lede">Compile the out-of-tree Mach kernel module <em>into</em> the <code>NEXTBSD</code> kernel (<code>options COMPAT_MACH</code>) instead of loading it as a <code>.ko</code>. This is the answer to “how do we load <code>mach.ko</code> once <code>loader.conf</code> is gone?” — we don’t load it; it’s part of the kernel image, present from the first instruction, long before launchd (PID 1). It is the <strong>foundational step of #180</strong> (eliminate <code>loader.conf</code>).</p>
48
-
<pclass="meta">2026-06-03. Grounded in a 2-agent code scope: the <code>nextbsd/src/mach_kmod</code> build (sources, MIG, Makefile, syscall wiring) + the FreeBSD 15.x <code>sys/conf/{options,files}</code> + SYSINIT build-in mechanism. Tracked on <ahref="https://github.com/nextbsd-redux/nextbsd/issues/180">nextbsd#180</a>.</p>
48
+
<pclass="meta">2026-06-03. Grounded in a 5-agent code scope: the <code>nextbsd/src/mach_kmod</code> build (sources, MIG, Makefile, syscall wiring) + the FreeBSD 15.x <code>sys/conf/{options,files}</code> + SYSINIT mechanism, then a deep pass on exact build wiring, header/namespace collisions, and link/init correctness (§11). Tracked on <ahref="https://github.com/nextbsd-redux/nextbsd/issues/181">nextbsd#181</a> (child of <ahref="https://github.com/nextbsd-redux/nextbsd/issues/180">#180</a>).</p>
49
49
50
50
<divclass="callout callout-good">
51
51
<p><spanclass="pill pill-good">Verdict</span><strong>Feasible and clean — mostly build-system wiring, not a C rewrite.</strong> Two things that usually make “module → built-in” painful don’t apply here: the MIG server stubs are <em>pre-generated and committed</em> (no codegen in the kernel build), and the syscalls already register through a <code>SYSINIT</code> via <code>kern_syscall_register()</code> (no <code>syscalls.master</code> regen). The mach source is <em>ours</em>, not <code>freebsd-src</code>, so it lives in <code>nextbsd-kernel</code> and is dropped into the builder’s throwaway clone — the fork is never touched.</p>
@@ -64,6 +64,7 @@ <h2>Contents</h2>
64
64
<li><ahref="#risk">Risk & the safety net</a></li>
65
65
<li><ahref="#steps">Steps & sequencing</a></li>
nextbsd/src/mach_kmod/opt_*.h → NOT COPIED (config(8) generates them — see gotchas)</code></pre>
115
+
<divclass="callout callout-warn">
116
+
<p><spanclass="pill pill-warn">Gotcha 1</span><strong>Do not lay the shipped <code>opt_*.h</code> into the tree.</strong> The module ships <code>opt_compat_mach.h</code>/<code>opt_capsicum.h</code>/<code>opt_ntp.h</code>/<code>opt_audit.h</code> (GENERIC-matching) for the out-of-tree build. In-kernel, <code>config(8)</code> generates these from the real <code>NEXTBSD</code> config; a shipped copy on the include path would <em>shadow</em> the generated one and <code>options COMPAT_MACH</code> would be silently ignored. Exclude them.</p>
117
+
</div>
118
+
<divclass="callout callout-warn">
119
+
<p><spanclass="pill pill-warn">Gotcha 2</span><strong><code>compat_shim.h</code> redefines <code>EVFILT_MACHPORT</code>.</strong> It does <code>#define EVFILT_MACHPORT (-16)</code>, but patch <strong>0003 now defines it in <code>sys/sys/event.h</code></strong> — so built against the patched kernel this is a hard redefinition error. Guard it: <code>#ifndef EVFILT_MACHPORT … #endif</code> (the same pattern as the <code>NO_SYSCALL</code> guard added in #178). The <code>kn_ext</code> alias and the <code>S_IFPORT</code>/<code>DTYPE_MACH_IPC</code> constants were checked and are collision-free.</p>
120
+
</div>
113
121
<p><strong>Delivery mechanism</strong>: two parts.</p>
114
122
<ul>
115
123
<li><strong>The source tree</strong> ships as real files in <code>nextbsd-kernel</code> (e.g. under <code>src/sys-overlay/</code>); the kernel build <code>cp -R</code>s it into the freebsd-src clone’s <code>sys/</code> before <code>buildkernel</code>. Bulk source as files, not a giant diff.</li>
@@ -123,7 +131,9 @@ <h2 id="cdelta">5. C deltas (smaller than expected)</h2>
123
131
<li><strong>Module declaration.</strong><code>DECLARE_MODULE(mach, …, SI_SUB_KLD, …)</code> still fires its <code>MOD_LOAD</code> event for a built-in (the module framework runs events for compiled-in modules too). We can keep it, or convert <code>mach_mod_init()</code> to a plain <code>SYSINIT</code> — either works; converting is tidier and drops the now-meaningless <code>MOD_UNLOAD→EBUSY</code> path.</li>
124
132
<li><strong>Syscall wiring.</strong> Unchanged — <code>mach_syscall_wire</code> is already a <code>SYSINIT</code> doing dynamic <code>kern_syscall_register()</code>. No <code>syscalls.master</code> regen, no fixed slot numbers.</li>
125
133
<li><strong>EVFILT_MACHPORT.</strong> Unchanged — <code>kqueue_add_filteropts(EVFILT_MACHPORT, &machport_filtops)</code> now succeeds (slot reserved by 0003). The stale “stock FreeBSD rejects -16” comment in <code>mach_module.c</code> can be corrected as a drive-by.</li>
126
-
<li><strong>Symbol hygiene.</strong> Built-in code shares the kernel namespace. The mach symbols are already prefixed (<code>mach_*</code>, <code>ipc_*</code>); a link-time check for collisions is the one new verification.</li>
134
+
<li><strong>Symbol hygiene — audited, clean.</strong> Every externally-visible global is <code>ipc_*</code>/<code>mach_*</code>/<code>machport_*</code>-prefixed or a clearly-named MIG server entry (<code>mach_host_server</code>, …); the scan found <strong>no collision</strong> with base-kernel globals. (Two unprefixed names — <code>mach_debug_enable</code>, <code>trailer_template</code> — are still collision-free in the kernel namespace.)</li>
135
+
<li><strong>Init ordering — one explicit <code>SI_ORDER</code> to add.</strong><code>ipc_bootstrap_sysinit</code> (zone setup) and the mach module init both fire at <code>SI_SUB_KLD, SI_ORDER_ANY</code>; today their order falls out of link order (IPC first — correct). Make it explicit (IPC <code>SI_ORDER_FIRST</code>, mach init <code>SI_ORDER_MIDDLE</code>) so it can’t regress. The syscall-wire SYSINIT (<code>SI_SUB_INTRINSIC</code>) already runs after both and before PID 1.</li>
136
+
<li><strong>EVFILT_MACHPORT.</strong> The <code>kqueue_add_filteropts</code> call now succeeds (slot reserved by 0003); guard the shim’s duplicate <code>#define</code> (gotcha 2) and correct the stale comment.</li>
127
137
<li><strong><code>opt_*.h</code>.</strong> The shipped <code>opt_compat_mach.h</code>/<code>opt_capsicum.h</code>/… are replaced by config(8)-generated ones from the real <code>NEXTBSD</code> config — which is <em>more</em> correct (guaranteed KBI match), removing the hand-maintained copies.</li>
128
138
</ul>
129
139
@@ -164,6 +174,76 @@ <h2 id="open">10. Open decisions</h2>
164
174
<li><strong>Init style.</strong> Keep <code>DECLARE_MODULE</code> (works built-in) vs. convert to <code>SYSINIT</code> (tidier). <em>Leaning: convert.</em></li>
<p>One <code>optional compat_mach</code> line per source file. The MIG <code>*_server.c</code> compile with the default rule; the hand-written files carry the Makefile’s flags via <code>compile-with</code>. Factor the shared flags into a macro to keep it readable:</p>
191
+
<pre><code># sys/conf/Makefile (or top of files.compat_mach via make var)
<pclass="cite">Flags decoded from <code>src/mach_kmod/Makefile</code>: <code>-DMACH_INTERNAL=</code> must be the bare form (its include-guard usage), and <code>-include compat_shim.h</code> stays force-included. <code>${NORMAL_C}</code> already supplies <code>-nostdinc -I$S -D_KERNEL</code>.</p>
218
+
219
+
<h3>11.3 Header placement (zero collisions, confirmed via cgit)</h3>
<tr><td><code>include/sys/mach/</code> (122 .h)</td><td><code>sys/sys/mach/</code></td><td><code><sys/mach/…></code> resolves unchanged ($S on the path)</td></tr>
<tr><td><code>opt_*.h</code> (4)</td><td><strong>excluded</strong></td><td>config(8) generates them (gotcha 1)</td></tr>
227
+
</tbody>
228
+
</table>
229
+
230
+
<h3>11.4 Source delivery + CI step</h3>
231
+
<p>Store the tree in <code>nextbsd-kernel</code> under <code>src-overlay/sys/</code> (real files, not a diff). The build copies it into the throwaway freebsd-src clone right after the patch loop, before <code>buildkernel</code>:</p>
232
+
<pre><code># .github/workflows/build.yml — new step after "Apply patches"
<p>The <code>sys/conf/{options,files}</code> + <code>config/NEXTBSD</code> edits ride as <code>patches/0004-compat-mach-builtin.patch</code> (tiny). This keeps <code>nextbsd-kernel</code> a patches-plus-overlay repo, the fork untouched, and the wiring reviewable.</p>
241
+
242
+
<h3>11.5 Verdict</h3>
243
+
<divclass="callout callout-good">
244
+
<p><spanclass="pill pill-good">Approved</span> Link-time and init correctness pass: no symbol collisions, syscalls wired before PID 1, <code>kern_syscall_register</code> works at boot, <code>machport_filtops</code> complete. The two compile-breakers (shipped <code>opt_*.h</code> shadowing; <code>compat_shim.h</code><code>EVFILT_MACHPORT</code> redefinition vs. patch 0003) are known and fixed in the steps above. Ready to implement as a <code>nextbsd-kernel</code> PR, boot-test-gated.</p>
245
+
</div>
246
+
167
247
<pclass="footnote">mach-into-kernel plan, 2026-06-03. Foundation for <ahref="freebsd-ko-to-kext-conversion-plan.html#loaderconf">eliminating loader.conf (#180)</a>. Sourced from the <code>nextbsd/src/mach_kmod</code> build (Makefile, <code>make-mach-kmod.sh</code>, <code>mach_module.c</code>, <code>mach_syscall_wire.c</code>) and FreeBSD 15.x <code>sys/conf/{options,files}</code> + SYSINIT(9) / config(5).</p>
0 commit comments