Merge pull request #4598 from lubinszARM:pr_kvm_precise_sync

PiperOrigin-RevId: 339404936
This commit is contained in:
gVisor bot
2020-10-27 23:47:12 -07:00
4 changed files with 59 additions and 32 deletions
@@ -38,6 +38,8 @@ const (
_KVM_ARM64_REGS_SCTLR_EL1 = 0x603000000013c080
_KVM_ARM64_REGS_CPACR_EL1 = 0x603000000013c082
_KVM_ARM64_REGS_VBAR_EL1 = 0x603000000013c600
_KVM_ARM64_REGS_TIMER_CNT = 0x603000000013df1a
_KVM_ARM64_REGS_CNTFRQ_EL0 = 0x603000000013df00
)
// Arm64: Architectural Feature Access Control Register EL1.
+33
View File
@@ -25,6 +25,7 @@ import (
"gvisor.dev/gvisor/pkg/procid"
"gvisor.dev/gvisor/pkg/sentry/platform/ring0"
"gvisor.dev/gvisor/pkg/sentry/platform/ring0/pagetables"
ktime "gvisor.dev/gvisor/pkg/sentry/time"
"gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/usermem"
)
@@ -625,3 +626,35 @@ func (c *vCPU) BounceToKernel() {
func (c *vCPU) BounceToHost() {
c.bounce(true)
}
// setSystemTimeLegacy calibrates and sets an approximate system time.
func (c *vCPU) setSystemTimeLegacy() error {
const minIterations = 10
minimum := uint64(0)
for iter := 0; ; iter++ {
// Try to set the TSC to an estimate of where it will be
// on the host during a "fast" system call iteration.
start := uint64(ktime.Rdtsc())
if err := c.setTSC(start + (minimum / 2)); err != nil {
return err
}
// See if this is our new minimum call time. Note that this
// serves two functions: one, we make sure that we are
// accurately predicting the offset we need to set. Second, we
// don't want to do the final set on a slow call, which could
// produce a really bad result.
end := uint64(ktime.Rdtsc())
if end < start {
continue // Totally bogus: unstable TSC?
}
current := end - start
if current < minimum || iter == 0 {
minimum = current // Set our new minimum.
}
// Is this past minIterations and within ~10% of minimum?
upperThreshold := (((minimum << 3) + minimum) >> 3)
if iter >= minIterations && current <= upperThreshold {
return nil
}
}
}
-32
View File
@@ -252,38 +252,6 @@ func (c *vCPU) setSystemTime() error {
}
}
// setSystemTimeLegacy calibrates and sets an approximate system time.
func (c *vCPU) setSystemTimeLegacy() error {
const minIterations = 10
minimum := uint64(0)
for iter := 0; ; iter++ {
// Try to set the TSC to an estimate of where it will be
// on the host during a "fast" system call iteration.
start := uint64(ktime.Rdtsc())
if err := c.setTSC(start + (minimum / 2)); err != nil {
return err
}
// See if this is our new minimum call time. Note that this
// serves two functions: one, we make sure that we are
// accurately predicting the offset we need to set. Second, we
// don't want to do the final set on a slow call, which could
// produce a really bad result.
end := uint64(ktime.Rdtsc())
if end < start {
continue // Totally bogus: unstable TSC?
}
current := end - start
if current < minimum || iter == 0 {
minimum = current // Set our new minimum.
}
// Is this past minIterations and within ~10% of minimum?
upperThreshold := (((minimum << 3) + minimum) >> 3)
if iter >= minIterations && current <= upperThreshold {
return nil
}
}
}
// nonCanonical generates a canonical address return.
//
//go:nosplit
@@ -159,9 +159,33 @@ func (c *vCPU) initArchState() error {
}
c.floatingPointState = arch.NewFloatingPointData()
return c.setSystemTime()
}
// setTSC sets the counter Virtual Offset.
func (c *vCPU) setTSC(value uint64) error {
var (
reg kvmOneReg
data uint64
)
reg.addr = uint64(reflect.ValueOf(&data).Pointer())
reg.id = _KVM_ARM64_REGS_TIMER_CNT
data = uint64(value)
if err := c.setOneRegister(&reg); err != nil {
return err
}
return nil
}
// setSystemTime sets the vCPU to the system time.
func (c *vCPU) setSystemTime() error {
return c.setSystemTimeLegacy()
}
//go:nosplit
func (c *vCPU) loadSegments(tid uint64) {
// TODO(gvisor.dev/issue/1238): TLS is not supported.