Skip to contentSkip to conversation

xinterface

PATCH New Gregory Haskins 6 participants 14 messages Jul 16, 2009 – Jul 17, 2009

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 xinterface

(Applies to kvm.git/master:84a3c081)

For details, please read the patch header.

Background: The original vbus code was tightly integrated with kvm.ko. Avi suggested that we abstract the interfaces such that it could live outside of kvm. Part of that discussion turned into what is now irqfd/ioeventfd checked into kvm.git. The other part of the discussion (pointer-translation) was suggested to be addressed by having the memory-slot info replicated across interested modules.

I was looking into what is required for essentially hooking the SET_MEMORY_REGION operations in QEMU yesterday by talking to Anthony and Glauber on IRC. We came to the conclusion that we could possibly do a minor cleanup on the various callsites of SET_MEMORY_REGION so that a wrapper function was used. I could then add a hook at this wrapper to essentially get notification events whenever memory-slots change, and could forward this info to my module appropriate.

Anthony made the observation that replicating the slots info is not the cleanest design, and I tend to agree with him. Its replicating data and is going to be prone to synchronization problems, etc. He also mentioned that other modules like virtio-net would want access to this same information at some point, so perhaps a general solution was in order.

Therefore, I stepped back from that initial approach of replicating slots and instead provided a abstract mechanism to utilize the original structures.

This code has been tested with a prototype of the vbus-v4 code and appears to function properly.

Comments/suggestions?

Regards,
-Greg

---

Gregory Haskins (1):
KVM: introduce "xinterface" API for external interaction with guests

 arch/x86/Kbuild                |    4 +
 arch/x86/kvm/Makefile          |    4 +
 arch/x86/kvm/x86.c             |    1 
 include/linux/kvm.h            |    2 +
 include/linux/kvm_host.h       |    6 ++
 include/linux/kvm_xinterface.h |   58 ++++++++++++++++
 virt/kvm/kvm_main.c            |   72 ++++++++++++++++++++
 virt/kvm/xinterface.c          |  147 ++++++++++++++++++++++++++++++++++++++++
 8 files changed, 293 insertions(+), 1 deletions(-)
 create mode 100644 include/linux/kvm_xinterface.h
 create mode 100644 virt/kvm/xinterface.c
Signature · 1 line
Signature
#1 lore raw

PATCH 1/1 KVM: introduce "xinterface" API for external interaction with guests

What: xinterface is a mechanism that allows kernel modules external to the kvm.ko proper to interface with a running guest. It accomplishes this by creating an abstracted interface which does not expose any private details of the guest or its related KVM structures, and provides a mechanism to find and bind to this interface at run-time. This binding mechanism uses a userspace friendly token "u64 vmid" as a handle. This vmid acts similar to a file-descriptor in the sense that it can be extracted from a guest, passed to an end-point of interest, and finally, converted back to a vtable pointer using a stable interface.

Why: There are various subsystems that would like to interact with a KVM guest which are ideally suited to exist outside the domain of the kvm.ko core logic. For instance, external pci-passthrough, virtual-bus, and virtio-net modules are currently under development. In order for these modules to successfully interact with the guest, they need, at the very least, various interfaces for signaling IO events, pointer translation, and possibly memory mapping.

The signaling case is covered by the recent introduction of the irqfd/ioeventfd mechanisms. This patch provides a mechanism to cover the other cases. Note that today we only expose pointer-translation related functions, but more could be added at a future date as needs arise.

Security considerations: This concept is not believed to expose KVM to any kind of additional security risk. The vmid token itself can only be acquired via an open handle to the vmfd (i.e. qemu-kvm), and the interface is only available within the kernel. Therefore the xinterface admission policy is delegated to the kernel/lkm admission policy, which must be assumed secure or the system is already compromised independent of this work.

Additionally, the xinterface design is hardened against malformed vmid tokens, as well as race conditions against valid tokens (e.g. guest exiting before the token is redeemed). It is additionally hardened against races in the kvm.ko module itself by acquiring proper module references. As a final measure, we link the xinterface code statically into the kernel so that callers are guaranteed a stable interface to kvm_xinterface_find() without implicitly pinning kvm.ko or racing against it.

