From: Mihai Dontu <mdontu@xxxxxxxxxxxxxxx> The introspection subsystem uses UUIDs to identify VMs. This patch adds support for QEMU to query for KVM_CAP_VM_UUID and set the uuid with KVM_SET_VM_UUID. The kvm_from_uuid() helper is used to search and 'get' a kvm struct by UUID, in order to link the VM and the guest introspection tool with a control socket connection. Signed-off-by: Mihai Dontu <mdontu@xxxxxxxxxxxxxxx> --- include/linux/kvm_host.h | 4 ++++ include/uapi/linux/kvm.h | 2 ++ virt/kvm/kvm_main.c | 26 ++++++++++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 88d4e4cbaba5..545964ed6a63 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -27,6 +27,7 @@ #include <linux/irqbypass.h> #include <linux/swait.h> #include <linux/refcount.h> +#include <linux/uuid.h> #include <asm/signal.h> #include <linux/kvm.h> @@ -438,6 +439,8 @@ struct kvm { struct kvm_stat_data **debugfs_stat_data; struct srcu_struct srcu; struct srcu_struct irq_srcu; + + uuid_le uuid; }; #define kvm_err(fmt, ...) \ @@ -551,6 +554,7 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align, void kvm_exit(void); void kvm_enum(int (*enum_cb) (const struct kvm *kvm, void *param), void *param); +struct kvm *kvm_from_uuid(const uuid_le *uuid); void kvm_get_kvm(struct kvm *kvm); void kvm_put_kvm(struct kvm *kvm); diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 577429a95ad8..9b5813597d71 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -895,6 +895,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_SPAPR_TCE_VFIO 142 #define KVM_CAP_X86_GUEST_MWAIT 143 #define KVM_CAP_ARM_USER_IRQ 144 +#define KVM_CAP_VM_UUID 145 #ifdef KVM_CAP_IRQ_ROUTING @@ -1318,6 +1319,7 @@ struct kvm_s390_ucas_mapping { #define KVM_S390_GET_IRQ_STATE _IOW(KVMIO, 0xb6, struct kvm_s390_irq_state) /* Available with KVM_CAP_X86_SMM */ #define KVM_SMI _IO(KVMIO, 0xb7) +#define KVM_SET_VM_UUID _IOW(KVMIO, 0xb8, uuid_le) #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index cfd2d1bf8ac4..31bcdc92f1ea 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -2924,6 +2924,7 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) #endif case KVM_CAP_IOEVENTFD_ANY_LENGTH: case KVM_CAP_CHECK_EXTENSION_VM: + case KVM_CAP_VM_UUID: return 1; #ifdef CONFIG_KVM_MMIO case KVM_CAP_COALESCED_MMIO: @@ -3106,6 +3107,13 @@ static long kvm_vm_ioctl(struct file *filp, case KVM_CHECK_EXTENSION: r = kvm_vm_ioctl_check_extension_generic(kvm, arg); break; + case KVM_SET_VM_UUID: + r = -EFAULT; + if (copy_from_user(&kvm->uuid, argp, sizeof(kvm->uuid))) + goto out; + + r = 0; + break; default: r = kvm_arch_vm_ioctl(filp, ioctl, arg); } @@ -4058,3 +4066,21 @@ void kvm_enum(int (*enum_cb) (const struct kvm *kvm, void *param), void *param) } spin_unlock(&kvm_lock); } + +/* Make sure to call kvm_put_kvm() when done */ +struct kvm *kvm_from_uuid(const uuid_le *uuid) +{ + struct kvm *kvm; + struct kvm *found = NULL; + + spin_lock(&kvm_lock); + list_for_each_entry(kvm, &vm_list, vm_list) { + if (!memcmp(&kvm->uuid, uuid, sizeof(kvm->uuid))) { + kvm_get_kvm(kvm); + found = kvm; + break; + } + } + spin_unlock(&kvm_lock); + return found; +} -- 2.12.2