diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-12-19 18:06:42 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-12-19 18:06:42 +0000 |
commit | 2965c5b8db08b44c6487f1ac6988355f2cb33dc7 (patch) | |
tree | f9cdfdf29e7600a806c2855584e3c176684493a2 | |
parent | 9adbdda3f4605e113aec5157f12f19002970d24a (diff) |
Pass calibrated TSC frequency to vmm(4) guests. On machines where TSC
cannot be calculated from the CPUID register, because the CPU does not
support it, but can be calibrated from another timer, the vmm(4) guest
doesn't have a chance to read or calibrate its own TSC frequency since
it has no access to a precise enough time counter. In that case, fake
the existence of the register and supply our calibrated TSC frequency.
mlarkin@ tells me this also greatly helps Linux guests.
ok mlarkin@
-rw-r--r-- | sys/arch/amd64/amd64/vmm.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/sys/arch/amd64/amd64/vmm.c b/sys/arch/amd64/amd64/vmm.c index 470306fe0ed..a689ddb4e04 100644 --- a/sys/arch/amd64/amd64/vmm.c +++ b/sys/arch/amd64/amd64/vmm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vmm.c,v 1.181 2017/12/17 19:16:02 mlarkin Exp $ */ +/* $OpenBSD: vmm.c,v 1.182 2017/12/19 18:06:41 patrick Exp $ */ /* * Copyright (c) 2014 Mike Larkin <mlarkin@openbsd.org> * @@ -224,6 +224,9 @@ struct vmm_reg_debug_info { }; #endif /* VMM_DEBUG */ +extern uint64_t tsc_frequency; +extern int tsc_is_invariant; + const char *vmm_hv_signature = VMM_HV_SIGNATURE; const struct kmem_pa_mode vmm_kp_contig = { @@ -5620,7 +5623,10 @@ vmm_handle_cpuid(struct vcpu *vcpu) switch (*rax) { case 0x00: /* Max level and vendor ID */ - *rax = cpuid_level; + if (cpuid_level < 0x15 && tsc_is_invariant) + *rax = 0x15; + else + *rax = cpuid_level; *rbx = *((uint32_t *)&cpu_vendor); *rdx = *((uint32_t *)&cpu_vendor + 1); *rcx = *((uint32_t *)&cpu_vendor + 2); @@ -5753,7 +5759,19 @@ vmm_handle_cpuid(struct vcpu *vcpu) *rdx = 0; break; case 0x15: - CPUID(0x15, *rax, *rbx, *rcx, *rdx); + if (cpuid_level >= 0x15) { + CPUID(0x15, *rax, *rbx, *rcx, *rdx); + } else if (tsc_is_invariant) { + *rax = 1; + *rbx = 100; + *rcx = tsc_frequency / 100; + *rdx = 0; + } else { + *rax = 0; + *rbx = 0; + *rcx = 0; + *rdx = 0; + } break; case 0x16: /* Processor frequency info (not supported) */ DPRINTF("%s: function 0x16 (frequency info) not supported\n", |