132 lines
3.4 KiB
Go
132 lines
3.4 KiB
Go
// 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 amd64
|
|
|
|
package ring0
|
|
|
|
import (
|
|
"gvisor.googlesource.com/gvisor/pkg/cpuid"
|
|
)
|
|
|
|
// LoadFloatingPoint loads floating point state by the most efficient mechanism
|
|
// available (set by Init).
|
|
var LoadFloatingPoint func(*byte)
|
|
|
|
// SaveFloatingPoint saves floating point state by the most efficient mechanism
|
|
// available (set by Init).
|
|
var SaveFloatingPoint func(*byte)
|
|
|
|
// fxrstor uses fxrstor64 to load floating point state.
|
|
func fxrstor(*byte)
|
|
|
|
// xrstor uses xrstor to load floating point state.
|
|
func xrstor(*byte)
|
|
|
|
// fxsave uses fxsave64 to save floating point state.
|
|
func fxsave(*byte)
|
|
|
|
// xsave uses xsave to save floating point state.
|
|
func xsave(*byte)
|
|
|
|
// xsaveopt uses xsaveopt to save floating point state.
|
|
func xsaveopt(*byte)
|
|
|
|
// WriteFS sets the GS address (set by init).
|
|
var WriteFS func(addr uintptr)
|
|
|
|
// wrfsbase writes to the GS base address.
|
|
func wrfsbase(addr uintptr)
|
|
|
|
// wrfsmsr writes to the GS_BASE MSR.
|
|
func wrfsmsr(addr uintptr)
|
|
|
|
// WriteGS sets the GS address (set by init).
|
|
var WriteGS func(addr uintptr)
|
|
|
|
// wrgsbase writes to the GS base address.
|
|
func wrgsbase(addr uintptr)
|
|
|
|
// wrgsmsr writes to the GS_BASE MSR.
|
|
func wrgsmsr(addr uintptr)
|
|
|
|
// writeCR3 writes the CR3 value.
|
|
func writeCR3(phys uintptr)
|
|
|
|
// readCR3 reads the current CR3 value.
|
|
func readCR3() uintptr
|
|
|
|
// readCR2 reads the current CR2 value.
|
|
func readCR2() uintptr
|
|
|
|
// jumpToKernel jumps to the kernel version of the current RIP.
|
|
func jumpToKernel()
|
|
|
|
// jumpToUser jumps to the user version of the current RIP.
|
|
func jumpToUser()
|
|
|
|
// fninit initializes the floating point unit.
|
|
func fninit()
|
|
|
|
// xsetbv writes to an extended control register.
|
|
func xsetbv(reg, value uintptr)
|
|
|
|
// xgetbv reads an extended control register.
|
|
func xgetbv(reg uintptr) uintptr
|
|
|
|
// wrmsr reads to the given MSR.
|
|
func wrmsr(reg, value uintptr)
|
|
|
|
// rdmsr reads the given MSR.
|
|
func rdmsr(reg uintptr) uintptr
|
|
|
|
// Mostly-constants set by Init.
|
|
var (
|
|
hasSMEP bool
|
|
hasPCID bool
|
|
hasXSAVEOPT bool
|
|
hasXSAVE bool
|
|
hasFSGSBASE bool
|
|
validXCR0Mask uintptr
|
|
)
|
|
|
|
// Init sets function pointers based on architectural features.
|
|
//
|
|
// This must be called prior to using ring0.
|
|
func Init(featureSet *cpuid.FeatureSet) {
|
|
hasSMEP = featureSet.HasFeature(cpuid.X86FeatureSMEP)
|
|
hasPCID = featureSet.HasFeature(cpuid.X86FeaturePCID)
|
|
hasXSAVEOPT = featureSet.UseXsaveopt()
|
|
hasXSAVE = featureSet.UseXsave()
|
|
hasFSGSBASE = featureSet.HasFeature(cpuid.X86FeatureFSGSBase)
|
|
validXCR0Mask = uintptr(featureSet.ValidXCR0Mask())
|
|
if hasXSAVEOPT {
|
|
SaveFloatingPoint = xsaveopt
|
|
LoadFloatingPoint = xrstor
|
|
} else if hasXSAVE {
|
|
SaveFloatingPoint = xsave
|
|
LoadFloatingPoint = xrstor
|
|
} else {
|
|
SaveFloatingPoint = fxsave
|
|
LoadFloatingPoint = fxrstor
|
|
}
|
|
if hasFSGSBASE {
|
|
WriteFS = wrfsbase
|
|
WriteGS = wrgsbase
|
|
} else {
|
|
WriteFS = wrfsmsr
|
|
WriteGS = wrgsmsr
|
|
}
|
|
}
|