From ce3155f1dc28e4fc83d594fab5ceaac6d74f0a3a Mon Sep 17 00:00:00 2001 From: Etienne Perot Date: Wed, 15 Nov 2023 16:51:31 -0800 Subject: [PATCH] Specify hottest syscalls for KVM and Systrap platforms on x86. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This causes the seccomp program generated to check for these syscall numbers first, provided that their rules are non-trivial. ``` │ before │ after │ │ sec/op │ sec/op vs base │ SentrySystrap 68.55n ± 2% 66.55n ± 2% -2.92% (p=0.020 n=779) SentrySystrap/futex 76.05n ± 1% 75.60n ± 1% ~ (p=0.264 n=1519+1528) SentrySystrap/nanosleep 92.40n ± 6% 92.95n ± 6% ~ (p=0.754 n=1212+1204) SentrySystrap/sendmmsg 78.76n ± 1% 72.28n ± 1% -8.23% (n=1519+1528) SentrySystrap/fstat 27.76n ± 2% 27.99n ± 2% ~ (p=0.996 n=1495+1502) SentrySystrap/ppoll 28.16n ± 3% 28.18n ± 2% ~ (p=0.948 n=1438+1445) SentrySystrap/fsync 27.56n ± 2% 27.84n ± 3% ~ (p=0.518 n=1441+1467) SentrySystrap/pwrite64 31.65n ± 2% 31.65n ± 2% ~ (p=0.930 n=1429+1448) SentrySystrap/epoll_pwait 91.76n ± 1% 100.00n ± 1% +8.97% (p=0.000 n=1203+1195) SentrySystrap/close 34.66n ± 3% 33.93n ± 6% ~ (p=0.491 n=752+748) SentrySystrap/getpid 35.11n ± 6% 35.31n ± 4% ~ (p=0.743 n=724) SentryKVM 61.62n ± 1% 60.55n ± 2% -1.74% (p=0.001 n=779) SentryKVM/futex 79.33n ± 1% 74.58n ± 1% -5.99% (n=1532+1528) SentryKVM/ioctl 92.19n ± 0% 88.37n ± 1% -4.15% (n=1532+1528) SentryKVM/rt_sigreturn 32.08n ± 3% 31.47n ± 3% ~ (p=0.121 n=1487+1478) SentryKVM/sendmmsg 74.03n ± 1% 72.04n ± 1% -2.68% (p=0.000 n=1532+1528) SentryKVM/fstat 24.84n ± 2% 24.84n ± 2% ~ (p=0.600 n=1509+1506) SentryKVM/ppoll 24.22n ± 3% 25.05n ± 3% ~ (p=0.233 n=1449+1461) SentryKVM/fsync 25.87n ± 2% 25.71n ± 2% ~ (p=0.686 n=1498+1471) SentryKVM/pwrite64 27.96n ± 2% 27.90n ± 2% ~ (p=0.439 n=1299+1314) SentryKVM/nanosleep 88.75n ± 7% 91.87n ± 6% ~ (p=0.342 n=1189) SentryKVM/epoll_pwait 89.79n ± 1% 109.79n ± 1% +22.27% (p=0.000 n=779) NVProxyIoctl 106.3n ± 0% 107.6n ± 0% +1.22% (p=0.000 n=779) ``` The gains are smaller than expected but still directionally correct. The top hot syscalls like `futex` and sendmmsg are slightly faster, whereas the later hot syscalls like `epoll_wait` take longer (but that's OK because they are called much less often). `NVProxyIoctl` suffers a bit because it's only doing `ioctl`s with a Systrap config, so `ioctl` is non-hot, hence the relative slowness. PiperOrigin-RevId: 582848625 --- pkg/sentry/platform/kvm/filters_amd64.go | 9 +++++++++ pkg/sentry/platform/kvm/filters_arm64.go | 5 +++++ pkg/sentry/platform/kvm/kvm.go | 2 -- pkg/sentry/platform/systrap/filters_amd64.go | 9 +++++++++ pkg/sentry/platform/systrap/filters_arm64.go | 5 +++++ pkg/sentry/platform/systrap/systrap.go | 1 - runsc/boot/filter/config_amd64.go | 8 +++++++- 7 files changed, 35 insertions(+), 4 deletions(-) diff --git a/pkg/sentry/platform/kvm/filters_amd64.go b/pkg/sentry/platform/kvm/filters_amd64.go index 2bcdde655..2ff3d6ea3 100644 --- a/pkg/sentry/platform/kvm/filters_amd64.go +++ b/pkg/sentry/platform/kvm/filters_amd64.go @@ -49,3 +49,12 @@ func (k *KVM) archSyscallFilters() seccomp.SyscallRules { }, }) } + +// HottestSyscalls implements Platform.HottestSyscalls. +func (*KVM) HottestSyscalls() []uintptr { + return []uintptr{ + unix.SYS_FUTEX, + unix.SYS_IOCTL, + unix.SYS_RT_SIGRETURN, + } +} diff --git a/pkg/sentry/platform/kvm/filters_arm64.go b/pkg/sentry/platform/kvm/filters_arm64.go index 20884f2dc..2fa875446 100644 --- a/pkg/sentry/platform/kvm/filters_arm64.go +++ b/pkg/sentry/platform/kvm/filters_arm64.go @@ -33,3 +33,8 @@ func (*KVM) archSyscallFilters() seccomp.SyscallRules { }, }) } + +// HottestSyscalls implements Platform.HottestSyscalls. +func (*KVM) HottestSyscalls() []uintptr { + return nil +} diff --git a/pkg/sentry/platform/kvm/kvm.go b/pkg/sentry/platform/kvm/kvm.go index e1d0218e9..d7dec72b1 100644 --- a/pkg/sentry/platform/kvm/kvm.go +++ b/pkg/sentry/platform/kvm/kvm.go @@ -69,8 +69,6 @@ type KVM struct { platform.DoesOwnPageTables - platform.HottestSyscallsNotSpecified - // machine is the backing VM. machine *machine } diff --git a/pkg/sentry/platform/systrap/filters_amd64.go b/pkg/sentry/platform/systrap/filters_amd64.go index 5a8366439..90a72aa9f 100644 --- a/pkg/sentry/platform/systrap/filters_amd64.go +++ b/pkg/sentry/platform/systrap/filters_amd64.go @@ -18,6 +18,7 @@ package systrap import ( + "golang.org/x/sys/unix" "gvisor.dev/gvisor/pkg/seccomp" ) @@ -25,3 +26,11 @@ import ( func (*Systrap) archSyscallFilters() seccomp.SyscallRules { return seccomp.SyscallRules{} } + +// HottestSyscalls implements Platform.HottestSyscalls. +func (*Systrap) HottestSyscalls() []uintptr { + return []uintptr{ + unix.SYS_FUTEX, + unix.SYS_NANOSLEEP, + } +} diff --git a/pkg/sentry/platform/systrap/filters_arm64.go b/pkg/sentry/platform/systrap/filters_arm64.go index a379d0fcb..64c80aa3f 100644 --- a/pkg/sentry/platform/systrap/filters_arm64.go +++ b/pkg/sentry/platform/systrap/filters_arm64.go @@ -40,3 +40,8 @@ func (*Systrap) archSyscallFilters() seccomp.SyscallRules { }, }) } + +// HottestSyscalls implements Platform.HottestSyscalls. +func (*Systrap) HottestSyscalls() []uintptr { + return nil +} diff --git a/pkg/sentry/platform/systrap/systrap.go b/pkg/sentry/platform/systrap/systrap.go index f1217602d..e5869845c 100644 --- a/pkg/sentry/platform/systrap/systrap.go +++ b/pkg/sentry/platform/systrap/systrap.go @@ -301,7 +301,6 @@ type Systrap struct { platform.NoCPUPreemptionDetection platform.UseHostGlobalMemoryBarrier platform.DoesNotOwnPageTables - platform.HottestSyscallsNotSpecified // memoryFile is used to create a stub sysmsg stack // which is shared with the Sentry. diff --git a/runsc/boot/filter/config_amd64.go b/runsc/boot/filter/config_amd64.go index 447542ec1..963da5552 100644 --- a/runsc/boot/filter/config_amd64.go +++ b/runsc/boot/filter/config_amd64.go @@ -46,5 +46,11 @@ func archFstatAtSysNo() uintptr { } func archSpecificHotSyscalls() []uintptr { - return nil // TODO(b/298726675): Populate. + return []uintptr{ + unix.SYS_NANOSLEEP, // Used a bunch + unix.SYS_SENDMMSG, // Used by network workloads + unix.SYS_FSTAT, // Used for file I/O + unix.SYS_PPOLL, // Used in general for I/O + unix.SYS_EPOLL_WAIT, // Same + } }