diff --git a/pkg/cpuid/BUILD b/pkg/cpuid/BUILD index 8defa4712..b2a0754c1 100644 --- a/pkg/cpuid/BUILD +++ b/pkg/cpuid/BUILD @@ -13,6 +13,8 @@ go_library( "cpuid_arm64.go", "features_amd64.go", "features_arm64.go", + "hwcap_amd64.go", + "hwcap_arm64.go", "native_amd64.go", "native_amd64.s", "native_arm64.go", diff --git a/pkg/cpuid/cpuid_amd64.go b/pkg/cpuid/cpuid_amd64.go index 829e089e9..0f7e1d0b2 100644 --- a/pkg/cpuid/cpuid_amd64.go +++ b/pkg/cpuid/cpuid_amd64.go @@ -480,3 +480,17 @@ func (fs FeatureSet) archCheckHostCompatible(hfs FeatureSet) error { return nil } + +// AllowedHWCap1 returns the HWCAP1 bits that the guest is allowed to depend +// on. +func (fs FeatureSet) AllowedHWCap1() uint64 { + // HWCAPS are not supported on amd64. + return 0 +} + +// AllowedHWCap2 returns the HWCAP2 bits that the guest is allowed to depend +// on. +func (fs FeatureSet) AllowedHWCap2() uint64 { + // HWCAPS are not supported on amd64. + return 0 +} diff --git a/pkg/cpuid/cpuid_arm64.go b/pkg/cpuid/cpuid_arm64.go index 964f33acb..3072a37a4 100644 --- a/pkg/cpuid/cpuid_arm64.go +++ b/pkg/cpuid/cpuid_arm64.go @@ -108,3 +108,47 @@ func (fs FeatureSet) WriteCPUInfoTo(cpu, numCPU uint, w io.Writer) { func (FeatureSet) archCheckHostCompatible(FeatureSet) error { return nil } + +// AllowedHWCap1 returns the HWCAP1 bits that the guest is allowed to depend +// on. +func (fs FeatureSet) AllowedHWCap1() uint64 { + // Pick a set of safe HWCAPS to expose. These do not rely on cpu state + // that gvisor does not restore after a context switch. + allowed := HWCAP_AES | + HWCAP_ASIMD | + HWCAP_ASIMDDP | + HWCAP_ASIMDFHM | + HWCAP_ASIMDHP | + HWCAP_ASIMDRDM | + HWCAP_ATOMICS | + HWCAP_CRC32 | + HWCAP_DCPOP | + HWCAP_DIT | + HWCAP_EVTSTRM | + HWCAP_FCMA | + HWCAP_FLAGM | + HWCAP_FP | + HWCAP_FPHP | + HWCAP_ILRCPC | + HWCAP_JSCVT | + HWCAP_LRCPC | + HWCAP_PMULL | + HWCAP_SHA1 | + HWCAP_SHA2 | + HWCAP_SHA3 | + HWCAP_SHA512 | + HWCAP_SM3 | + HWCAP_SM4 | + HWCAP_USCAT + return fs.hwCap.hwCap1 & uint64(allowed) +} + +// AllowedHWCap2 returns the HWCAP2 bits that the guest is allowed to depend +// on. +func (fs FeatureSet) AllowedHWCap2() uint64 { + // We don't expose anything here yet, but this could be expanded to + // include features do not rely on cpu state that is not restored after + // a context switch. + allowed := 0 + return fs.hwCap.hwCap2 & uint64(allowed) +} diff --git a/pkg/cpuid/hwcap_amd64.go b/pkg/cpuid/hwcap_amd64.go new file mode 100644 index 000000000..f75a0a6f0 --- /dev/null +++ b/pkg/cpuid/hwcap_amd64.go @@ -0,0 +1,24 @@ +// Copyright 2024 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build amd64 +// +build amd64 + +package cpuid + +// See arch/x86/include/uapi/asm/hwcap2.h +const ( + HWCAP2_RING3MWAIT = 1 << 0 + HWCAP2_FSGSBASE = 1 << 1 +) diff --git a/pkg/cpuid/hwcap_arm64.go b/pkg/cpuid/hwcap_arm64.go new file mode 100644 index 000000000..8b85bf9b6 --- /dev/null +++ b/pkg/cpuid/hwcap_arm64.go @@ -0,0 +1,79 @@ +// Copyright 2024 The gVisor Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build arm64 +// +build arm64 + +package cpuid + +// See arch/arm64/include/uapi/asm/hwcap.h +const ( + // HWCAP flags for AT_HWCAP. + HWCAP_FP = 1 << 0 + HWCAP_ASIMD = 1 << 1 + HWCAP_EVTSTRM = 1 << 2 + HWCAP_AES = 1 << 3 + HWCAP_PMULL = 1 << 4 + HWCAP_SHA1 = 1 << 5 + HWCAP_SHA2 = 1 << 6 + HWCAP_CRC32 = 1 << 7 + HWCAP_ATOMICS = 1 << 8 + HWCAP_FPHP = 1 << 9 + HWCAP_ASIMDHP = 1 << 10 + HWCAP_CPUID = 1 << 11 + HWCAP_ASIMDRDM = 1 << 12 + HWCAP_JSCVT = 1 << 13 + HWCAP_FCMA = 1 << 14 + HWCAP_LRCPC = 1 << 15 + HWCAP_DCPOP = 1 << 16 + HWCAP_SHA3 = 1 << 17 + HWCAP_SM3 = 1 << 18 + HWCAP_SM4 = 1 << 19 + HWCAP_ASIMDDP = 1 << 20 + HWCAP_SHA512 = 1 << 21 + HWCAP_SVE = 1 << 22 + HWCAP_ASIMDFHM = 1 << 23 + HWCAP_DIT = 1 << 24 + HWCAP_USCAT = 1 << 25 + HWCAP_ILRCPC = 1 << 26 + HWCAP_FLAGM = 1 << 27 + HWCAP_SSBS = 1 << 28 + HWCAP_SB = 1 << 29 + HWCAP_PACA = 1 << 30 + HWCAP_PACG = 1 << 31 + + // HWCAP2 flags for AT_HWCAP2. + HWCAP2_DCPODP = 1 << 0 + HWCAP2_SVE2 = 1 << 1 + HWCAP2_SVEAES = 1 << 2 + HWCAP2_SVEPMULL = 1 << 3 + HWCAP2_SVEBITPERM = 1 << 4 + HWCAP2_SVESHA3 = 1 << 5 + HWCAP2_SVESM4 = 1 << 6 + HWCAP2_FLAGM2 = 1 << 7 + HWCAP2_FRINT = 1 << 8 + HWCAP2_SVEI8MM = 1 << 9 + HWCAP2_SVEF32MM = 1 << 10 + HWCAP2_SVEF64MM = 1 << 11 + HWCAP2_SVEBF16 = 1 << 12 + HWCAP2_I8MM = 1 << 13 + HWCAP2_BF16 = 1 << 14 + HWCAP2_DGH = 1 << 15 + HWCAP2_RNG = 1 << 16 + HWCAP2_BTI = 1 << 17 + HWCAP2_MTE = 1 << 18 + HWCAP2_ECV = 1 << 19 + HWCAP2_AFP = 1 << 20 + HWCAP2_RPRES = 1 << 21 +) diff --git a/pkg/cpuid/static_amd64.go b/pkg/cpuid/static_amd64.go index f21f2e4fb..8f8564a55 100644 --- a/pkg/cpuid/static_amd64.go +++ b/pkg/cpuid/static_amd64.go @@ -26,7 +26,9 @@ type Static map[In]Out // Fixed converts the FeatureSet to a fixed set. func (fs FeatureSet) Fixed() FeatureSet { - return fs.ToStatic().ToFeatureSet() + sfs := fs.ToStatic().ToFeatureSet() + sfs.hwCap = fs.hwCap + return sfs } // ToStatic converts a FeatureSet to a Static function. diff --git a/pkg/sentry/loader/loader.go b/pkg/sentry/loader/loader.go index 3af837060..efd8990c8 100644 --- a/pkg/sentry/loader/loader.go +++ b/pkg/sentry/loader/loader.go @@ -329,8 +329,9 @@ func Load(ctx context.Context, args LoadArgs, extraAuxv []arch.AuxEntry, vdso *V arch.AuxEntry{linux.AT_RANDOM, random}, arch.AuxEntry{linux.AT_PAGESZ, hostarch.PageSize}, arch.AuxEntry{linux.AT_SYSINFO_EHDR, vdsoAddr}, + arch.AuxEntry{linux.AT_HWCAP, hostarch.Addr(args.Features.AllowedHWCap1())}, + arch.AuxEntry{linux.AT_HWCAP2, hostarch.Addr(args.Features.AllowedHWCap2())}, }...) - auxv = append(auxv, extraAuxv...) sl, err := stack.Load(newArgv, args.Envv, auxv) if err != nil {