[PATCH v2 08/16] KVM: x86/xen: register shared_info page

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Joao Martins <joao.m.martins@xxxxxxxxxx>

We add a new ioctl, XEN_HVM_SHARED_INFO, to allow hypervisor
to know where the guest's shared info page is.

Signed-off-by: Joao Martins <joao.m.martins@xxxxxxxxxx>
Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx>
---
 arch/x86/include/asm/kvm_host.h |  2 +
 arch/x86/kvm/x86.c              |  1 +
 arch/x86/kvm/xen.c              | 69 +++++++++++++++++++++++++++++++++
 include/uapi/linux/kvm.h        |  4 ++
 4 files changed, 76 insertions(+)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index c9a4feaee2e7..b6eff9814c6a 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -893,6 +893,8 @@ struct msr_bitmap_range {
 /* Xen emulation context */
 struct kvm_xen {
 	bool long_mode;
+	struct kvm_host_map shinfo_map;
+	void *shinfo;
 };
 
 enum kvm_irqchip_mode {
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 975ef5d6dda1..4a960629687c 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10446,6 +10446,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 	kvm_mmu_uninit_vm(kvm);
 	kvm_page_track_cleanup(kvm);
 	kvm_hv_destroy_vm(kvm);
+	kvm_xen_destroy_vm(kvm);
 }
 
 void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *slot)
diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
index 52cb9e465542..c156ed1ef972 100644
--- a/arch/x86/kvm/xen.c
+++ b/arch/x86/kvm/xen.c
@@ -13,9 +13,51 @@
 #include <linux/kvm_host.h>
 
 #include <trace/events/kvm.h>
+#include <xen/interface/xen.h>
 
 #include "trace.h"
 
+static int kvm_xen_map_guest_page(struct kvm *kvm, struct kvm_host_map *map,
+				  void **hva, gpa_t gpa, size_t len)
+{
+	gfn_t gfn = gpa_to_gfn(gpa);
+	struct kvm_host_map new_map;
+	bool unmap = !!*hva;
+	int ret;
+
+	if (offset_in_page(gpa) + len > PAGE_SIZE)
+		return -EINVAL;
+
+	ret = kvm_map_gfn(kvm, gfn, &new_map, NULL, false);
+	if (ret)
+		return ret;
+
+	WRITE_ONCE(*hva, new_map.hva + offset_in_page(gpa));
+
+	if (unmap) {
+	        synchronize_srcu(&kvm->srcu);
+
+		kvm_unmap_gfn(kvm, map, NULL, true, false);
+	}
+
+	*map = new_map;
+	return 0;
+}
+
+static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn)
+{
+	gpa_t gpa = gfn_to_gpa(gfn);
+	int ret;
+
+	ret = kvm_xen_map_guest_page(kvm, &kvm->arch.xen.shinfo_map,
+				     (void **)&kvm->arch.xen.shinfo, gpa,
+				     PAGE_SIZE);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
 {
 	int r = -ENOENT;
@@ -28,6 +70,14 @@ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
 		kvm->arch.xen.long_mode = !!data->u.long_mode;
 		r = 0;
 		break;
+
+	case KVM_XEN_ATTR_TYPE_SHARED_INFO: {
+		gfn_t gfn = data->u.shared_info.gfn;
+
+		r = kvm_xen_shared_info_init(kvm, gfn);
+		break;
+	}
+
 	default:
 		break;
 	}
@@ -44,6 +94,15 @@ int kvm_xen_hvm_get_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data)
 		data->u.long_mode = kvm->arch.xen.long_mode;
 		r = 0;
 		break;
+
+	case KVM_XEN_ATTR_TYPE_SHARED_INFO: {
+		if (kvm->arch.xen.shinfo) {
+			data->u.shared_info.gfn = kvm->arch.xen.shinfo_map.gfn;
+			r = 0;
+		}
+		break;
+	}
+
 	default:
 		break;
 	}
@@ -182,3 +241,13 @@ int kvm_xen_hypercall(struct kvm_vcpu *vcpu)
 
 	return 0;
 }
+
+void kvm_xen_destroy_vm(struct kvm *kvm)
+{
+	struct kvm_xen *xen = &kvm->arch.xen;
+
+	if (xen->shinfo) {
+		kvm_unmap_gfn(kvm, &xen->shinfo_map, NULL, true, false);
+		xen->shinfo = NULL;
+	}
+}
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 6b556ef98b76..caa9faf3c5ad 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1585,11 +1585,15 @@ struct kvm_xen_hvm_attr {
 
 	union {
 		__u8 long_mode;
+		struct {
+			__u64 gfn;
+		} shared_info;
 		__u64 pad[4];
 	} u;
 };
 
 #define KVM_XEN_ATTR_TYPE_LONG_MODE		0x0
+#define KVM_XEN_ATTR_TYPE_SHARED_INFO		0x1
 
 /* Secure Encrypted Virtualization command */
 enum sev_cmd_id {
-- 
2.26.2




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux