Thread information[
[No responses]
From: | Cong Wang <cwang-AT-multikernel.io> | | To: | linux-kernel-AT-vger.kernel.org | | Subject: | [ANNOUNCE] mklinux v7.0-mk2 | | Date: | Tue, 25 Aug 2026 13:17:08 -0700 | | Message-ID: | ao34RJ7aZ2BLd67S@pop-os.localdomain | | Cc: | multikernel-AT-lists.linux.dev |
Hi all,
I am happy to announce mklinux v7.0-mk2, the first public release of
the multikernel Linux tree.
git: https://github.com/multikernel/linux
tag: v7.0-mk2
mklinux lets one machine run several independent Linux kernels at the
same time on bare metal, without a hypervisor. A host kernel owns a pool
of CPUs, memory and PCI devices, carves that pool into instances, and
boots a spawn kernel into each instance through kexec_file_load(). Every
spawn kernel runs natively on its own CPUs, its own physical memory and
its own devices. Nothing is emulated and nothing is trapped; the only
thing shared is what you choose to share.
Instances are declared with a device tree written to
/sys/fs/multikernel/, and device tree overlays move memory, CPUs and
devices between the pool and running instances without a reboot. An
instance can be shut down, its resources reclaimed, and respawned with
a different kernel.
Compared with virtual machines, there is no VM exit path, no second
level of page tables and no device model. Compared with containers,
instances do not share a kernel, so a lock, a panic or an exploit in one
kernel cannot reach another.
The tree is based on v7.0. With CONFIG_MULTIKERNEL=n it builds and
behaves exactly like v7.0.
Two things matter here: a spawn kernel should pay nothing over bare
metal, and splitting a machine into several kernels should let workloads
scale past the walls a single kernel hits. Both were measured on a
dual-socket Xeon Gold 5418Y (Sapphire Rapids, 2x24 cores, SMT off).
No virtualization tax
---------------------
lmbench on a 2-core, 1 GB spawn kernel against a 2-vCPU, 1 GB KVM guest
with EPT, unrestricted guest and APICv, vCPUs pinned to idle cores:
Benchmark Multikernel KVM guest Ratio
Null syscall 0.070 us 0.099 us 1.42x
read() 0.099 us 0.124 us 1.26x
write() 0.082 us 0.114 us 1.39x
Signal handler install 0.123 us 0.159 us 1.29x
Signal handler catch 0.770 us 0.881 us 1.14x
Context switch (2 procs) 1.37 us 3.42 us 2.50x
Pipe latency 3.24 us 7.06 us 2.18x
AF_UNIX stream latency 4.81 us 7.48 us 1.55x
fork + exit 115 us 123 us 1.07x
Memory latency and bandwidth are at parity (lat_mem_rd 32.1 ns vs
31.2 ns at 128 MB; ~20.9 GB/s sequential read on both), which is
expected: EPT with huge pages has made nested translation essentially
free. What a guest cannot avoid is the exit on every kernel entry and
on every wakeup of an idle vCPU, which is where the 2.5x context switch
and 2.2x pipe latency gap comes from. KVM can close most of that gap
with idle=poll or mwait passthrough, at the cost of a vCPU that looks
100% busy to the host and 12 to 19 W of extra power. A spawn kernel
gets the low latency and still puts its cores into C1 to C6 when idle.
https://multikernel.io/2026/08/16/multikernel-vs-kvm-lmbe...
Scaling past the single-kernel wall
-----------------------------------
will-it-scale, processes mode, 24 tasks on one socket: one kernel
driving 24 cores versus two spawn kernels driving 12 cores each.
Test 1 kernel 2 kernels Ratio
unlink1 300K/s 780K/s 2.60x
rename1 792K/s 1.69M/s 2.14x
stat2 9.42M/s 19.8M/s 2.10x
open3 3.42M/s 7.41M/s 2.17x
open1 9.6M/s 19.3M/s 2.02x
pread4 ~5.2M/s ~10.1M/s 1.94x
mmap1 9.9M/s 12.2M/s 1.23x
tcp_conn1 1.81M/s 2.10M/s 1.16x
getppid1 268.2M/s 267.1M/s 1.00x (control)
futex4 135.5M/s 134.9M/s 1.00x (control)
poll2 26.7M/s 26.5M/s 0.99x (control)
The controls show there is no multikernel overhead on the syscall path
at all. The wins come from locks that a single kernel cannot shard:
the directory i_rwsem, s_vfs_rename_mutex, a shared dentry refcount, a
folio refcount in the page cache. On one kernel, unlink1 peaks at 2
tasks and then goes backwards; at 48 tasks it delivers 40% of what one
task manages alone. Splitting the same tasks across network namespaces
on one kernel gives exactly nothing (tcp_conn2 matches tcp_conn1 at
every task count), because the wall sits below the namespace boundary.
Aligning kernels with sockets makes the effect larger: with 12 cores
per socket, one kernel spanning both sockets versus one kernel per
socket gives unlink1 231K/s vs 939K/s (4.07x) and open1 9.06M/s vs
20.1M/s (2.22x).
For fairness, the caveats are in the post as well: open1's win is
mostly AppArmor label sharing and drops to 1.00x with the LSM off
(unlink1 keeps 2.24x); mmap1 needed 8 GB instances to keep
vm_committed_as batching out of the way; and workloads that share one
address space across all cores (threads mode) cannot be split and gain
nothing.
https://multikernel.io/2026/08/17/multikernel-will-it-scale/
x86_64 is the supported architecture for this release and the reason
it is the first one announced. Instances have been spawned, shut down,
reconfigured and respawned in long soak loops on the machines above,
with KASLR and 5-level paging, including spawn kernels that panic; a
crash in one kernel does not reach the others, and every CPU an
instance was given is confirmed parked back on the host before it is
reused. The benchmark numbers above were collected on this exact
release with unmodified workloads inside the spawn kernels.
The architecture interface is split out so other ports can follow, but
no other architecture is supported yet.
Check https://multikernel.io/getting-started.html
Feedback, bug reports and testing on other hardware are very welcome.
The tree will keep tracking upstream releases, and pieces that stand on
their own will be posted for upstream review separately.
Thanks,
Cong Wang