SlimVM is a lightweight VMX-based platform for gVisor that accelerates
sentry system calls by eliminating unnecessary user/kernel context
switches.
In a traditional gVisor + KVM setup, every guest syscall triggers a
full VM exit to userspace, then re-enters the kernel via a regular
syscall:
gr0 -> hr0 (vm_exit) -> hr3 (ioctl return) -> hr0 (re-invoke syscall)
SlimVM eliminates this overhead. When the guest executes a VMCALL, the
VM exits into VMX root mode where SlimVM directly invokes the host
kernel's syscall handler, then immediately resumes the guest:
gr0 -> hr0 (vmcall + direct function call)
SlimVM requires a companion kernel module that provides the /dev/slimvm
device interface. See https://github.com/antgroup/slimvm for the
kernel module and full documentation.
A sentry->host getpid microbenchmark (Xeon 6982P-C, host kernel 5.10.134)
shows the effect:
│ ns/op │ vs base │
base 82.5 1.0x
slimvm 420.9 5.1x
kvm 3566.1 43.2x
slimvm is ~8.5x faster than the kvm platform on this path. See the issue
for details.
Updates: https://github.com/google/gvisor/issues/13330
Co-developed-by: Chenggang <[email protected]>
Co-developed-by: Robin Luk <[email protected]>
Co-developed-by: Tiwei Bie <[email protected]>
Co-developed-by: Jianfeng Tan <[email protected]>
Co-developed-by: liushi.ls <[email protected]>
Co-developed-by: Yong He <[email protected]>
Co-developed-by: Aaron Lu <[email protected]>
Co-developed-by: chris.zn <[email protected]>
Co-developed-by: Lai Jiangshan <[email protected]>
Co-developed-by: Lingfu <[email protected]>
Co-developed-by: Min Le <[email protected]>
Co-developed-by: Quan Xu <[email protected]>
Co-developed-by: Zhang Haoyu <[email protected]>
Co-developed-by: Dawei Shen <[email protected]>
Signed-off-by: Tianyu Zhou <[email protected]>
After Linux commit dc8aa31a7a, fx_sw->xstate_size is no longer used to
determine the location for FP_XSTATE_MAGIC2. This exposed the fact that
even in cases where AMX was disabled, AMX TILECFG was not considered to be
part of the AMX extended state.
Fixes#12741.
PiperOrigin-RevId: 904687888
Currently, runsc compares the host feature set between the machine used
for checkpointing and the machine used for restoring. If the former
feature set is not a subset of the latter, the restore will fail, as
user apps might mistakenly use unsupported instructions.
Thanks to cpuid faulting support, it is possible to intercept the cpuid
instruction from user apps and generate results referring to the host
feature set recorded during sandbox boot.
This patch adds support to expose only specified CPU features by
removing features from the list when setting the feature set of kernel.
This makes it possible to checkpoint and restore on machines with
different CPU features. The list of enabled features is passed via
annotation.
It should be noted that currently this feature is not supported on
ARM64, as there is no ARM64 equivalent to cpuid.Static.Remove().
Updates #11486
Signed-off-by: Tianyu Zhou <[email protected]>
Reviewed-by: Jamie Liu <[email protected]>
On machines with many CPUs, reading all of /proc/cpuinfo spends a surprising
amount of time generating information for each CPU; reduce this time by reading
incrementally until we find the CPU frequency. On such machines, this saves
3-4ms on sentry startup.
PiperOrigin-RevId: 688609950
Linux prints this field when cache information is available. This field
is conditional (see arch/x86/kernel/cpu/proc.c:x86_cache_size()). It a
different meaning and implementation on each vendor. For example, as of
Linux 6.1.0 it returns LLC size on Intel and L2 size on AMD CPUs.
Even though usefullness of this field in its current implementation
debatable, some relatively popular software such as PyPy (as of 7.3.11)
relies on it and prints a warning if it is not available.
Linux prints these fields when the kernel is built with support for multiple
processors/cores (CONFIG_SMP), in
arch/x86/kernel/cpu/proc.c:show_cpuinfo_core().
Fixes#10205
PiperOrigin-RevId: 632621375
This allows for external information to be passed to restore code.
Similar to a9af2d309b ("Plumb restore context to afterLoad()").
Updates #1956.
PiperOrigin-RevId: 614125262
SETREGSET/GETREGSET expect AMX portions of fpstate to always be used.
For this reason we need to allocate enough memory for this to happen,
even if we never populate the AMX portions within initX86FPState.
PiperOrigin-RevId: 599702181
For now we are going to completely disable using AMX, so we will
always subtract extended state size reserved from AMX from the rest
of the extended state size, and hardcode the AMX XCR0 bits to be
always off.
Fixes#9750.
PiperOrigin-RevId: 599302059
This block holds information about whether AMX is enabled or not,
which is important for CPUs that support it due to the fact that
the fpstate buffer becomes dynamically sized, and the cpuid value
reported for extended state size assumes that AMX is enabled for
any given process.
PiperOrigin-RevId: 598941137
It is an idea of running codespell as part of our presubmit checks.
Before enabling it for new changes, let's fix what it has found.
Signed-off-by: Andrei Vagin <[email protected]>
It is impossible to enable any features from user-space, so
it is no reason to return the maximum size with all features enabled.
The kvm and systrap platforms uses ExtendedStateSize to generate fpu states
that are restored via rt_sigreturn, but the kernel rejects frames with
incorrect sizes.
PiperOrigin-RevId: 537333319
This moves the initialization of `cpuid.hostFeatureSet` out of package-level
`init` and instead moves it to an explicit `cpuid.Initialize()` function.
On AMD64, this saves about 512KiB of heap memory that would otherwise always
be live.
PiperOrigin-RevId: 514896323
For all trivial and zero frame-sized functions, we now require an explicit
NOFRAME annotation as the heuristic has changed. See go.dev/cl/466316.
Most of these functions do not *require* NOFRAME, but this change encodes
the existing behavior in order to avoid accidental bugs or regressions.
PiperOrigin-RevId: 513946210
HostFeatureSet() returns a fixed set that is initialized at startup.
Here results fro the signal_benchmark on the kvm platform:
Before:
BM_FaultSignalFixup/real_time 8353 ns 8383 ns 94234
After:
BM_FaultSignalFixup/real_time 6127 ns 6087 ns 111708
PiperOrigin-RevId: 462012597
The origin version converts KVM cpuid entries into cpuid.Static
to be able to modify it. But such conversion has side-effects
that we need to avoid and so it looks reasonable to modify KVM
cpuid entries directly.
PiperOrigin-RevId: 424221630
Right now, each vdso call triggers vmexit. VDSO and VVAR pages are
mapped with VM_IO and get_user_pages fails for such vma-s. KVM was not
able to handle this case up to the v4.8 kernel. This problem was fixed by
add6a0cd1c5ba ("KVM: MMU: try to fix up page faults before giving up").
For some unknown reasons, it still doesn't work in case of nested
virtualization.
Before:
BenchmarkKernelVDSO-6 252519 4598 ns/op
After:
BenchmarkKernelVDSO-6 34431957 34.91 ns/op
PiperOrigin-RevId: 405715941