summaryrefslogtreecommitdiffhomepage
path: root/pkg/cpuid
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/cpuid')
-rw-r--r--pkg/cpuid/BUILD35
-rw-r--r--pkg/cpuid/cpuid_arm64_state_autogen.go51
-rw-r--r--pkg/cpuid/cpuid_arm64_test.go55
-rw-r--r--pkg/cpuid/cpuid_parse_x86_test.go144
-rw-r--r--pkg/cpuid/cpuid_state_autogen.go3
-rw-r--r--pkg/cpuid/cpuid_x86_state_autogen.go111
-rw-r--r--pkg/cpuid/cpuid_x86_test.go243
7 files changed, 165 insertions, 477 deletions
diff --git a/pkg/cpuid/BUILD b/pkg/cpuid/BUILD
deleted file mode 100644
index d6cb1a549..000000000
--- a/pkg/cpuid/BUILD
+++ /dev/null
@@ -1,35 +0,0 @@
-load("//tools:defs.bzl", "go_library", "go_test")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "cpuid",
- srcs = [
- "cpu_amd64.s",
- "cpuid.go",
- "cpuid_arm64.go",
- "cpuid_x86.go",
- ],
- visibility = ["//:sandbox"],
- deps = ["//pkg/log"],
-)
-
-go_test(
- name = "cpuid_test",
- size = "small",
- srcs = [
- "cpuid_arm64_test.go",
- "cpuid_x86_test.go",
- ],
- library = ":cpuid",
-)
-
-go_test(
- name = "cpuid_parse_test",
- size = "small",
- srcs = [
- "cpuid_parse_x86_test.go",
- ],
- library = ":cpuid",
- tags = ["manual"],
-)
diff --git a/pkg/cpuid/cpuid_arm64_state_autogen.go b/pkg/cpuid/cpuid_arm64_state_autogen.go
new file mode 100644
index 000000000..d5911799d
--- /dev/null
+++ b/pkg/cpuid/cpuid_arm64_state_autogen.go
@@ -0,0 +1,51 @@
+// automatically generated by stateify.
+
+// +build arm64
+
+package cpuid
+
+import (
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func (fs *FeatureSet) StateTypeName() string {
+ return "pkg/cpuid.FeatureSet"
+}
+
+func (fs *FeatureSet) StateFields() []string {
+ return []string{
+ "Set",
+ "CPUImplementer",
+ "CPUArchitecture",
+ "CPUVariant",
+ "CPUPartnum",
+ "CPURevision",
+ }
+}
+
+func (fs *FeatureSet) beforeSave() {}
+
+func (fs *FeatureSet) StateSave(stateSinkObject state.Sink) {
+ fs.beforeSave()
+ stateSinkObject.Save(0, &fs.Set)
+ stateSinkObject.Save(1, &fs.CPUImplementer)
+ stateSinkObject.Save(2, &fs.CPUArchitecture)
+ stateSinkObject.Save(3, &fs.CPUVariant)
+ stateSinkObject.Save(4, &fs.CPUPartnum)
+ stateSinkObject.Save(5, &fs.CPURevision)
+}
+
+func (fs *FeatureSet) afterLoad() {}
+
+func (fs *FeatureSet) StateLoad(stateSourceObject state.Source) {
+ stateSourceObject.Load(0, &fs.Set)
+ stateSourceObject.Load(1, &fs.CPUImplementer)
+ stateSourceObject.Load(2, &fs.CPUArchitecture)
+ stateSourceObject.Load(3, &fs.CPUVariant)
+ stateSourceObject.Load(4, &fs.CPUPartnum)
+ stateSourceObject.Load(5, &fs.CPURevision)
+}
+
+func init() {
+ state.Register((*FeatureSet)(nil))
+}
diff --git a/pkg/cpuid/cpuid_arm64_test.go b/pkg/cpuid/cpuid_arm64_test.go
deleted file mode 100644
index a34f67779..000000000
--- a/pkg/cpuid/cpuid_arm64_test.go
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2020 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.
-
-// +build arm64
-
-package cpuid
-
-import (
- "testing"
-)
-
-var justFP = &FeatureSet{
- Set: map[Feature]bool{
- ARM64FeatureFP: true,
- }}
-
-func TestHostFeatureSet(t *testing.T) {
- hostFeatures := HostFeatureSet()
- if len(hostFeatures.Set) == 0 {
- t.Errorf("Got invalid feature set %v from HostFeatureSet()", hostFeatures)
- }
-}
-
-func TestHasFeature(t *testing.T) {
- if !justFP.HasFeature(ARM64FeatureFP) {
- t.Errorf("HasFeature failed, %v should contain %v", justFP, ARM64FeatureFP)
- }
-
- if justFP.HasFeature(ARM64FeatureSM3) {
- t.Errorf("HasFeature failed, %v should not contain %v", justFP, ARM64FeatureSM3)
- }
-}
-
-func TestFeatureFromString(t *testing.T) {
- f, ok := FeatureFromString("asimd")
- if f != ARM64FeatureASIMD || !ok {
- t.Errorf("got %v want asimd", f)
- }
-
- f, ok = FeatureFromString("bad")
- if ok {
- t.Errorf("got %v want nothing", f)
- }
-}
diff --git a/pkg/cpuid/cpuid_parse_x86_test.go b/pkg/cpuid/cpuid_parse_x86_test.go
deleted file mode 100644
index e4ae0d689..000000000
--- a/pkg/cpuid/cpuid_parse_x86_test.go
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright 2018 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.
-
-// +build 386 amd64
-
-package cpuid
-
-import (
- "fmt"
- "io/ioutil"
- "regexp"
- "strconv"
- "strings"
- "syscall"
- "testing"
-)
-
-func kernelVersion() (int, int, error) {
- var u syscall.Utsname
- if err := syscall.Uname(&u); err != nil {
- return 0, 0, err
- }
-
- var sb strings.Builder
- for _, b := range u.Release {
- if b == 0 {
- break
- }
- sb.WriteByte(byte(b))
- }
-
- s := strings.Split(sb.String(), ".")
- if len(s) < 2 {
- return 0, 0, fmt.Errorf("kernel release missing major and minor component: %s", sb.String())
- }
-
- major, err := strconv.Atoi(s[0])
- if err != nil {
- return 0, 0, fmt.Errorf("error parsing major version %q in %q: %w", s[0], sb.String(), err)
- }
-
- minor, err := strconv.Atoi(s[1])
- if err != nil {
- return 0, 0, fmt.Errorf("error parsing minor version %q in %q: %w", s[1], sb.String(), err)
- }
-
- return major, minor, nil
-}
-
-// TestHostFeatureFlags tests that all features detected by HostFeatureSet are
-// on the host.
-//
-// It does *not* verify that all features reported by the host are detected by
-// HostFeatureSet.
-//
-// i.e., test that HostFeatureSet is a subset of the host features.
-func TestHostFeatureFlags(t *testing.T) {
- cpuinfoBytes, _ := ioutil.ReadFile("/proc/cpuinfo")
- cpuinfo := string(cpuinfoBytes)
- t.Logf("Host cpu info:\n%s", cpuinfo)
-
- major, minor, err := kernelVersion()
- if err != nil {
- t.Fatalf("Unable to parse kernel version: %v", err)
- }
-
- re := regexp.MustCompile(`(?m)^flags\s+: (.*)$`)
- m := re.FindStringSubmatch(cpuinfo)
- if len(m) != 2 {
- t.Fatalf("Unable to extract flags from %q", cpuinfo)
- }
-
- cpuinfoFlags := make(map[string]struct{})
- for _, f := range strings.Split(m[1], " ") {
- cpuinfoFlags[f] = struct{}{}
- }
-
- fs := HostFeatureSet()
-
- // All features have a string and appear in host cpuinfo.
- for f := range fs.Set {
- name := f.flagString(false)
- if name == "" {
- t.Errorf("Non-parsable feature: %v", f)
- }
-
- // Special cases not consistently visible. We don't mind if
- // they are exposed in earlier versions.
- switch {
- // Block 0.
- case f == X86FeatureSDBG && (major < 4 || major == 4 && minor < 3):
- // SDBG only exposed in
- // b1c599b8ff80ea79b9f8277a3f9f36a7b0cfedce (4.3).
- continue
- // Block 2.
- case f == X86FeatureRDT && (major < 4 || major == 4 && minor < 10):
- // RDT only exposed in
- // 4ab1586488cb56ed8728e54c4157cc38646874d9 (4.10).
- continue
- // Block 3.
- case f == X86FeatureAVX512VBMI && (major < 4 || major == 4 && minor < 10):
- // AVX512VBMI only exposed in
- // a8d9df5a509a232a959e4ef2e281f7ecd77810d6 (4.10).
- continue
- case f == X86FeatureUMIP && (major < 4 || major == 4 && minor < 15):
- // UMIP only exposed in
- // 3522c2a6a4f341058b8291326a945e2a2d2aaf55 (4.15).
- continue
- case f == X86FeaturePKU && (major < 4 || major == 4 && minor < 9):
- // PKU only exposed in
- // dfb4a70f20c5b3880da56ee4c9484bdb4e8f1e65 (4.9).
- continue
- // Block 4.
- case f == X86FeatureXSAVES && (major < 4 || major == 4 && minor < 8):
- // XSAVES only exposed in
- // b8be15d588060a03569ac85dc4a0247460988f5b (4.8).
- continue
- // Block 5.
- case f == X86FeaturePERFCTR_LLC && (major < 4 || major == 4 && minor < 14):
- // PERFCTR_LLC renamed in
- // 910448bbed066ab1082b510eef1ae61bb792d854 (4.14).
- continue
- }
-
- hidden := f.flagString(true) == ""
- _, ok := cpuinfoFlags[name]
- if hidden && ok {
- t.Errorf("Unexpectedly hidden flag: %v", f)
- } else if !hidden && !ok {
- t.Errorf("Non-native flag: %v", f)
- }
- }
-}
diff --git a/pkg/cpuid/cpuid_state_autogen.go b/pkg/cpuid/cpuid_state_autogen.go
new file mode 100644
index 000000000..86206a6bf
--- /dev/null
+++ b/pkg/cpuid/cpuid_state_autogen.go
@@ -0,0 +1,3 @@
+// automatically generated by stateify.
+
+package cpuid
diff --git a/pkg/cpuid/cpuid_x86_state_autogen.go b/pkg/cpuid/cpuid_x86_state_autogen.go
new file mode 100644
index 000000000..023f8d742
--- /dev/null
+++ b/pkg/cpuid/cpuid_x86_state_autogen.go
@@ -0,0 +1,111 @@
+// automatically generated by stateify.
+
+// +build 386 amd64
+
+package cpuid
+
+import (
+ "gvisor.dev/gvisor/pkg/state"
+)
+
+func (c *Cache) StateTypeName() string {
+ return "pkg/cpuid.Cache"
+}
+
+func (c *Cache) StateFields() []string {
+ return []string{
+ "Level",
+ "Type",
+ "FullyAssociative",
+ "Partitions",
+ "Ways",
+ "Sets",
+ "InvalidateHierarchical",
+ "Inclusive",
+ "DirectMapped",
+ }
+}
+
+func (c *Cache) beforeSave() {}
+
+func (c *Cache) StateSave(stateSinkObject state.Sink) {
+ c.beforeSave()
+ stateSinkObject.Save(0, &c.Level)
+ stateSinkObject.Save(1, &c.Type)
+ stateSinkObject.Save(2, &c.FullyAssociative)
+ stateSinkObject.Save(3, &c.Partitions)
+ stateSinkObject.Save(4, &c.Ways)
+ stateSinkObject.Save(5, &c.Sets)
+ stateSinkObject.Save(6, &c.InvalidateHierarchical)
+ stateSinkObject.Save(7, &c.Inclusive)
+ stateSinkObject.Save(8, &c.DirectMapped)
+}
+
+func (c *Cache) afterLoad() {}
+
+func (c *Cache) StateLoad(stateSourceObject state.Source) {
+ stateSourceObject.Load(0, &c.Level)
+ stateSourceObject.Load(1, &c.Type)
+ stateSourceObject.Load(2, &c.FullyAssociative)
+ stateSourceObject.Load(3, &c.Partitions)
+ stateSourceObject.Load(4, &c.Ways)
+ stateSourceObject.Load(5, &c.Sets)
+ stateSourceObject.Load(6, &c.InvalidateHierarchical)
+ stateSourceObject.Load(7, &c.Inclusive)
+ stateSourceObject.Load(8, &c.DirectMapped)
+}
+
+func (fs *FeatureSet) StateTypeName() string {
+ return "pkg/cpuid.FeatureSet"
+}
+
+func (fs *FeatureSet) StateFields() []string {
+ return []string{
+ "Set",
+ "VendorID",
+ "ExtendedFamily",
+ "ExtendedModel",
+ "ProcessorType",
+ "Family",
+ "Model",
+ "SteppingID",
+ "Caches",
+ "CacheLine",
+ }
+}
+
+func (fs *FeatureSet) beforeSave() {}
+
+func (fs *FeatureSet) StateSave(stateSinkObject state.Sink) {
+ fs.beforeSave()
+ stateSinkObject.Save(0, &fs.Set)
+ stateSinkObject.Save(1, &fs.VendorID)
+ stateSinkObject.Save(2, &fs.ExtendedFamily)
+ stateSinkObject.Save(3, &fs.ExtendedModel)
+ stateSinkObject.Save(4, &fs.ProcessorType)
+ stateSinkObject.Save(5, &fs.Family)
+ stateSinkObject.Save(6, &fs.Model)
+ stateSinkObject.Save(7, &fs.SteppingID)
+ stateSinkObject.Save(8, &fs.Caches)
+ stateSinkObject.Save(9, &fs.CacheLine)
+}
+
+func (fs *FeatureSet) afterLoad() {}
+
+func (fs *FeatureSet) StateLoad(stateSourceObject state.Source) {
+ stateSourceObject.Load(0, &fs.Set)
+ stateSourceObject.Load(1, &fs.VendorID)
+ stateSourceObject.Load(2, &fs.ExtendedFamily)
+ stateSourceObject.Load(3, &fs.ExtendedModel)
+ stateSourceObject.Load(4, &fs.ProcessorType)
+ stateSourceObject.Load(5, &fs.Family)
+ stateSourceObject.Load(6, &fs.Model)
+ stateSourceObject.Load(7, &fs.SteppingID)
+ stateSourceObject.Load(8, &fs.Caches)
+ stateSourceObject.Load(9, &fs.CacheLine)
+}
+
+func init() {
+ state.Register((*Cache)(nil))
+ state.Register((*FeatureSet)(nil))
+}
diff --git a/pkg/cpuid/cpuid_x86_test.go b/pkg/cpuid/cpuid_x86_test.go
deleted file mode 100644
index bacf345c8..000000000
--- a/pkg/cpuid/cpuid_x86_test.go
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2018 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.
-
-// +build 386 amd64
-
-package cpuid
-
-import (
- "testing"
-)
-
-// These are the default values of various FeatureSet fields.
-const (
- defaultVendorID = "GenuineIntel"
-
- // These processor signature defaults are derived from the values
- // listed in Intel Application Note 485 for i7/Xeon processors.
- defaultExtFamily uint8 = 0
- defaultExtModel uint8 = 1
- defaultType uint8 = 0
- defaultFamily uint8 = 0x06
- defaultModel uint8 = 0x0a
- defaultSteppingID uint8 = 0
-)
-
-// newEmptyFeatureSet creates a new FeatureSet with a sensible default model and no features.
-func newEmptyFeatureSet() *FeatureSet {
- return &FeatureSet{
- Set: make(map[Feature]bool),
- VendorID: defaultVendorID,
- ExtendedFamily: defaultExtFamily,
- ExtendedModel: defaultExtModel,
- ProcessorType: defaultType,
- Family: defaultFamily,
- Model: defaultModel,
- SteppingID: defaultSteppingID,
- }
-}
-
-var justFPU = &FeatureSet{
- Set: map[Feature]bool{
- X86FeatureFPU: true,
- }}
-
-var justFPUandPAE = &FeatureSet{
- Set: map[Feature]bool{
- X86FeatureFPU: true,
- X86FeaturePAE: true,
- }}
-
-func TestSubtract(t *testing.T) {
- if diff := justFPU.Subtract(justFPUandPAE); diff != nil {
- t.Errorf("Got %v is not subset of %v, want diff (%v) to be nil", justFPU, justFPUandPAE, diff)
- }
-
- if justFPUandPAE.Subtract(justFPU) == nil {
- t.Errorf("Got %v is a subset of %v, want diff to be nil", justFPU, justFPUandPAE)
- }
-}
-
-// TODO(b/73346484): Run this test on a very old platform, and make sure more
-// bits are enabled than just FPU and PAE. This test currently may not detect
-// if HostFeatureSet gives back junk bits.
-func TestHostFeatureSet(t *testing.T) {
- hostFeatures := HostFeatureSet()
- if justFPUandPAE.Subtract(hostFeatures) != nil {
- t.Errorf("Got invalid feature set %v from HostFeatureSet()", hostFeatures)
- }
-}
-
-func TestHasFeature(t *testing.T) {
- if !justFPU.HasFeature(X86FeatureFPU) {
- t.Errorf("HasFeature failed, %v should contain %v", justFPU, X86FeatureFPU)
- }
-
- if justFPU.HasFeature(X86FeatureAVX) {
- t.Errorf("HasFeature failed, %v should not contain %v", justFPU, X86FeatureAVX)
- }
-}
-
-// Note: these tests are aware of and abuse internal details of FeatureSets.
-// Users of FeatureSets should not depend on this.
-func TestAdd(t *testing.T) {
- // Test a basic insertion into the FeatureSet.
- testFeatures := newEmptyFeatureSet()
- testFeatures.Add(X86FeatureCLFSH)
- if len(testFeatures.Set) != 1 {
- t.Errorf("Got length %v want 1", len(testFeatures.Set))
- }
-
- if !testFeatures.HasFeature(X86FeatureCLFSH) {
- t.Errorf("Add failed, got %v want set with %v", testFeatures, X86FeatureCLFSH)
- }
-
- // Test that duplicates are ignored.
- testFeatures.Add(X86FeatureCLFSH)
- if len(testFeatures.Set) != 1 {
- t.Errorf("Got length %v, want 1", len(testFeatures.Set))
- }
-}
-
-func TestRemove(t *testing.T) {
- // Try removing the last feature.
- testFeatures := newEmptyFeatureSet()
- testFeatures.Add(X86FeatureFPU)
- testFeatures.Add(X86FeaturePAE)
- testFeatures.Remove(X86FeaturePAE)
- if !testFeatures.HasFeature(X86FeatureFPU) || len(testFeatures.Set) != 1 || testFeatures.HasFeature(X86FeaturePAE) {
- t.Errorf("Remove failed, got %v want %v", testFeatures, justFPU)
- }
-
- // Try removing a feature not in the set.
- testFeatures.Remove(X86FeatureRDRAND)
- if !testFeatures.HasFeature(X86FeatureFPU) || len(testFeatures.Set) != 1 {
- t.Errorf("Remove failed, got %v want %v", testFeatures, justFPU)
- }
-}
-
-func TestFeatureFromString(t *testing.T) {
- f, ok := FeatureFromString("avx")
- if f != X86FeatureAVX || !ok {
- t.Errorf("got %v want avx", f)
- }
-
- f, ok = FeatureFromString("bad")
- if ok {
- t.Errorf("got %v want nothing", f)
- }
-}
-
-// This tests function 0 (eax=0), which returns the vendor ID and highest cpuid
-// function reported to be available.
-func TestEmulateIDVendorAndLength(t *testing.T) {
- testFeatures := newEmptyFeatureSet()
-
- ax, bx, cx, dx := testFeatures.EmulateID(0, 0)
- wantEax := uint32(0xd) // Highest supported cpuid function.
-
- // These magical constants are the characters of "GenuineIntel".
- // See Intel AN485 for a reference on why they are laid out like this.
- wantEbx := uint32(0x756e6547)
- wantEcx := uint32(0x6c65746e)
- wantEdx := uint32(0x49656e69)
- if wantEax != ax {
- t.Errorf("highest function failed, got %x want %x", ax, wantEax)
- }
-
- if wantEbx != bx || wantEcx != cx || wantEdx != dx {
- t.Errorf("vendor string emulation failed, bx:cx:dx, got %x:%x:%x want %x:%x:%x", bx, cx, dx, wantEbx, wantEcx, wantEdx)
- }
-}
-
-func TestEmulateIDBasicFeatures(t *testing.T) {
- // Make a minimal test feature set.
- testFeatures := newEmptyFeatureSet()
- testFeatures.Add(X86FeatureCLFSH)
- testFeatures.Add(X86FeatureAVX)
- testFeatures.CacheLine = 64
-
- ax, bx, cx, dx := testFeatures.EmulateID(1, 0)
- ECXAVXBit := uint32(1 << uint(X86FeatureAVX))
- EDXCLFlushBit := uint32(1 << uint(X86FeatureCLFSH-32)) // We adjust by 32 since it's in block 1.
-
- if EDXCLFlushBit&dx == 0 || dx&^EDXCLFlushBit != 0 {
- t.Errorf("EmulateID failed, got feature bits %x want %x", dx, testFeatures.blockMask(1))
- }
-
- if ECXAVXBit&cx == 0 || cx&^ECXAVXBit != 0 {
- t.Errorf("EmulateID failed, got feature bits %x want %x", cx, testFeatures.blockMask(0))
- }
-
- // Default signature bits, based on values for i7/Xeon.
- // See Intel AN485 for information on stepping/model bits.
- defaultSignature := uint32(0x000106a0)
- if defaultSignature != ax {
- t.Errorf("EmulateID stepping emulation failed, got %x want %x", ax, defaultSignature)
- }
-
- clflushSizeInfo := uint32(8 << 8)
- if clflushSizeInfo != bx {
- t.Errorf("EmulateID bx emulation failed, got %x want %x", bx, clflushSizeInfo)
- }
-}
-
-func TestEmulateIDExtendedFeatures(t *testing.T) {
- // Make a minimal test feature set, one bit in each extended feature word.
- testFeatures := newEmptyFeatureSet()
- testFeatures.Add(X86FeatureSMEP)
- testFeatures.Add(X86FeatureAVX512VBMI)
-
- ax, bx, cx, dx := testFeatures.EmulateID(7, 0)
- EBXSMEPBit := uint32(1 << uint(X86FeatureSMEP-2*32)) // Adjust by 2*32 since SMEP is a block 2 feature.
- ECXAVXBit := uint32(1 << uint(X86FeatureAVX512VBMI-3*32)) // We adjust by 3*32 since it's a block 3 feature.
-
- // Test that the desired bit is set and no other bits are set.
- if EBXSMEPBit&bx == 0 || bx&^EBXSMEPBit != 0 {
- t.Errorf("extended feature emulation failed, got feature bits %x want %x", bx, testFeatures.blockMask(2))
- }
-
- if ECXAVXBit&cx == 0 || cx&^ECXAVXBit != 0 {
- t.Errorf("extended feature emulation failed, got feature bits %x want %x", cx, testFeatures.blockMask(3))
- }
-
- if ax != 0 || dx != 0 {
- t.Errorf("extended feature emulation failed, ax:dx, got %x:%x want 0:0", ax, dx)
- }
-
- // Check that no subleaves other than 0 do anything.
- ax, bx, cx, dx = testFeatures.EmulateID(7, 1)
- if ax != 0 || bx != 0 || cx != 0 || dx != 0 {
- t.Errorf("extended feature emulation failed, got %x:%x:%x:%x want 0:0", ax, bx, cx, dx)
- }
-
-}
-
-// Checks that the expected extended features are available via cpuid functions
-// 0x80000000 and up.
-func TestEmulateIDExtended(t *testing.T) {
- testFeatures := newEmptyFeatureSet()
- testFeatures.Add(X86FeatureSYSCALL)
- EDXSYSCALLBit := uint32(1 << uint(X86FeatureSYSCALL-6*32)) // Adjust by 6*32 since SYSCALL is a block 6 feature.
-
- ax, bx, cx, dx := testFeatures.EmulateID(0x80000000, 0)
- if ax != 0x80000001 || bx != 0 || cx != 0 || dx != 0 {
- t.Errorf("EmulateID extended emulation failed, ax:bx:cx:dx, got %x:%x:%x:%x want 0x80000001:0:0:0", ax, bx, cx, dx)
- }
-
- _, _, _, dx = testFeatures.EmulateID(0x80000001, 0)
- if EDXSYSCALLBit&dx == 0 || dx&^EDXSYSCALLBit != 0 {
- t.Errorf("extended feature emulation failed, got feature bits %x want %x", dx, testFeatures.blockMask(6))
- }
-}