Example usage: QEMU instantiates a guest, and an external module "foo" that desires the ability to interface with the guest (say via open("/dev/foo")). QEMU may then issue a KVM_GET_VMID operation to acquire the u64-based vmid, and pass it to ioctl(foofd, FOO_SET_VMID, &vmid). Upon receipt, the foo module can issue kvm_xinterface_find(vmid) to acquire the proper context. Internally, the struct kvm* and associated struct module* will remain pinned at least until the foo module calls kvm_xinterface_put().

---

 arch/x86/Kbuild                |    4 +
 arch/x86/kvm/Makefile          |    4 +
 arch/x86/kvm/x86.c             |    1 
 include/linux/kvm.h            |    2 +
 include/linux/kvm_host.h       |    6 ++
 include/linux/kvm_xinterface.h |   58 ++++++++++++++++
 virt/kvm/kvm_main.c            |   72 ++++++++++++++++++++
 virt/kvm/xinterface.c          |  147 ++++++++++++++++++++++++++++++++++++++++
 8 files changed, 293 insertions(+), 1 deletions(-)
 create mode 100644 include/linux/kvm_xinterface.h
 create mode 100644 virt/kvm/xinterface.c
arch/x86/Kbuild +3 -1
index ad8ec35..9f50cc3 100644
@@ -1,5 +1,7 @@
 
-obj-$(CONFIG_KVM) += kvm/
+ifdef CONFIG_KVM
+obj-y += kvm/
+endif
 
 # Xen paravirtualization support
 obj-$(CONFIG_XEN) += xen/
arch/x86/kvm/Makefile +4 -0
index afaaa76..80d951d 100644
@@ -17,3 +17,7 @@ kvm-amd-y		+= svm.o
 obj-$(CONFIG_KVM)	+= kvm.o
 obj-$(CONFIG_KVM_INTEL)	+= kvm-intel.o
 obj-$(CONFIG_KVM_AMD)	+= kvm-amd.o
+
+ifdef CONFIG_KVM
+obj-y += $(addprefix ../../../virt/kvm/, xinterface.o)
+endif
arch/x86/kvm/x86.c +1 -0
index 48567fa..5725527 100644
@@ -1208,6 +1208,7 @@ int kvm_dev_ioctl_check_extension(long ext)
 	case KVM_CAP_IOEVENTFD:
 	case KVM_CAP_PIT2:
 	case KVM_CAP_PIT_STATE2:
+	case KVM_CAP_XINTERFACE:
 		r = 1;
 		break;
 	case KVM_CAP_COALESCED_MMIO:
include/linux/kvm.h +2 -0
index 230a91a..7790894 100644
@@ -435,6 +435,7 @@ struct kvm_ioeventfd {
 #define KVM_CAP_PIT_STATE2 35
 #endif
 #define KVM_CAP_IOEVENTFD 36
+#define KVM_CAP_XINTERFACE 37
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -544,6 +545,7 @@ struct kvm_irqfd {
 #define KVM_CREATE_PIT2		   _IOW(KVMIO, 0x77, struct kvm_pit_config)
 #define KVM_SET_BOOT_CPU_ID        _IO(KVMIO, 0x78)
 #define KVM_IOEVENTFD             _IOW(KVMIO, 0x79, struct kvm_ioeventfd)
+#define KVM_GET_VMID              _IOR(KVMIO, 0x7a, __u64)
 
 /*
  * ioctls for vcpu fds
include/linux/kvm_host.h +6 -0
index f244f11..0ee95df 100644
@@ -23,6 +23,7 @@
 #include <linux/kvm_para.h>
 
 #include <linux/kvm_types.h>
+#include <linux/kvm_xinterface.h>
 
 #include <asm/kvm_host.h>
 
@@ -175,6 +176,7 @@ struct kvm {
 	unsigned long mmu_notifier_seq;
 	long mmu_notifier_count;
 #endif
+	struct kvm_xinterface xinterface; /* interface for external modules */
 };
 
 /* The guest did something we don't support. */
@@ -199,6 +201,10 @@ static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
 	     idx < atomic_read(&kvm->online_vcpus) && vcpup; \
 	     vcpup = kvm_get_vcpu(kvm, ++idx))
 
+void kvm_xinterface_register(struct kvm_xinterface *intf,
+			     const struct kvm_xinterface_ops *ops);
+void kvm_xinterface_unregister(struct kvm_xinterface *intf);
+
 int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id);
 void kvm_vcpu_uninit(struct kvm_vcpu *vcpu);
 
