8000 kvm: enable CPUID faulting on all VCPUs by copybara-service[bot] · Pull Request #11492 · google/gvisor · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

kvm: enable CPUID faulting on all VCPUs #11492

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions pkg/ring0/kernel_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,27 +315,6 @@ func startGo(c *CPU) {
wrmsr(_MSR_CSTAR, kernelFunc(addrOfSysenter()))
}

// SetCPUIDFaulting sets CPUID faulting per the boolean value.
//
// True is returned if faulting could be set.
//
//go:nosplit
func SetCPUIDFaulting(on bool) bool {
// Per the SDM (Vol 3, Table 2-43), PLATFORM_INFO bit 31 denotes support
// for CPUID faulting, and we enable and disable via the MISC_FEATURES MSR.
if rdmsr(_MSR_PLATFORM_INFO)&_PLATFORM_INFO_CPUID_FAULT != 0 {
features := rdmsr(_MSR_MISC_FEATURES)
if on {
features |= _MISC_FEATURE_CPUID_TRAP
} else {
features &^= _MISC_FEATURE_CPUID_TRAP
}
wrmsr(_MSR_MISC_FEATURES, features)
return true // Setting successful.
}
return false
}

// ReadCR2 reads the current CR2 value.
//
//go:nosplit
Expand Down
14 changes: 4 additions & 10 deletions pkg/ring0/x86.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,10 @@ const (
_EFER_LMA = 0x400
_EFER_NX = 0x800

_MSR_STAR = 0xc0000081
_MSR_LSTAR = 0xc0000082
_MSR_CSTAR = 0xc0000083
_MSR_SYSCALL_MASK = 0xc0000084
_MSR_PLATFORM_INFO = 0xce
_MSR_MISC_FEATURES = 0x140

_PLATFORM_INFO_CPUID_FAULT = 1 << 31

_MISC_FEATURE_CPUID_TRAP = 0x1
_MSR_STAR = 0xc0000081
_MSR_LSTAR = 0xc0000082
_MSR_CSTAR = 0xc0000083
_MSR_SYSCALL_MASK = 0xc0000084
)

const (
Expand Down
38 changes: 20 additions & 18 deletions pkg/sentry/platform/kvm/machine_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,18 @@ import (
"math/big"
"reflect"
"runtime"
"runtime/debug"

"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/hostsyscall"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/ring0"
"gvisor.dev/gvisor/pkg/ring0/pagetables"
"gvisor.dev/gvisor/pkg/sentry/platform"
ktime "gvisor.dev/gvisor/pkg/sentry/time"
"gvisor.dev/gvisor/pkg/sync"
)

// initArchState initializes architecture-specific state.
Expand All @@ -54,22 +55,6 @@ func (m *machine) initArchState() error {
}
m.mu.Unlock()

c := m.Get()
defer m.Put(c)
// Enable CPUID faulting, if possible. Note that this also serves as a
// basic platform sanity tests, since we will enter guest mode for the
// first time here. The recovery is necessary, since if we fail to read
// the platform info register, we will retry to host mode and
// ultimately need to handle a segmentation fault.
old := debug.SetPanicOnFault(true)
defer func() {
recover()
debug.SetPanicOnFault(old)
}()

bluepill(c)
ring0.SetCPUIDFaulting(true)

return nil
}

Expand Down Expand Up @@ -97,6 +82,8 @@ const (
poolPCIDs = 8
)

var cpuidFaultingWarnOnce sync.Once

// initArchState initializes architecture-specific state.
func (c *vCPU) initArchState() error {
var (
Expand Down Expand Up @@ -158,7 +145,22 @@ func (c *vCPU) initArchState() error {
}

// Set the time offset to the host native time.
return c.setSystemTime()
if err := c.setSystemTime(); err != nil {
return err
}

// Try to enable CPUID faulting. This is required to handle app CPUID
// correctly, since we always pass the CPUID returned by
// KVM_GET_SUPPORTED_CPUID to KVM_SET_CPUID2. Note that while hardware
// support for CPUID faulting is inconsistent, KVM always supports it after
// db2336a80489e ("KVM: x86: virtualize cpuid faulting"), Linux 4.12+.
if err := c.enableCPUIDFaulting(); err != nil {
cpuidFaultingWarnOnce.Do(func() {
log.Warningf("Application CPUID will be incorrect: %v", err)
})
}

return nil
}

// bitsForScaling returns the bits available for storing the fraction component
Expand Down
20 changes: 20 additions & 0 deletions pkg/sentry/platform/kvm/machine_amd64_unsafe.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,26 @@ func (c *vCPU) setTSC(value uint64) error {
return nil
}

func (c *vCPU) enableCPUIDFaulting() error {
const (
_MSR_MISC_FEATURES_ENABLE = 0x140
_MSR_MISC_FEATURES_ENABLES_CPUID_FAULT = 1 << 0
)
registers := modelControlRegisters{
nmsrs: 1,
}
registers.entries[0].index = _MSR_MISC_FEATURES_ENABLE
registers.entries[0].data = _MSR_MISC_FEATURES_ENABLES_CPUID_FAULT
if errno := hostsyscall.RawSyscallErrno(
unix.SYS_IOCTL,
uintptr(c.fd),
KVM_SET_MSRS,
uintptr(unsafe.Pointer(&registers))); errno != 0 {
return fmt.Errorf("error enabling CPUID faulting: %v", errno)
}
return nil
}

// setUserRegisters sets user registers in the vCPU.
//
//go:nosplit
Expand Down
Loading
0