|
@@ -244,12 +244,49 @@ int kvm_pmu_is_valid_msr_idx(struct kvm_vcpu *vcpu, unsigned idx)
|
|
|
return kvm_x86_ops->pmu_ops->is_valid_msr_idx(vcpu, idx);
|
|
|
}
|
|
|
|
|
|
+bool is_vmware_backdoor_pmc(u32 pmc_idx)
|
|
|
+{
|
|
|
+ switch (pmc_idx) {
|
|
|
+ case VMWARE_BACKDOOR_PMC_HOST_TSC:
|
|
|
+ case VMWARE_BACKDOOR_PMC_REAL_TIME:
|
|
|
+ case VMWARE_BACKDOOR_PMC_APPARENT_TIME:
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+static int kvm_pmu_rdpmc_vmware(struct kvm_vcpu *vcpu, unsigned idx, u64 *data)
|
|
|
+{
|
|
|
+ u64 ctr_val;
|
|
|
+
|
|
|
+ switch (idx) {
|
|
|
+ case VMWARE_BACKDOOR_PMC_HOST_TSC:
|
|
|
+ ctr_val = rdtsc();
|
|
|
+ break;
|
|
|
+ case VMWARE_BACKDOOR_PMC_REAL_TIME:
|
|
|
+ ctr_val = ktime_get_boot_ns();
|
|
|
+ break;
|
|
|
+ case VMWARE_BACKDOOR_PMC_APPARENT_TIME:
|
|
|
+ ctr_val = ktime_get_boot_ns() +
|
|
|
+ vcpu->kvm->arch.kvmclock_offset;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ *data = ctr_val;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
int kvm_pmu_rdpmc(struct kvm_vcpu *vcpu, unsigned idx, u64 *data)
|
|
|
{
|
|
|
bool fast_mode = idx & (1u << 31);
|
|
|
struct kvm_pmc *pmc;
|
|
|
u64 ctr_val;
|
|
|
|
|
|
+ if (is_vmware_backdoor_pmc(idx))
|
|
|
+ return kvm_pmu_rdpmc_vmware(vcpu, idx, data);
|
|
|
+
|
|
|
pmc = kvm_x86_ops->pmu_ops->msr_idx_to_pmc(vcpu, idx);
|
|
|
if (!pmc)
|
|
|
return 1;
|