gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/platform/kvm/kvm_amd64_test.go (about) 1 // Copyright 2020 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //go:build amd64 16 // +build amd64 17 18 package kvm 19 20 import ( 21 "testing" 22 23 "gvisor.dev/gvisor/pkg/abi/linux" 24 "gvisor.dev/gvisor/pkg/cpuid" 25 "gvisor.dev/gvisor/pkg/ring0" 26 "gvisor.dev/gvisor/pkg/ring0/pagetables" 27 "gvisor.dev/gvisor/pkg/sentry/arch" 28 "gvisor.dev/gvisor/pkg/sentry/platform" 29 "gvisor.dev/gvisor/pkg/sentry/platform/kvm/testutil" 30 ) 31 32 func TestSegments(t *testing.T) { 33 applicationTest(t, true, testutil.AddrOfTwiddleSegments(), func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool { 34 testutil.SetTestSegments(regs) 35 for { 36 var si linux.SignalInfo 37 if _, err := c.SwitchToUser(ring0.SwitchOpts{ 38 Registers: regs, 39 FloatingPointState: &dummyFPState, 40 PageTables: pt, 41 FullRestore: true, 42 }, &si); err == platform.ErrContextInterrupt { 43 continue // Retry. 44 } else if err != nil { 45 t.Errorf("application segment check with full restore got unexpected error: %v", err) 46 } 47 if err := testutil.CheckTestSegments(regs); err != nil { 48 t.Errorf("application segment check with full restore failed: %v", err) 49 } 50 break // Done. 51 } 52 return false 53 }) 54 } 55 56 // stmxcsr reads the MXCSR control and status register. 57 func stmxcsr(addr *uint32) 58 59 func TestMXCSR(t *testing.T) { 60 applicationTest(t, true, testutil.AddrOfSyscallLoop(), func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool { 61 var si linux.SignalInfo 62 switchOpts := ring0.SwitchOpts{ 63 Registers: regs, 64 FloatingPointState: &dummyFPState, 65 PageTables: pt, 66 FullRestore: true, 67 } 68 69 const mxcsrControllMask = uint32(0x1f80) 70 mxcsrBefore := uint32(0) 71 mxcsrAfter := uint32(0) 72 stmxcsr(&mxcsrBefore) 73 if mxcsrBefore == 0 { 74 // goruntime sets mxcsr to 0x1f80 and it never changes 75 // the control configuration. 76 panic("mxcsr is zero") 77 } 78 switchOpts.FloatingPointState.SetMXCSR(0) 79 if _, err := c.SwitchToUser( 80 switchOpts, &si); err == platform.ErrContextInterrupt { 81 return true // Retry. 82 } else if err != nil { 83 t.Errorf("application syscall failed: %v", err) 84 } 85 stmxcsr(&mxcsrAfter) 86 if mxcsrAfter&mxcsrControllMask != mxcsrBefore&mxcsrControllMask { 87 t.Errorf("mxcsr = %x (expected %x)", mxcsrBefore, mxcsrAfter) 88 } 89 return false 90 }) 91 } 92 93 //go:nosplit 94 func nestedVirtIsOn(c *vCPU, fs *cpuid.FeatureSet) bool { 95 bluepill(c) 96 return fs.HasFeature(cpuid.X86FeatureVMX) || fs.HasFeature(cpuid.X86FeatureSVM) 97 98 } 99 100 func TestKernelCPUID(t *testing.T) { 101 bluepillTest(t, func(c *vCPU) { 102 fs := cpuid.FeatureSet{ 103 Function: &cpuid.Native{}, 104 } 105 if nestedVirtIsOn(c, &fs) { 106 t.Fatalf("Nested virtualization is enabled") 107 } 108 }) 109 }