include/linux/kvm_xinterface.h new file +58 -0

58 lines not on this page · raw message

virt/kvm/kvm_main.c +72 -0

102 lines not on this page · raw message

virt/kvm/xinterface.c new file +147 -0

147 lines not on this page · raw message

#2 lore raw

Re: [KVM PATCH] KVM: introduce "xinterface" API for external interaction with guests

arch/x86/Kbuild line 4

Quoted 10 lines
arch/x86/Kbuild +3 -1
index ad8ec35..9f50cc3 100644
@@ -1,5 +1,7 @@
 
-obj-$(CONFIG_KVM) += kvm/
+ifdef CONFIG_KVM
+obj-y += kvm/
+endif

What was wrong with the old version?
If this is because xinterface.o is builtin to the kernel then we should always visit kvm/ and use:

obj-y += kvm/

unconditionally.

Quoted 8 lines
arch/x86/Kbuild +0 -0
 # Xen paravirtualization support
 obj-$(CONFIG_XEN) += xen/
arch/x86/kvm/Makefile +0 -0
index afaaa76..80d951d 100644

arch/x86/kvm/Makefile kvm-amd-y += svm.o · line 23

Quoted 7 lines
arch/x86/kvm/Makefile +4 -0
@@ -17,3 +17,7 @@ kvm-amd-y		+= svm.o
 obj-$(CONFIG_KVM)	+= kvm.o
 obj-$(CONFIG_KVM_INTEL)	+= kvm-intel.o
 obj-$(CONFIG_KVM_AMD)	+= kvm-amd.o
+
+ifdef CONFIG_KVM
+obj-y += $(addprefix ../../../virt/kvm/, xinterface.o)
+endif

And when we always visit kvm/ the above code snippet makes sense. Before we never visited kvm/ unless CONFIG_KVM was defined.

Sam

#3 lore raw

Re: [KVM PATCH] KVM: introduce "xinterface" API for external interaction with guests

Quoted 6 lines · Sam Ravnborg
Quoted 6 lines
arch/x86/Kbuild +0 -0
index ad8ec35..9f50cc3 100644
@@ -1,5 +1,7 @@
 
Quoted 8 lines

arch/x86/Kbuild line 5

Quoted 5 lines
arch/x86/Kbuild +3 -1
-obj-$(CONFIG_KVM) += kvm/
+ifdef CONFIG_KVM
+obj-y += kvm/
+endif
 

What was wrong with the old version?
If this is because xinterface.o is builtin to the kernel

Bingo

Quoted 8 lines

then we should
always visit kvm/ and use:

   obj-y += kvm/

unconditionally.

Ok, easy enough.

Thanks Sam,
-Greg

#4 lore raw

Re: [KVM PATCH] KVM: introduce "xinterface" API for external interaction with guests

