Thread (131 messages) 131 messages, 5 authors, 2019-09-10
STALE2447d
Revisions (5)
  1. v4 [diff vs current]
  2. v6 current
  3. v8 [diff vs current]
  4. v10 [diff vs current]
  5. v11 [diff vs current]

[RFC PATCH v6 18/92] kvm: introspection: add KVMI_EVENT_UNHOOK

From: Adalbert Lazăr <hidden>
Date: 2019-08-09 16:01:45
Also in: kvm, linux-mm
Subsystem: documentation, kernel virtual machine (kvm), the rest · Maintainers: Jonathan Corbet, Paolo Bonzini, Linus Torvalds

In certain situations (when the guest has to be paused, suspended,
migrated, etc.), userspace/QEMU will use the KVM_INTROSPECTION_UNHOOK
ioctl in order to trigger the KVMI_EVENT_UNHOOK. If the event is sent
successfully (the VM has an active introspection channel), userspace
should delay the action (pause/suspend/...) to give the introspection
tool the chance to remove its hooks (eg. breakpoints). Once a timeout
is reached or the introspection tool has closed the socket, QEMU should
continue with the planned action.

Signed-off-by: Adalbert Lazăr <redacted>
---
 Documentation/virtual/kvm/kvmi.rst | 20 ++++++++++++++++++
 virt/kvm/kvmi.c                    | 34 +++++++++++++++++++++++++++++-
 virt/kvm/kvmi_int.h                |  1 +
 virt/kvm/kvmi_msg.c                | 20 ++++++++++++++++++
 4 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/Documentation/virtual/kvm/kvmi.rst b/Documentation/virtual/kvm/kvmi.rst
index 1ea4be0d5a45..28e1a1c80551 100644
--- a/Documentation/virtual/kvm/kvmi.rst
+++ b/Documentation/virtual/kvm/kvmi.rst
@@ -493,3 +493,23 @@ Some of the events accept the KVMI_EVENT_ACTION_RETRY action, to continue
 by re-entering the guest.
 
 Specific data can follow these common structures.
+
+1. KVMI_EVENT_UNHOOK
+--------------------
+
+:Architecture: all
+:Versions: >= 1
+:Actions: CONTINUE, CRASH
+:Parameters:
+
+::
+
+	struct kvmi_event;
+
+:Returns: none
+
+This event is sent when the device manager (ie. QEMU) has to
+pause/stop/migrate the guest (see **Unhooking**) and the introspection
+has been enabled for this event (see **KVMI_CONTROL_VM_EVENTS**).
+The introspection tool has a chance to unhook and close the KVMI channel
+(signaling that the operation can proceed).
diff --git a/virt/kvm/kvmi.c b/virt/kvm/kvmi.c
index 0d3560b74f2d..7eda49bf65c4 100644
--- a/virt/kvm/kvmi.c
+++ b/virt/kvm/kvmi.c
@@ -644,6 +644,9 @@ int kvmi_cmd_control_vm_events(struct kvmi *ikvm, unsigned int event_id,
 
 static void kvmi_job_abort(struct kvm_vcpu *vcpu, void *ctx)
 {
+	struct kvmi_vcpu *ivcpu = IVCPU(vcpu);
+
+	ivcpu->reply_waiting = false;
 }
 
 static void kvmi_abort_events(struct kvm *kvm)
@@ -655,6 +658,34 @@ static void kvmi_abort_events(struct kvm *kvm)
 		kvmi_add_job(vcpu, kvmi_job_abort, NULL, NULL);
 }
 
+static bool __kvmi_unhook_event(struct kvmi *ikvm)
+{
+	int err;
+
+	if (!test_bit(KVMI_EVENT_UNHOOK, ikvm->vm_ev_mask))
+		return false;
+
+	err = kvmi_msg_send_unhook(ikvm);
+
+	return !err;
+}
+
+static bool kvmi_unhook_event(struct kvm *kvm)
+{
+	struct kvmi *ikvm;
+	bool ret = true;
+
+	ikvm = kvmi_get(kvm);
+	if (!ikvm)
+		return false;
+
+	ret = __kvmi_unhook_event(ikvm);
+
+	kvmi_put(kvm);
+
+	return ret;
+}
+
 int kvmi_ioctl_unhook(struct kvm *kvm, bool force_reset)
 {
 	struct kvmi *ikvm;
@@ -664,7 +695,8 @@ int kvmi_ioctl_unhook(struct kvm *kvm, bool force_reset)
 	if (!ikvm)
 		return -EFAULT;
 
-	kvm_info("TODO: %s force_reset %d", __func__, force_reset);
+	if (!force_reset && !kvmi_unhook_event(kvm))
+		err = -ENOENT;
 
 	kvmi_put(kvm);
 
diff --git a/virt/kvm/kvmi_int.h b/virt/kvm/kvmi_int.h
index 70c8ca0343a3..9750a9b9902b 100644
--- a/virt/kvm/kvmi_int.h
+++ b/virt/kvm/kvmi_int.h
@@ -123,6 +123,7 @@ bool kvmi_sock_get(struct kvmi *ikvm, int fd);
 void kvmi_sock_shutdown(struct kvmi *ikvm);
 void kvmi_sock_put(struct kvmi *ikvm);
 bool kvmi_msg_process(struct kvmi *ikvm);
+int kvmi_msg_send_unhook(struct kvmi *ikvm);
 
 /* kvmi.c */
 void *kvmi_msg_alloc(void);
diff --git a/virt/kvm/kvmi_msg.c b/virt/kvm/kvmi_msg.c
index 536034e1bea7..0c7c1e968007 100644
--- a/virt/kvm/kvmi_msg.c
+++ b/virt/kvm/kvmi_msg.c
@@ -705,3 +705,23 @@ int kvmi_send_event(struct kvm_vcpu *vcpu, u32 ev_id,
 	return err;
 }
 
+int kvmi_msg_send_unhook(struct kvmi *ikvm)
+{
+	struct kvmi_msg_hdr hdr;
+	struct kvmi_event common;
+	struct kvec vec[] = {
+		{.iov_base = &hdr,	.iov_len = sizeof(hdr)	 },
+		{.iov_base = &common,	.iov_len = sizeof(common)},
+	};
+	size_t msg_size = sizeof(hdr) + sizeof(common);
+	size_t n = ARRAY_SIZE(vec);
+
+	memset(&hdr, 0, sizeof(hdr));
+	hdr.id = KVMI_EVENT;
+	hdr.seq = new_seq(ikvm);
+	hdr.size = msg_size - sizeof(hdr);
+
+	kvmi_setup_event_common(&common, KVMI_EVENT_UNHOOK, 0);
+
+	return kvmi_sock_write(ikvm, vec, n, msg_size);
+}
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help