mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
cpuid: Initialize hostFeatureSet only when it's needed.
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
This commit is contained in:
committed by
gVisor bot
parent
38750cdedc
commit
0620c3b638
@@ -21,6 +21,7 @@ go_library(
|
||||
visibility = ["//:sandbox"],
|
||||
deps = [
|
||||
"//pkg/log",
|
||||
"//pkg/sync",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
)
|
||||
|
||||
// contextID is the package for context.Context.Value keys.
|
||||
@@ -253,3 +254,11 @@ func initHWCap() {
|
||||
hostFeatureSet.hwCap = c
|
||||
}
|
||||
}
|
||||
|
||||
var initOnce sync.Once
|
||||
|
||||
// Initialize initializes the global data structures used by this package.
|
||||
// Must be called prior to using anything else in this package.
|
||||
func Initialize() {
|
||||
initOnce.Do(archInitialize)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package cpuid
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -67,3 +68,8 @@ func TestHostFeatureFlags(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
Initialize()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -90,3 +90,8 @@ func TestReadingSelfProcAuxv(t *testing.T) {
|
||||
t.Errorf("got %v, expected nil", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
Initialize()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -215,7 +215,8 @@ func readMaxCPUFreq() {
|
||||
|
||||
}
|
||||
|
||||
func init() {
|
||||
// archInitialize initializes hostFeatureSet.
|
||||
func archInitialize() {
|
||||
hostFeatureSet = FeatureSet{
|
||||
Function: &Native{},
|
||||
}.Fixed()
|
||||
|
||||
@@ -150,7 +150,8 @@ func initCPUInfo() {
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// archInitialize initializes hostFeatureSet.
|
||||
func archInitialize() {
|
||||
initCPUInfo()
|
||||
initHWCap()
|
||||
}
|
||||
|
||||
@@ -93,9 +93,9 @@ var (
|
||||
|
||||
// Init sets function pointers based on architectural features.
|
||||
//
|
||||
// This must be called prior to using ring0. By default, it will be called by
|
||||
// the init() function. However, it may be called at another time with a
|
||||
// different FeatureSet.
|
||||
// This must be called prior to using ring0. It may be called with the
|
||||
// auto-detected feature set using InitDefault. It may also be called at
|
||||
// another time with a different FeatureSet.
|
||||
func Init(fs cpuid.FeatureSet) {
|
||||
// Initialize all sizes.
|
||||
VirtualAddressBits = uintptr(fs.VirtualAddressBits())
|
||||
@@ -123,7 +123,8 @@ func Init(fs cpuid.FeatureSet) {
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// See Init, above.
|
||||
// InitDefault initializes ring0 with the auto-detected host feature set.
|
||||
func InitDefault() {
|
||||
cpuid.Initialize()
|
||||
Init(cpuid.HostFeatureSet())
|
||||
}
|
||||
|
||||
@@ -76,3 +76,7 @@ func FPSIMDEnableTrap()
|
||||
//
|
||||
// This must be called prior to using ring0.
|
||||
func Init() {}
|
||||
|
||||
// InitDefault calls Init with default parameters.
|
||||
// On ARM, this is not much.
|
||||
func InitDefault() {}
|
||||
|
||||
@@ -50,6 +50,7 @@ var (
|
||||
|
||||
// Boot initializes a new bare bones kernel for test.
|
||||
func Boot() (*kernel.Kernel, error) {
|
||||
cpuid.Initialize()
|
||||
seccheck.Initialize()
|
||||
|
||||
platformCtr, err := platform.Lookup(*platformFlag)
|
||||
|
||||
@@ -219,6 +219,7 @@ func (c *cpuidEntries) Set(in cpuid.In, out cpuid.Out) {
|
||||
|
||||
// updateGlobalOnce does global initialization. It has to be called only once.
|
||||
func updateGlobalOnce(fd int) error {
|
||||
bitsForScaling = getBitsForScaling()
|
||||
if err := updateSystemValues(int(fd)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -16,12 +16,14 @@ package kvm
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/cpuid"
|
||||
"gvisor.dev/gvisor/pkg/hostarch"
|
||||
"gvisor.dev/gvisor/pkg/ring0"
|
||||
"gvisor.dev/gvisor/pkg/ring0/pagetables"
|
||||
@@ -32,7 +34,8 @@ import (
|
||||
ktime "gvisor.dev/gvisor/pkg/sentry/time"
|
||||
)
|
||||
|
||||
var dummyFPState = fpu.NewState()
|
||||
// dummyFPState is initialized in TestMain.
|
||||
var dummyFPState fpu.State
|
||||
|
||||
type testHarness interface {
|
||||
Errorf(format string, args ...any)
|
||||
@@ -554,3 +557,9 @@ func BenchmarkWorldSwitchToUserRoundtrip(b *testing.B) {
|
||||
b.Logf("ErrContextInterrupt occurred %d times (in %d iterations).", a, a+i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
cpuid.Initialize()
|
||||
dummyFPState = fpu.NewState()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -158,12 +158,17 @@ func (c *vCPU) initArchState() error {
|
||||
}
|
||||
|
||||
// bitsForScaling returns the bits available for storing the fraction component
|
||||
// of the TSC scaling ratio.
|
||||
// It is set using getBitsForScaling when the KVM platform is initialized.
|
||||
var bitsForScaling int64
|
||||
|
||||
// getBitsForScaling returns the bits available for storing the fraction component
|
||||
// of the TSC scaling ratio. This allows us to replicate the (bad) math done by
|
||||
// the kernel below in scaledTSC, and ensure we can compute an exact zero
|
||||
// offset in setSystemTime.
|
||||
//
|
||||
// These constants correspond to kvm_tsc_scaling_ratio_frac_bits.
|
||||
var bitsForScaling = func() int64 {
|
||||
func getBitsForScaling() int64 {
|
||||
fs := cpuid.HostFeatureSet()
|
||||
if fs.Intel() {
|
||||
return 48 // See vmx.c (kvm sources).
|
||||
@@ -172,7 +177,7 @@ var bitsForScaling = func() int64 {
|
||||
} else {
|
||||
return 63 // Unknown: theoretical maximum.
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// scaledTSC returns the host TSC scaled by the given frequency.
|
||||
//
|
||||
|
||||
@@ -137,8 +137,10 @@ go_test(
|
||||
library = ":boot",
|
||||
deps = [
|
||||
"//pkg/control/server",
|
||||
"//pkg/cpuid",
|
||||
"//pkg/fspath",
|
||||
"//pkg/log",
|
||||
"//pkg/sentry/seccheck",
|
||||
"//pkg/sentry/vfs",
|
||||
"//pkg/sync",
|
||||
"//pkg/unet",
|
||||
|
||||
@@ -26,8 +26,10 @@ import (
|
||||
"github.com/syndtr/gocapability/capability"
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/control/server"
|
||||
"gvisor.dev/gvisor/pkg/cpuid"
|
||||
"gvisor.dev/gvisor/pkg/fspath"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck"
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
"gvisor.dev/gvisor/pkg/unet"
|
||||
@@ -496,3 +498,9 @@ func TestCreateMountNamespace(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
cpuid.Initialize()
|
||||
seccheck.Initialize()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -54,9 +54,11 @@ go_library(
|
||||
"//pkg/atomicbitops",
|
||||
"//pkg/coretag",
|
||||
"//pkg/coverage",
|
||||
"//pkg/cpuid",
|
||||
"//pkg/log",
|
||||
"//pkg/metric",
|
||||
"//pkg/prometheus",
|
||||
"//pkg/ring0",
|
||||
"//pkg/sentry/control",
|
||||
"//pkg/sentry/fsutil/chdir",
|
||||
"//pkg/sentry/kernel",
|
||||
|
||||
@@ -28,8 +28,10 @@ import (
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/coretag"
|
||||
"gvisor.dev/gvisor/pkg/cpuid"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/metric"
|
||||
"gvisor.dev/gvisor/pkg/ring0"
|
||||
"gvisor.dev/gvisor/pkg/sentry/fsutil/chdir"
|
||||
"gvisor.dev/gvisor/pkg/sentry/platform"
|
||||
"gvisor.dev/gvisor/runsc/boot"
|
||||
@@ -208,6 +210,12 @@ func (b *Boot) Execute(_ context.Context, f *flag.FlagSet, args ...any) subcomma
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize CPUID information.
|
||||
cpuid.Initialize()
|
||||
|
||||
// Initialize ring0 library.
|
||||
ring0.InitDefault()
|
||||
|
||||
if len(b.productName) == 0 {
|
||||
// Do this before chroot takes effect, otherwise we can't read /sys.
|
||||
if product, err := ioutil.ReadFile("/sys/devices/virtual/dmi/id/product_name"); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user