In reply to Gregory Haskins
Quoted 42 lines · Gregory Haskins
virt/kvm/kvm_main.c +41 -0
+/*
+ * ------------
+ * XINTERFACE (External Interface)
+ * -------------
+ */
+
+static struct kvm *
+intf_to_kvm(struct kvm_xinterface *intf)
+{
+	return container_of(intf, struct kvm, xinterface);
+}
+
+static unsigned long
+xinterface_gpa_to_hva(struct kvm_xinterface *intf, unsigned long gpa)
+{
+	struct kvm *kvm = intf_to_kvm(intf);
+	unsigned long addr;
+
+	addr = gfn_to_hva(kvm, gpa >> PAGE_SHIFT);
+	if (kvm_is_error_hva(addr))
+		return 0;
+
+	return addr + offset_in_page(gpa);
+}
+
+static struct page *
+xinterface_gpa_to_page(struct kvm_xinterface *intf, unsigned long gpa)
+{
+	struct kvm *kvm = intf_to_kvm(intf);
+	struct page *page;
+
+	page = gfn_to_page(kvm, gpa >> PAGE_SHIFT);
+	if (page == bad_page)
+		return ERR_PTR(-EINVAL);
+
+	return page;
+}
+
+static void
+xinterface_release(struct kvm_xinterface *intf)
+{

virt/kvm/kvm_main.c static const struct mmu_notifier_ops kvm_mmu_notifier_ops = { · line 988

Quoted 10 lines
virt/kvm/kvm_main.c +10 -0
+	struct kvm *kvm = intf_to_kvm(intf);
+
+	kvm_put_kvm(kvm);
+}
+
+struct kvm_xinterface_ops _kvm_xinterface_ops = {
+	.gpa_to_hva  = xinterface_gpa_to_hva,
+	.gpa_to_page = xinterface_gpa_to_page,
+	.release     = xinterface_release,
+};

How do you deal with locking?

The mappings (gpa_to_page) are not fixed. They can and do change very often. The interface doesn't seem to attempt to cope with this.

Regards,

Anthony Liguori

#5 lore raw

Re: [KVM PATCH] KVM: introduce "xinterface" API for external interaction with guests

Quoted 56 lines · Anthony Liguori
Quoted 42 lines · Gregory Haskins
virt/kvm/kvm_main.c +41 -0
+/*
+ * ------------
+ * XINTERFACE (External Interface)
+ * -------------
+ */
+
+static struct kvm *
+intf_to_kvm(struct kvm_xinterface *intf)
+{
+    return container_of(intf, struct kvm, xinterface);
+}
+
+static unsigned long
+xinterface_gpa_to_hva(struct kvm_xinterface *intf, unsigned long gpa)
+{
+    struct kvm *kvm = intf_to_kvm(intf);
+    unsigned long addr;
+
+    addr = gfn_to_hva(kvm, gpa >> PAGE_SHIFT);
+    if (kvm_is_error_hva(addr))
+        return 0;
+
+    return addr + offset_in_page(gpa);
+}
+
+static struct page *
+xinterface_gpa_to_page(struct kvm_xinterface *intf, unsigned long gpa)
+{
+    struct kvm *kvm = intf_to_kvm(intf);
+    struct page *page;
+
+    page = gfn_to_page(kvm, gpa >> PAGE_SHIFT);
+    if (page == bad_page)
+        return ERR_PTR(-EINVAL);
+
+    return page;
+}
+
+static void
+xinterface_release(struct kvm_xinterface *intf)
+{

virt/kvm/kvm_main.c static const struct mmu_notifier_ops kvm_mmu_notifier_ops = { · line 988

Quoted 10 lines
virt/kvm/kvm_main.c +10 -0
+    struct kvm *kvm = intf_to_kvm(intf);
+
+    kvm_put_kvm(kvm);
+}
+
+struct kvm_xinterface_ops _kvm_xinterface_ops = {
+    .gpa_to_hva  = xinterface_gpa_to_hva,
+    .gpa_to_page = xinterface_gpa_to_page,
+    .release     = xinterface_release,
+};

How do you deal with locking?

Quoted 2 lines

The mappings (gpa_to_page) are not fixed. They can and do change very often. The interface doesn't seem to attempt to cope with this.

Hmm, well I used to need gpa_to_page() in the older version of vbus that did explicit hypercalls, but I don't actually use it today in v4. I left it in because it seems like it might be useful in general (perhaps for Michael). However, if this ends up being a real problem I suppose we can just drop that vtable entry and let the guy that actually needs it deal with the issues ;) I really only require gpa_to_hva() in the short-term.

That said, I think the assumption that was made when I was using this was that a proper ref for the page was acquired by the gfn_to_page() and dropped by the caller. This was always used in the context of a hypercall/vmexit so presumably the gpa should be considered stable across that call. Is that not true?

Regards,
-Greg

#6 lore raw

Re: [KVM PATCH] KVM: introduce "xinterface" API for external interaction with guests

Quoted 6 lines · Gregory Haskins

That said, I think the assumption that was made when I was using this was that a proper ref for the page was acquired by the gfn_to_page() and dropped by the caller. This was always used in the context of a hypercall/vmexit so presumably the gpa should be considered stable across that call. Is that not true?

If you're in kvm.ko, then yes, that's a safe assumption to make because the guest VCPU cannot run while you are running.

But you're opening this interface to any caller so the VCPU is likely to be running while someone calls this function

Quoted 5 lines

Regards,
-Greg

Signature · 3 lines
Regards,

Anthony Liguori
#7 lore raw

Re: [KVM PATCH] KVM: introduce "xinterface" API for external interaction with guests

In reply to Gregory Haskins
Quoted 3 lines · Gregory Haskins

Background: The original vbus code was tightly integrated with kvm.ko. Avi suggested that we abstract the interfaces such that it could live outside of kvm.

The code is still highly kvm-specific, you would not be able to use it with another hypervisor like lguest or vmware player, right?

Quoted 8 lines

Example usage: QEMU instantiates a guest, and an external module "foo" that desires the ability to interface with the guest (say via open("/dev/foo")). QEMU may then issue a KVM_GET_VMID operation to acquire the u64-based vmid, and pass it to ioctl(foofd, FOO_SET_VMID, &vmid). Upon receipt, the foo module can issue kvm_xinterface_find(vmid) to acquire the proper context. Internally, the struct kvm* and associated struct module* will remain pinned at least until the foo module calls kvm_xinterface_put().

Your approach allows passing the vmid from a process that does not own the kvm context. This looks like an intentional feature, but I can't see what this gains us.

Quoted 4 lines

As a final measure, we link the xinterface code statically into the kernel so that callers are guaranteed a stable interface to kvm_xinterface_find() without implicitly pinning kvm.ko or racing against it.

I also don't understand this. Are you worried about driver modules breaking when an externally-compiled kvm.ko is loaded? The same could be achieved by defining your data structures kvm_xinterface_ops and kvm_xinterface in a kernel header that is not shipped by kvm-kmod but always taken from the kernel headers.
It does not matter if the entry points are build into the kernel or exported from a kvm.ko as long as you define a fixed ABI.

What is the problem with pinning kvm.ko from another module using its features?

Can't you simply provide a function call to lookup the kvm context pointer from the file descriptor to achieve the same functionality?

To take that thought further, maybe the dependency can be turned
around: If every user (pci-uio, virtio-net, ...) exposes a file descriptor based interface to user space, you can have a kvm ioctl to register the object behind that file descriptor with an existing kvm context to associate it with a guest. That would nicely solve the life time questions by pinning the external object for the life time of the kvm context rather than the other way round, and it would be completely separate from kvm in that each such object could be used by other subsystems independent of kvm.

	Arnd <><
#8 lore raw

Re: [KVM PATCH] KVM: introduce "xinterface" API for external interaction with guests

Quoted 10 lines · Arnd Bergmann
Quoted 4 lines · Gregory Haskins

Background: The original vbus code was tightly integrated with kvm.ko. Avi suggested that we abstract the interfaces such that it could live outside of kvm.

The code is still highly kvm-specific, you would not be able to use it with another hypervisor like lguest or vmware player, right?

In its current form, it is kvm specific primarily because it was not a explicit design constraint of mine to support others. However, there is no reason why we could not generalize the interface if that is a desirable trait. Ultimately I would like to have my project support other things like lguest, so this is not a bad idea. Otherwise, someone will invariably be proposing an "lguest_xinterface" next ;)

Quoted 11 lines
Quoted 10 lines

Example usage: QEMU instantiates a guest, and an external module "foo" that desires the ability to interface with the guest (say via open("/dev/foo")). QEMU may then issue a KVM_GET_VMID operation to acquire the u64-based vmid, and pass it to ioctl(foofd, FOO_SET_VMID, &vmid). Upon receipt, the foo module can issue kvm_xinterface_find(vmid) to acquire the proper context. Internally, the struct kvm* and associated struct module* will remain pinned at least until the foo module calls kvm_xinterface_put().

Quoted 3 lines

Your approach allows passing the vmid from a process that does not own the kvm context. This looks like an intentional feature, but I can't see what this gains us.

This work is towards the implementation of lockless-shared-memory subsystems, which includes ring constructs such as virtio-ring,
VJ-netchannels, and vbus-ioq. I find that these designs perform
optimally when you allow two distinct contexts (producer + consumer) to process the ring concurrently, which implies a disparate context from the guest in question. Note that the infrastructure we are discussing does not impose a requirement for the contexts to be unique: it will work equally well from the same or a different process.

For an example of this "producer/consumer" dynamic over shared memory in action, please refer to my previous posting re: "vbus"

http://lkml.org/lkml/2009/4/21/408

I am working on v4 now, and this patch is part of the required support.

Quoted 17 lines
Quoted 8 lines

As a final measure, we link the xinterface code statically into the kernel so that callers are guaranteed a stable interface to kvm_xinterface_find() without implicitly pinning kvm.ko or racing against it.

I also don't understand this. Are you worried about driver modules breaking when an externally-compiled kvm.ko is loaded? The same could be achieved by defining your data structures kvm_xinterface_ops and kvm_xinterface in a kernel header that is not shipped by kvm-kmod but always taken from the kernel headers.
It does not matter if the entry points are build into the kernel or exported from a kvm.ko as long as you define a fixed ABI.

Quoted 3 lines

What is the problem with pinning kvm.ko from another module using its features?

Well, there is always the chance that I am doing something dumb or missing the point ;)

