From: Mihai Donțu <mdontu@xxxxxxxxxxxxxxx> For now, this command returns the TSC frequency (in HZ) for the specified vCPU if available (otherwise it returns zero). Signed-off-by: Mihai Donțu <mdontu@xxxxxxxxxxxxxxx> Signed-off-by: Adalbert Lazăr <alazar@xxxxxxxxxxxxxxx> --- Documentation/virtual/kvm/kvmi.rst | 29 +++++++++++++++++++++++++++++ arch/x86/kvm/kvmi.c | 12 ++++++++++++ include/uapi/linux/kvmi.h | 4 ++++ virt/kvm/kvmi_int.h | 2 ++ virt/kvm/kvmi_msg.c | 14 ++++++++++++++ 5 files changed, 61 insertions(+) diff --git a/Documentation/virtual/kvm/kvmi.rst b/Documentation/virtual/kvm/kvmi.rst index b29cd1b80b4f..71897338e85a 100644 --- a/Documentation/virtual/kvm/kvmi.rst +++ b/Documentation/virtual/kvm/kvmi.rst @@ -427,6 +427,35 @@ in almost all cases, it must reply with: continue, retry, crash, etc. * -KVM_EINVAL - padding is not zero * -KVM_EPERM - the access is restricted by the host +7. KVMI_GET_VCPU_INFO +--------------------- + +:Architectures: all +:Versions: >= 1 +:Parameters: + +:: + + struct kvmi_vcpu_hdr; + +:Returns: + +:: + + struct kvmi_error_code; + struct kvmi_get_vcpu_info_reply { + __u64 tsc_speed; + }; + +Returns the TSC frequency (in HZ) for the specified vCPU if available +(otherwise it returns zero). + +:Errors: + +* -KVM_EINVAL - the selected vCPU is invalid +* -KVM_EINVAL - padding is not zero +* -KVM_EAGAIN - the selected vCPU can't be introspected yet + Events ====== diff --git a/arch/x86/kvm/kvmi.c b/arch/x86/kvm/kvmi.c index 9aecca551673..97c72cdc6fb0 100644 --- a/arch/x86/kvm/kvmi.c +++ b/arch/x86/kvm/kvmi.c @@ -90,3 +90,15 @@ void kvmi_arch_setup_event(struct kvm_vcpu *vcpu, struct kvmi_event *ev) ev->arch.mode = kvmi_vcpu_mode(vcpu, &event->sregs); kvmi_get_msrs(vcpu, event); } + +int kvmi_arch_cmd_get_vcpu_info(struct kvm_vcpu *vcpu, + struct kvmi_get_vcpu_info_reply *rpl) +{ + if (kvm_has_tsc_control) + rpl->tsc_speed = 1000ul * vcpu->arch.virtual_tsc_khz; + else + rpl->tsc_speed = 0; + + return 0; +} + diff --git a/include/uapi/linux/kvmi.h b/include/uapi/linux/kvmi.h index ccf2239b5db4..aa5bc909e278 100644 --- a/include/uapi/linux/kvmi.h +++ b/include/uapi/linux/kvmi.h @@ -112,6 +112,10 @@ struct kvmi_get_guest_info_reply { __u32 padding[3]; }; +struct kvmi_get_vcpu_info_reply { + __u64 tsc_speed; +}; + struct kvmi_control_vm_events { __u16 event_id; __u8 enable; diff --git a/virt/kvm/kvmi_int.h b/virt/kvm/kvmi_int.h index c21f0fd5e16c..7cff91bc1acc 100644 --- a/virt/kvm/kvmi_int.h +++ b/virt/kvm/kvmi_int.h @@ -139,5 +139,7 @@ int kvmi_add_job(struct kvm_vcpu *vcpu, /* arch */ void kvmi_arch_setup_event(struct kvm_vcpu *vcpu, struct kvmi_event *ev); +int kvmi_arch_cmd_get_vcpu_info(struct kvm_vcpu *vcpu, + struct kvmi_get_vcpu_info_reply *rpl); #endif diff --git a/virt/kvm/kvmi_msg.c b/virt/kvm/kvmi_msg.c index 8e8af572a4f4..3372d8c7e74f 100644 --- a/virt/kvm/kvmi_msg.c +++ b/virt/kvm/kvmi_msg.c @@ -28,6 +28,7 @@ static const char *const msg_IDs[] = { [KVMI_EVENT] = "KVMI_EVENT", [KVMI_EVENT_REPLY] = "KVMI_EVENT_REPLY", [KVMI_GET_GUEST_INFO] = "KVMI_GET_GUEST_INFO", + [KVMI_GET_VCPU_INFO] = "KVMI_GET_VCPU_INFO", [KVMI_GET_VERSION] = "KVMI_GET_VERSION", }; @@ -390,6 +391,18 @@ static int handle_event_reply(struct kvm_vcpu *vcpu, return expected->error; } +static int handle_get_vcpu_info(struct kvm_vcpu *vcpu, + const struct kvmi_msg_hdr *msg, + const void *req, vcpu_reply_fct reply_cb) +{ + struct kvmi_get_vcpu_info_reply rpl; + + memset(&rpl, 0, sizeof(rpl)); + kvmi_arch_cmd_get_vcpu_info(vcpu, &rpl); + + return reply_cb(vcpu, msg, 0, &rpl, sizeof(rpl)); +} + /* * These commands are executed on the vCPU thread. The receiving thread * passes the messages using a newly allocated 'struct kvmi_vcpu_cmd' @@ -400,6 +413,7 @@ static int(*const msg_vcpu[])(struct kvm_vcpu *, const struct kvmi_msg_hdr *, const void *, vcpu_reply_fct) = { [KVMI_EVENT_REPLY] = handle_event_reply, + [KVMI_GET_VCPU_INFO] = handle_get_vcpu_info, }; static void kvmi_job_vcpu_cmd(struct kvm_vcpu *vcpu, void *_ctx)