Fallback to legacy system time logic when host does not have TSC_CONTROL

If the host doesn't have TSC scaling feature, then scaling down TSC to
the lowest value will fail, and we will fall back to legacy logic
anyway, but we leave an ugly log message in host's kernel log.

  kernel: user requested TSC rate below hardware speed

Instead, check for KVM_CAP_TSC_CONTROL when initializing KVM, and fall
back to legacy logic early if host's cpu doesn't support that.

Signed-off-by: Daniel Dao <dqminh89@gmail.com>
This commit is contained in:
Daniel Dao 2021-03-26 11:15:23 +00:00
parent fbec65fc3f
commit 58843520b5
No known key found for this signature in database
GPG Key ID: ECAB2B462D43B768
3 changed files with 14 additions and 0 deletions

View File

@ -66,6 +66,7 @@ const (
_KVM_CAP_ARM_VM_IPA_SIZE = 0xa5
_KVM_CAP_VCPU_EVENTS = 0x29
_KVM_CAP_ARM_INJECT_SERROR_ESR = 0x9e
_KVM_CAP_TSC_CONTROL = 0x3c
)
// KVM limits.

View File

@ -67,6 +67,9 @@ type machine struct {
// maxSlots is the maximum number of memory slots supported by the machine.
maxSlots int
// tscControl checks whether cpu supports TSC scaling
tscControl bool
// usedSlots is the set of used physical addresses (sorted).
usedSlots []uintptr
@ -214,6 +217,11 @@ func newMachine(vm int) (*machine, error) {
log.Debugf("The maximum number of slots is %d.", m.maxSlots)
m.usedSlots = make([]uintptr, m.maxSlots)
// Check TSC Scaling
hasTSCControl, _, errno := unix.RawSyscall(unix.SYS_IOCTL, uintptr(m.fd), _KVM_CHECK_EXTENSION, _KVM_CAP_TSC_CONTROL)
m.tscControl = errno == 0 && hasTSCControl == 1
log.Debugf("TSC scaling support: %t.", m.tscControl)
// Create the upper shared pagetables and kernel(sentry) pagetables.
m.upperSharedPageTables = pagetables.New(newAllocator())
m.mapUpperHalf(m.upperSharedPageTables)

View File

@ -213,6 +213,11 @@ func (c *vCPU) setSystemTime() error {
// capabilities as it is emulated in KVM. We don't actually use this
// capability, but it means that this method should be robust to
// different hardware configurations.
// if tsc scaling is not supported, fallback to legacy mode
if !c.machine.tscControl {
return c.setSystemTimeLegacy()
}
rawFreq, err := c.getTSCFreq()
if err != nil {
return c.setSystemTimeLegacy()