But my rationale was as follows: The problem is that kvm is a little weird in the module ref department: If I were to do it the standard way and link xinterface.o into kvm.o (and have any xinterface_find() users do a tristate+"depends on KVM"), this would work as I believe you are suggesting. That is to say: whenever I loaded "foo.ko", insmod would automatically up the reference of kvm.ko. The issue is that is not quite what I really want ;)

I want to hold the reference to the entire .text chain, which includes kvm.ko + [kvm-intel.ko | kvm-amd.ko]. If you look carefully, the ops->owner that is assigned is actually the arch.ko. In addition, I wanted the kvm.ko lifetime to be associated with the lifetime of its contexts actually in use, not the lifetime of its installed dependencies. Therefore, I did it this way.

But to your point, I suppose the dependency lifetime thing is not a huge deal. I could therefore modify the patch to simply link xinterface.o into kvm.ko and still achieve the primary objective by retaining ops->owner.

Note that if we are going to generalize the interface to support other guests as you may have been suggesting above, it should probably stay statically linked (and perhaps live in ./lib or something)

Quoted 3 lines

Can't you simply provide a function call to lookup the kvm context pointer from the file descriptor to achieve the same functionality?

You mean so have: struct kvm_xinterface *kvm_xinterface_find(int fd)

(instead of creating our own vmid namespace) ?

