mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Merge pull request #4598 from lubinszARM:pr_kvm_precise_sync
PiperOrigin-RevId: 339404936
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(®); 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.
|
||||
|
||||
Reference in New Issue
Block a user