Or are you suggesting using fget() instead of kvm_xinterface_find()?

Quoted 5 lines

To take that thought further, maybe the dependency can be turned
around: If every user (pci-uio, virtio-net, ...) exposes a file descriptor based interface to user space, you can have a kvm ioctl to register the object behind that file descriptor with an existing kvm context to associate it with a guest.

FWIW: We do that already for the signaling path (see irqfd and ioeventfd in kvm.git). Each side exposes interfaces that accept eventfds, and the fds are passed around that way.

However, for the functions we are talking about now, I don't think it really works well to go the other way. I could be misunderstanding what you mean, though. What I mean is that it's KVM that is providing a service to the other modules (in this case, translating memory pointers), so what would an inverse interface look like for that? And even if you came up with one, it seems to me that its just "6 of one, half-dozen of the other" kind of thing.

Quoted 3 lines

That would
nicely solve the life time questions by pinning the external object for the life time of the kvm context

I suppose that is nice, but note that in practice both objects (the kvm-guest and the "foo" module) are managed by the same entity (i.e. QEMU) and therefore share the same approximate lifetime.

Kind Regards,
-Greg

#9 lore raw

Re: [KVM PATCH] KVM: introduce "xinterface" API for external interaction with guests

Quoted 4 lines · Gregory Haskins

Note that if we are going to generalize the interface to support other guests as you may have been suggesting above, it should probably stay statically linked (and perhaps live in ./lib or something)

More specifically, it can no longer live in kvm.ko. I guess it technically doesn't have to be statically linked, though (e.g. xinterface.ko is fine, too).

Regards,
-Greg

#10 lore raw

Re: [KVM PATCH] KVM: introduce "xinterface" API for external interaction with guests

Quoted 9 lines · Gregory Haskins
Quoted 4 lines · Gregory Haskins

Note that if we are going to generalize the interface to support other guests as you may have been suggesting above, it should probably stay statically linked (and perhaps live in ./lib or something)

More specifically, it can no longer live in kvm.ko. I guess it technically doesn't have to be statically linked, though (e.g. xinterface.ko is fine, too).

Speaking as someone who knows nothing about this, if this is going to be a module and visible in places like lsmod, could you name it something else?

I see "xinterface.ko" and the first thing in my head is "something to do with the X Window System."

How about kvm_xinterface or vguest_xinterface?

Signature · 4 lines
Zan Lynx
[email protected]

"Knowledge is Power.  Power Corrupts.  Study Hard.  Be Evil."
#11 lore raw

Re: [KVM PATCH] KVM: introduce "xinterface" API for external interaction with guests

Quoted 11 lines · Zan Lynx
Quoted 9 lines · Gregory Haskins
Quoted 4 lines · Gregory Haskins

Note that if we are going to generalize the interface to support other guests as you may have been suggesting above, it should probably stay statically linked (and perhaps live in ./lib or something)

More specifically, it can no longer live in kvm.ko. I guess it technically doesn't have to be statically linked, though (e.g. xinterface.ko is fine, too).

Quoted 9 lines

Speaking as someone who knows nothing about this, if this is going to be a module and visible in places like lsmod, could you name it something else?

I see "xinterface.ko" and the first thing in my head is "something to do with the X Window System."

How about kvm_xinterface or vguest_xinterface?

Heh, I totally agree. That was just pseudo-naming, anyway. ;)

If it was going to be generic, I would do something like "virt-xinterface.ko".

Kind Regards,
-Greg

#12 lore raw

Re: [KVM PATCH] KVM: introduce "xinterface" API for external interaction with guests

In reply to Gregory Haskins
Quoted 15 lines · Gregory Haskins
Quoted 3 lines · Arnd Bergmann

Your approach allows passing the vmid from a process that does not own the kvm context. This looks like an intentional feature, but I can't see what this gains us.

This work is towards the implementation of lockless-shared-memory subsystems, which includes ring constructs such as virtio-ring,
VJ-netchannels, and vbus-ioq. I find that these designs perform
optimally when you allow two distinct contexts (producer + consumer) to process the ring concurrently, which implies a disparate context from the guest in question. Note that the infrastructure we are discussing does not impose a requirement for the contexts to be unique: it will work equally well from the same or a different process.

Quoted 6 lines

For an example of this "producer/consumer" dynamic over shared memory in action, please refer to my previous posting re: "vbus"

http://lkml.org/lkml/2009/4/21/408

I am working on v4 now, and this patch is part of the required support.

Ok. I can see how your approach gives you more flexibility in this regard, but it does not seem critical.

Quoted 3 lines

But to your point, I suppose the dependency lifetime thing is not a huge deal. I could therefore modify the patch to simply link xinterface.o into kvm.ko and still achieve the primary objective by retaining ops->owner.

Right. And even if it's a separate module, holding an extra reference on kvm.ko will not cause any harm.

Quoted 8 lines
Quoted 3 lines

Can't you simply provide a function call to lookup the kvm context pointer from the file descriptor to achieve the same functionality?

You mean so have: struct kvm_xinterface *kvm_xinterface_find(int fd)

(instead of creating our own vmid namespace) ?

Or are you suggesting using fget() instead of kvm_xinterface_find()?

I guess they are roughly equivalent. Either you pass a fd to kvm_xinterface_find, or pass the struct file pointer you get from fget. The latter is probably more convenient because it allows you to pass around the struct file in kernel contexts that don't have that file descriptor open.

Quoted 10 lines
Quoted 5 lines

To take that thought further, maybe the dependency can be turned
around: If every user (pci-uio, virtio-net, ...) exposes a file descriptor based interface to user space, you can have a kvm ioctl to register the object behind that file descriptor with an existing kvm context to associate it with a guest.

FWIW: We do that already for the signaling path (see irqfd and ioeventfd in kvm.git). Each side exposes interfaces that accept eventfds, and the fds are passed around that way.

Quoted 7 lines

However, for the functions we are talking about now, I don't think it really works well to go the other way. I could be misunderstanding what you mean, though. What I mean is that it's KVM that is providing a service to the other modules (in this case, translating memory pointers), so what would an inverse interface look like for that? And even if you came up with one, it seems to me that its just "6 of one, half-dozen of the other" kind of thing.

I mean something like

int kvm_ioctl_register_service(struct file *filp, unsigned long arg)

{
	struct file *service = fget(arg);
	struct kvm *kvm = filp->private_data;

	if (!service->f_ops->new_xinterface_register)
		return -EINVAL;

	return service->f_ops->new_xinterface_register(service, (void*)kvm,
				&kvm_xinterface_ops);
}

This would assume that we define a new file_operation specifically for this, which would simplify the code, but there are other ways to achieve the same. It would even mean that you don't need any static code as an interface layer.

	Arnd <><
#13 lore raw

Re: [KVM PATCH] KVM: introduce "xinterface" API for external interaction with guests

Quoted 22 lines · Arnd Bergmann
Quoted 20 lines · Gregory Haskins
Quoted 4 lines · Arnd Bergmann

Your approach allows passing the vmid from a process that does not own the kvm context. This looks like an intentional feature, but I can't see what this gains us.

This work is towards the implementation of lockless-shared-memory subsystems, which includes ring constructs such as virtio-ring,
VJ-netchannels, and vbus-ioq. I find that these designs perform
optimally when you allow two distinct contexts (producer + consumer) to process the ring concurrently, which implies a disparate context from the guest in question. Note that the infrastructure we are discussing does not impose a requirement for the contexts to be unique: it will work equally well from the same or a different process.

For an example of this "producer/consumer" dynamic over shared memory in action, please refer to my previous posting re: "vbus"

Quoted 8 lines
Quoted 4 lines

http://lkml.org/lkml/2009/4/21/408

I am working on v4 now, and this patch is part of the required support.

Ok. I can see how your approach gives you more flexibility in this regard, but it does not seem critical.

Yeah, and I think I missed your point the first time around. I thought you were asking about how the resulting memory API was used, but now I see you were referring to the scope of the vmid namespace (vs file-descriptors).

On that topic, yes the vmid implementation here differs from file-descriptors in the sense that the namespace is global to the kernel, instead of per-process. And yes, I also agree with you that this is not critical to the design, per se. For instance, the use cases I have in mind would work fine with the per-task fd namespace as well since I will be within the same QEMU instance.

So ultimately, I think that means the fd idea you presented would work equally well.

Quoted 9 lines
Quoted 5 lines

But to your point, I suppose the dependency lifetime thing is not a huge deal. I could therefore modify the patch to simply link xinterface.o into kvm.ko and still achieve the primary objective by retaining ops->owner.

Right. And even if it's a separate module, holding an extra reference on kvm.ko will not cause any harm.

Yep, agreed.

Quoted 9 lines
Quoted 9 lines
Quoted 5 lines

Can't you simply provide a function call to lookup the kvm context pointer from the file descriptor to achieve the same functionality?

You mean so have: struct kvm_xinterface *kvm_xinterface_find(int fd)

(instead of creating our own vmid namespace) ?

Quoted 9 lines
Quoted 2 lines

Or are you suggesting using fget() instead of kvm_xinterface_find()?

I guess they are roughly equivalent. Either you pass a fd to kvm_xinterface_find, or pass the struct file pointer you get from fget. The latter is probably more convenient because it allows you to pass around the struct file in kernel contexts that don't have that file descriptor open.

Interesting. I like it.

Quoted 34 lines
Quoted 11 lines
Quoted 7 lines

To take that thought further, maybe the dependency can be turned
around: If every user (pci-uio, virtio-net, ...) exposes a file descriptor based interface to user space, you can have a kvm ioctl to register the object behind that file descriptor with an existing kvm context to associate it with a guest.

FWIW: We do that already for the signaling path (see irqfd and ioeventfd in kvm.git). Each side exposes interfaces that accept eventfds, and the fds are passed around that way.

Quoted 8 lines

However, for the functions we are talking about now, I don't think it really works well to go the other way. I could be misunderstanding what you mean, though. What I mean is that it's KVM that is providing a service to the other modules (in this case, translating memory pointers), so what would an inverse interface look like for that? And even if you came up with one, it seems to me that its just "6 of one, half-dozen of the other" kind of thing.

I mean something like

int kvm_ioctl_register_service(struct file *filp, unsigned long arg)

{
	struct file *service = fget(arg);
	struct kvm *kvm = filp->private_data;

	if (!service->f_ops->new_xinterface_register)
		return -EINVAL;

	return service->f_ops->new_xinterface_register(service, (void*)kvm,
				&kvm_xinterface_ops);
}
Quoted 4 lines

This would assume that we define a new file_operation specifically for this, which would simplify the code, but there are other ways to achieve the same. It would even mean that you don't need any static code as an interface layer.

I suspect I will have a much harder time getting that type of modification accepted in mainline ;)

I think I will go with your suggestion for the fd/file interface, tho. I can get rid of the rbtree logic and re-use the lookup via fget, which is a nice win.

Thanks Arnd!
-Greg