iosignalfd
v9 cover iosignalfd
(Applies to kvm.git/master:c5b13264e)
This is v9 of the series. For more details, please see the header to patch 2/2.
This series has been tested against the kvm-eventfd unit test, and appears to be functioning properly. You can download this test here:
ftp://ftp.novell.com/dev/ghaskins/kvm-eventfd.tar.bz2
(Note: unit test has been updated to accomodate new feature-set)
Please consider for inclusion to kvm.git
[
Changelog:
v9:
*) Rebased onto Michael's new iodev locking scheme *) Removed group+item nesting in favor of using iodev facility *) Removed iodev-limit patch since we no longer create
our own devices. The limit feature itself may be useful but it is now out of scope from iosignalfd and thus should be addressed separately.
*) Rebased to kvm.git/master:c5b13264e
v8:
*) Addressed Avi's review comments:
*) Simplified the unregister_dev logic in patch 1/3 *) Implemented a per-vm io-device limit (patch 2/3) *) Removed spurious whitespace hunk
*) changed the data-match from a void* to a u64 *) check group-length violations before wildcarding
v7:
*) Implemented a resource limit (CONFIG_KVM_MAX_IOSIGNALFD_ITEMS)
to limit malicious/broken userspace from consuming arbitrary kernel memory.
*) Rebased to kvm.git/master:c27b64a0, which already includes
Marcelo's irq-lock rework.
v6:
*) Removed "FIXME?" comment on choice over RCU vs SRCU after
discussion/numbers from Paul. I think RCU is fine to use for now based on the conversation. We can always convert it later if need be.
*) Fixed the "group" free path to eliminate an RCU related race *) Fixed a memory/eventfd leak on shutdown for any iosignalfd's
which were still active at the time the guest shuts down.
*) Beefed up comments
*) Rebased to kvm.git/master:0281e88f + irq locking rework and
verified that kvm-eventfd unit test still passes.
v5:
*) Removed "cookie" field, which was a misunderstanding on my
part on what Avi wanted for a data-match feature
*) Added a new "trigger" data-match feature which I think is
much closer to what we need.
*) We retain the dev_count field in the io_bus infrastructure
and instead back-fill the array on removal.
*) Various minor cleanups
*) Rebased to kvm.git/master:25deed73
v4:
*) Fixed a bug in the original 2/4 where the PIT failure case
would potentially leave the io_bus components registered.
*) Condensed the v3 2/4 and 3/4 into one patch (2/2) since
the patches became interdependent with the fix described above
*) Rebased to kvm.git/master:74dfca0a
v3:
*) fixed patch 2/4 to handle error cases instead of BUG_ON *) implemented same HAVE_EVENTFD protection mechanism as
irqfd to prevent compilation errors on unsupported arches
*) completed testing
*) rebased to kvm.git/master:7391a6d5
v2:
*) added optional data-matching capability (via cookie field) *) changed name from iofd to iosignalfd
*) added io_bus unregister function
*) implemented deassign feature
v1:
*) original release (integrated into irqfd v7 series as "iofd")
]
---
Gregory Haskins (2):
KVM: add iosignalfd support
KVM: make io_bus interface more robust
arch/x86/kvm/i8254.c | 22 +++- arch/x86/kvm/i8259.c | 9 + arch/x86/kvm/x86.c | 1 include/linux/kvm.h | 15 ++ include/linux/kvm_host.h | 20 ++- virt/kvm/coalesced_mmio.c | 8 + virt/kvm/eventfd.c | 280 +++++++++++++++++++++++++++++++++++++++++++++ virt/kvm/ioapic.c | 8 + virt/kvm/kvm_main.c | 52 +++++++- 9 files changed, 396 insertions(+), 19 deletions(-)
Signature · 1 line
Signature
PATCH v9 1/2 KVM: make io_bus interface more robust
Today kvm_io_bus_regsiter_dev() returns void and will internally BUG_ON if it fails. We want to create dynamic MMIO/PIO entries driven from userspace later in the series, so we need to enhance the code to be more robust with the following changes:
1) Add a return value to the registration function
2) Fix up all the callsites to check the return code, handle any failures, and percolate the error up to the caller.
3) Add an unregister function that collapses holes in the array
---
arch/x86/kvm/i8254.c | 22 ++++++++++++++++++++-- arch/x86/kvm/i8259.c | 9 ++++++++- include/linux/kvm_host.h | 10 +++++++--- virt/kvm/coalesced_mmio.c | 8 ++++++-- virt/kvm/ioapic.c | 8 ++++++-- virt/kvm/kvm_main.c | 41 ++++++++++++++++++++++++++++++++++++----- 6 files changed, 83 insertions(+), 15 deletions(-)
arch/x86/kvm/i8254.c +20 -2
@@ -591,6 +591,7 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags) {struct kvm_pit *pit;struct kvm_kpit_state *pit_state; +int ret; pit =kzalloc (sizeof (struct kvm_pit ),GFP_KERNEL );if (!pit)
@@ -625,14 +626,31 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)kvm_register_irq_mask_notifier (kvm,0 , &pit->mask_notifier);kvm_iodevice_init (&pit->dev, &pit_dev_ops); -__kvm_io_bus_register_dev (&kvm->pio_bus, &pit->dev); + ret =__kvm_io_bus_register_dev (&kvm->pio_bus, &pit->dev); +if (ret <0 ) + goto fail;if (flags &KVM_PIT_SPEAKER_DUMMY ) {kvm_iodevice_init (&pit->speaker_dev, &speaker_dev_ops); -__kvm_io_bus_register_dev (&kvm->pio_bus, &pit->speaker_dev); + ret =__kvm_io_bus_register_dev (&kvm->pio_bus, + &pit->speaker_dev); +if (ret <0 ) + goto fail; }return pit; + +fail: +if (flags &KVM_PIT_SPEAKER_DUMMY ) +__kvm_io_bus_unregister_dev (&kvm->pio_bus, &pit->speaker_dev); + +__kvm_io_bus_unregister_dev (&kvm->pio_bus, &pit->dev); + +if (pit->irq_source_id >=0 ) +kvm_free_irq_source_id (kvm, pit->irq_source_id); + +kfree (pit); +return NULL ; }void kvm_free_pit (struct kvm *kvm)
arch/x86/kvm/i8259.c +8 -1
@@ -536,6 +536,8 @@ static const struct kvm_io_device_ops picdev_ops = {struct kvm_pic *kvm_create_pic (struct kvm *kvm) {struct kvm_pic *s; +int ret; + s =kzalloc (sizeof (struct kvm_pic ),GFP_KERNEL );if (!s)return NULL ;
@@ -552,6 +554,11 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)* Initialize PIO device */ kvm_iodevice_init (&s->dev, &picdev_ops); -kvm_io_bus_register_dev (kvm, &kvm->pio_bus, &s->dev); + ret =kvm_io_bus_register_dev (kvm, &kvm->pio_bus, &s->dev); +if (ret <0 ) { +kfree (s); +return NULL ; + } +return s; }
include/linux/kvm_host.h +7 -3
@@ -64,10 +64,14 @@ int kvm_io_bus_write(struct kvm_io_bus *bus, gpa_t addr, int len, const void *val);int kvm_io_bus_read (struct kvm_io_bus *bus,gpa_t addr,int len,void *val); -void __kvm_io_bus_register_dev (struct kvm_io_bus *bus, +int __kvm_io_bus_register_dev (struct kvm_io_bus *bus, +struct kvm_io_device *dev); +int kvm_io_bus_register_dev (struct kvm *kvm,struct kvm_io_bus *bus, +struct kvm_io_device *dev); +void __kvm_io_bus_unregister_dev (struct kvm_io_bus *bus, +struct kvm_io_device *dev); +void kvm_io_bus_unregister_dev (struct kvm *kvm,struct kvm_io_bus *bus,struct kvm_io_device *dev); -void kvm_io_bus_register_dev (struct kvm *kvm,struct kvm_io_bus *bus, -struct kvm_io_device *dev);struct kvm_vcpu {struct kvm *kvm;
virt/kvm/coalesced_mmio.c +6 -2
@@ -92,6 +92,7 @@ static const struct kvm_io_device_ops coalesced_mmio_ops = {int kvm_coalesced_mmio_init (struct kvm *kvm) {struct kvm_coalesced_mmio_dev *dev; +int ret; dev =kzalloc (sizeof (struct kvm_coalesced_mmio_dev ),GFP_KERNEL );if (!dev)
@@ -100,9 +101,12 @@ int kvm_coalesced_mmio_init(struct kvm *kvm)kvm_iodevice_init (&dev->dev, &coalesced_mmio_ops); dev->kvm = kvm; kvm->coalesced_mmio_dev = dev; -kvm_io_bus_register_dev (kvm, &kvm->mmio_bus, &dev->dev); -return 0 ; + ret =kvm_io_bus_register_dev (kvm, &kvm->mmio_bus, &dev->dev); +if (ret <0 ) +kfree (dev); + +return ret; } int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm,
virt/kvm/ioapic.c +6 -2
@@ -340,6 +340,7 @@ static const struct kvm_io_device_ops ioapic_mmio_ops = {int kvm_ioapic_init (struct kvm *kvm) {struct kvm_ioapic *ioapic; +int ret; ioapic =kzalloc (sizeof (struct kvm_ioapic ),GFP_KERNEL );if (!ioapic)
@@ -348,7 +349,10 @@ int kvm_ioapic_init(struct kvm *kvm)kvm_ioapic_reset (ioapic);kvm_iodevice_init (&ioapic->dev, &ioapic_mmio_ops); ioapic->kvm = kvm; -kvm_io_bus_register_dev (kvm, &kvm->mmio_bus, &ioapic->dev); -return 0 ; + ret =kvm_io_bus_register_dev (kvm, &kvm->mmio_bus, &ioapic->dev); +if (ret <0 ) +kfree (ioapic); + +return ret; }
virt/kvm/kvm_main.c +36 -5
57 lines not on this page · raw message
Re: [KVM PATCH v9 1/2] KVM: make io_bus interface more robust
Looks good to me. One thing that's kind of ugly is the cleanup in i8254, see below. And a couple of other style comments.
Quoted 48 lines · Gregory Haskins
Today
kvm_io_bus_regsiter_dev()returns void and will internallyBUG_ONif it fails. We want to create dynamic MMIO/PIO entries driven from userspace later in the series, so we need to enhance the code to be more robust with the following changes:1) Add a return value to the registration function
2) Fix up all the callsites to check the return code, handle any failures, and percolate the error up to the caller.
3) Add an unregister function that collapses holes in the arraySigned-off-by Gregory Haskins <[email protected]>---
arch/x86/kvm/i8254.c | 22 ++++++++++++++++++++-- arch/x86/kvm/i8259.c | 9 ++++++++- include/linux/kvm_host.h | 10 +++++++--- virt/kvm/coalesced_mmio.c | 8 ++++++-- virt/kvm/ioapic.c | 8 ++++++-- virt/kvm/kvm_main.c | 41 ++++++++++++++++++++++++++++++++++++----- 6 files changed, 83 insertions(+), 15 deletions(-)arch/x86/kvm/i8254.c +7
-2@@ -591,6 +591,7 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags) {struct kvm_pit *pit;struct kvm_kpit_state *pit_state; +int ret; pit =kzalloc (sizeof (struct kvm_pit ),GFP_KERNEL );if (!pit)@@ -625,14 +626,31 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)kvm_register_irq_mask_notifier (kvm,0 , &pit->mask_notifier);kvm_iodevice_init (&pit->dev, &pit_dev_ops); -__kvm_io_bus_register_dev (&kvm->pio_bus, &pit->dev); + ret =__kvm_io_bus_register_dev (&kvm->pio_bus, &pit->dev); +if (ret <0 ) + goto fail;if (flags &KVM_PIT_SPEAKER_DUMMY ) {kvm_iodevice_init (&pit->speaker_dev, &speaker_dev_ops); -__kvm_io_bus_register_dev (&kvm->pio_bus, &pit->speaker_dev); + ret =__kvm_io_bus_register_dev (&kvm->pio_bus, + &pit->speaker_dev); +if (ret <0 )
arch/x86/kvm/i8254.c struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags) · line 647
Quoted 10 lines
arch/x86/kvm/i8254.c +7
-0+ goto fail; }return pit; + +fail: +if (flags &KVM_PIT_SPEAKER_DUMMY ) +__kvm_io_bus_unregister_dev (&kvm->pio_bus, &pit->speaker_dev); + +__kvm_io_bus_unregister_dev (&kvm->pio_bus, &pit->dev);
The above works because we scan the whole array; so it's safe to call unregister on a device that we didn't register, and even on a device we didn't init. But IMO it's cleaner not to assume this and do cleanup properly. No?
Quoted 23 lines
arch/x86/kvm/i8254.c +6
-0+ +if (pit->irq_source_id >=0 ) +kvm_free_irq_source_id (kvm, pit->irq_source_id); + +kfree (pit); +return NULL ; }void kvm_free_pit (struct kvm *kvm)arch/x86/kvm/i8259.c +2
-0@@ -536,6 +536,8 @@ static const struct kvm_io_device_ops picdev_ops = {struct kvm_pic *kvm_create_pic (struct kvm *kvm) {struct kvm_pic *s; +int ret; + s =kzalloc (sizeof (struct kvm_pic ),GFP_KERNEL );if (!s)return NULL ;
arch/x86/kvm/i8259.c struct kvm_pic *kvm_create_pic(struct kvm *kvm) · line 558
Quoted 6 lines
arch/x86/kvm/i8259.c +2
-1@@ -552,6 +554,11 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)* Initialize PIO device */ kvm_iodevice_init (&s->dev, &picdev_ops); -kvm_io_bus_register_dev (kvm, &kvm->pio_bus, &s->dev); + ret =kvm_io_bus_register_dev (kvm, &kvm->pio_bus, &s->dev); +if (ret <0 ) {
I thought the function returns 0 on success?
If so can we just if (ret) all over?
arch/x86/kvm/i8259.c struct kvm_pic *kvm_create_pic(struct kvm *kvm) · line 562
Quoted 4 lines
arch/x86/kvm/i8259.c +4
-0+kfree (s); +return NULL ; + } +
kill empty line
Quoted 37 lines
arch/x86/kvm/i8259.c +0
-0return s; }include/linux/kvm_host.h +7
-3@@ -64,10 +64,14 @@ int kvm_io_bus_write(struct kvm_io_bus *bus, gpa_t addr, int len, const void *val);int kvm_io_bus_read (struct kvm_io_bus *bus,gpa_t addr,int len,void *val); -void __kvm_io_bus_register_dev (struct kvm_io_bus *bus, +int __kvm_io_bus_register_dev (struct kvm_io_bus *bus, +struct kvm_io_device *dev); +int kvm_io_bus_register_dev (struct kvm *kvm,struct kvm_io_bus *bus, +struct kvm_io_device *dev); +void __kvm_io_bus_unregister_dev (struct kvm_io_bus *bus, +struct kvm_io_device *dev); +void kvm_io_bus_unregister_dev (struct kvm *kvm,struct kvm_io_bus *bus,struct kvm_io_device *dev); -void kvm_io_bus_register_dev (struct kvm *kvm,struct kvm_io_bus *bus, -struct kvm_io_device *dev);struct kvm_vcpu {struct kvm *kvm;virt/kvm/coalesced_mmio.c +1
-0@@ -92,6 +92,7 @@ static const struct kvm_io_device_ops coalesced_mmio_ops = {int kvm_coalesced_mmio_init (struct kvm *kvm) {struct kvm_coalesced_mmio_dev *dev; +int ret; dev =kzalloc (sizeof (struct kvm_coalesced_mmio_dev ),GFP_KERNEL );if (!dev)
virt/kvm/coalesced_mmio.c int kvm_coalesced_mmio_init(struct kvm *kvm) · line 108
Quoted 10 lines
virt/kvm/coalesced_mmio.c +4
-2@@ -100,9 +101,12 @@ int kvm_coalesced_mmio_init(struct kvm *kvm)kvm_iodevice_init (&dev->dev, &coalesced_mmio_ops); dev->kvm = kvm; kvm->coalesced_mmio_dev = dev; -kvm_io_bus_register_dev (kvm, &kvm->mmio_bus, &dev->dev); -return 0 ; + ret =kvm_io_bus_register_dev (kvm, &kvm->mmio_bus, &dev->dev); +if (ret <0 ) +kfree (dev); +
kill empty line
Quoted 17 lines
virt/kvm/coalesced_mmio.c +1
-0+return ret; } int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm,virt/kvm/ioapic.c +1
-0@@ -340,6 +340,7 @@ static const struct kvm_io_device_ops ioapic_mmio_ops = {int kvm_ioapic_init (struct kvm *kvm) {struct kvm_ioapic *ioapic; +int ret; ioapic =kzalloc (sizeof (struct kvm_ioapic ),GFP_KERNEL );if (!ioapic)
virt/kvm/ioapic.c int kvm_ioapic_init(struct kvm *kvm) · line 354
Quoted 8 lines
virt/kvm/ioapic.c +3
-2@@ -348,7 +349,10 @@ int kvm_ioapic_init(struct kvm *kvm)kvm_ioapic_reset (ioapic);kvm_iodevice_init (&ioapic->dev, &ioapic_mmio_ops); ioapic->kvm = kvm; -kvm_io_bus_register_dev (kvm, &kvm->mmio_bus, &ioapic->dev); -return 0 ; + ret =kvm_io_bus_register_dev (kvm, &kvm->mmio_bus, &ioapic->dev); +if (ret <0 ) +kfree (ioapic);
kill empty line
Quoted 9 lines
virt/kvm/ioapic.c +2
-0+ +return ret; }virt/kvm/kvm_main.c +0
-0
virt/kvm/kvm_main.c int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) · line 2537
Quoted 6 lines
virt/kvm/kvm_main.c +1
-1@@ -2533,21 +2533,52 @@ int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val)return -EOPNOTSUPP ; } -void kvm_io_bus_register_dev (struct kvm *kvm,struct kvm_io_bus *bus, +int kvm_io_bus_register_dev (struct kvm *kvm,struct kvm_io_bus *bus,struct kvm_io_device *dev)
Let's document return value?
virt/kvm/kvm_main.c int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) · line 2543
Quoted 7 lines
virt/kvm/kvm_main.c +3
-1{ +int ret; +down_write (&kvm->slots_lock); -__kvm_io_bus_register_dev (bus, dev); + ret =__kvm_io_bus_register_dev (bus, dev);up_write (&kvm->slots_lock);
kill empty line? this one is kind of iffy
virt/kvm/kvm_main.c int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) · line 2552
Quoted 12 lines
virt/kvm/kvm_main.c +5
-3+ +return ret; }/* An unlocked version. Caller must have write lock on slots_lock. */ -void __kvm_io_bus_register_dev (struct kvm_io_bus *bus, -struct kvm_io_device *dev) +int __kvm_io_bus_register_dev (struct kvm_io_bus *bus, +struct kvm_io_device *dev) { -BUG_ON (bus->dev_count > (NR_IOBUS_DEVS -1 )); +if (bus->dev_count > (NR_IOBUS_DEVS -1 ))
as long as we are touching this: (NR_IOBUS_DEVS-1) -> NR_IOBUS_DEVS - 1?
virt/kvm/kvm_main.c int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) · line 2555
Quoted 3 lines
virt/kvm/kvm_main.c +1
-0+return -ENOSPC ; bus->devs[bus->dev_count++] = dev;
kill empty line
Quoted 11 lines
virt/kvm/kvm_main.c +11
-0+ +return 0 ; +} + +void kvm_io_bus_unregister_dev (struct kvm *kvm, +struct kvm_io_bus *bus, +struct kvm_io_device *dev) +{ +down_write (&kvm->slots_lock); +__kvm_io_bus_unregister_dev (bus, dev); +up_write (&kvm->slots_lock);
virt/kvm/kvm_main.c int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) · line 2576
Quoted 10 lines
virt/kvm/kvm_main.c +10
-0+} + +/* An unlocked version. Caller must have write lock on slots_lock. */ +void __kvm_io_bus_unregister_dev (struct kvm_io_bus *bus, +struct kvm_io_device *dev) +{ +int i; + +for (i =0 ; i < bus->dev_count; i++) { +
kill empty line
virt/kvm/kvm_main.c int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) · line 2581
Quoted 5 lines
virt/kvm/kvm_main.c +5
-0+if (bus->devs[i] == dev) { + bus->devs[i] = bus->devs[--bus->dev_count]; +break ; + } + }
no {} around single statement
Quoted 3 lines
virt/kvm/kvm_main.c +0
-0}static struct notifier_block kvm_cpu_notifier = {
Re: [KVM PATCH v9 1/2] KVM: make io_bus interface more robust
Quoted 56 lines · Michael S. Tsirkin
Looks good to me. One thing that's kind of ugly is the cleanup in i8254, see below. And a couple of other style comments.
Quoted 51 lines · Gregory Haskins
Today
kvm_io_bus_regsiter_dev()returns void and will internallyBUG_ONif it fails. We want to create dynamic MMIO/PIO entries driven from userspace later in the series, so we need to enhance the code to be more robust with the following changes:1) Add a return value to the registration function
2) Fix up all the callsites to check the return code, handle any failures, and percolate the error up to the caller.
3) Add an unregister function that collapses holes in the arraySigned-off-by Gregory Haskins <[email protected]>---
arch/x86/kvm/i8254.c | 22 ++++++++++++++++++++-- arch/x86/kvm/i8259.c | 9 ++++++++- include/linux/kvm_host.h | 10 +++++++--- virt/kvm/coalesced_mmio.c | 8 ++++++-- virt/kvm/ioapic.c | 8 ++++++-- virt/kvm/kvm_main.c | 41 ++++++++++++++++++++++++++++++++++++----- 6 files changed, 83 insertions(+), 15 deletions(-)arch/x86/kvm/i8254.c +8
-2@@ -591,6 +591,7 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags) {struct kvm_pit *pit;struct kvm_kpit_state *pit_state; +int ret; pit =kzalloc (sizeof (struct kvm_pit ),GFP_KERNEL );if (!pit)@@ -625,14 +626,31 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags)kvm_register_irq_mask_notifier (kvm,0 , &pit->mask_notifier);kvm_iodevice_init (&pit->dev, &pit_dev_ops); -__kvm_io_bus_register_dev (&kvm->pio_bus, &pit->dev); + ret =__kvm_io_bus_register_dev (&kvm->pio_bus, &pit->dev); +if (ret <0 ) + goto fail;if (flags &KVM_PIT_SPEAKER_DUMMY ) {kvm_iodevice_init (&pit->speaker_dev, &speaker_dev_ops); -__kvm_io_bus_register_dev (&kvm->pio_bus, &pit->speaker_dev); + ret =__kvm_io_bus_register_dev (&kvm->pio_bus, + &pit->speaker_dev); +if (ret <0 ) + goto fail; }
Quoted 14 lines
arch/x86/kvm/i8254.c struct kvm_pit *kvm_create_pit(struct kvm *kvm, u32 flags) · line 655
Quoted 8 lines
arch/x86/kvm/i8254.c +6
-0return pit; + +fail: +if (flags &KVM_PIT_SPEAKER_DUMMY ) +__kvm_io_bus_unregister_dev (&kvm->pio_bus, &pit->speaker_dev); + +__kvm_io_bus_unregister_dev (&kvm->pio_bus, &pit->dev);The above works because we scan the whole array; so it's safe to call unregister on a device that we didn't register, and even on a device we didn't init. But IMO it's cleaner not to assume this and do cleanup properly. No?
Ack (this was a left-over from when the code was structured differently)
Quoted 9 lines
Quoted 9 lines
arch/x86/kvm/i8254.c +6
-0+ +if (pit->irq_source_id >=0 ) +kvm_free_irq_source_id (kvm, pit->irq_source_id); + +kfree (pit); +return NULL ; }
Quoted 12 lines
arch/x86/kvm/i8259.c static const struct kvm_io_device_ops picdev_ops = { · line 541
Quoted 12 lines
void
kvm_free_pit(struct kvm *kvm)arch/x86/kvm/i8259.c +2
-0@@ -536,6 +536,8 @@ static const struct kvm_io_device_ops picdev_ops = {struct kvm_pic *kvm_create_pic (struct kvm *kvm) {struct kvm_pic *s; +int ret; +
[A]
Quoted 6 lines
Quoted 6 lines
arch/x86/kvm/i8259.c +0
-0s =kzalloc (sizeof (struct kvm_pic ),GFP_KERNEL );if (!s)arch/x86/kvm/i8259.c +0
-0return NULL ;@@ -552,6 +554,11 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)* Initialize PIO device */
Quoted 10 lines
arch/x86/kvm/i8259.c struct kvm_pic *kvm_create_pic(struct kvm *kvm)
Quoted 5 lines
arch/x86/kvm/i8259.c +2
-1kvm_iodevice_init (&s->dev, &picdev_ops); -kvm_io_bus_register_dev (kvm, &kvm->pio_bus, &s->dev); + ret =kvm_io_bus_register_dev (kvm, &kvm->pio_bus, &s->dev); +if (ret <0 ) {I thought the function returns 0 on success?
If so can we just if (ret) all over?
I guess, but what does that churn buy us?
Quoted 8 lines
arch/x86/kvm/i8259.c struct kvm_pic *kvm_create_pic(struct kvm *kvm)
Quoted 5 lines
arch/x86/kvm/i8259.c +4
-0+kfree (s); +return NULL ; + } +kill empty line
Are they docking your pay for every whitespace that goes into KVM or something ;)
These patches pass checkpatch.pl and I happen to like the extra whitespace for readability. I agree that a random isolated whitespace hunk, or double whitespace in a row are probably inadvertent and should be pointed out. But these little one liners in the middle of code I generally do on purpose (for instance, [A]). I suppose its personal preference either way, so I guess unless Avi objects lets just each have our own style in that regard.
Quoted 43 lines
Quoted 43 lines
arch/x86/kvm/i8259.c +0
-0return s; }include/linux/kvm_host.h +7
-3@@ -64,10 +64,14 @@ int kvm_io_bus_write(struct kvm_io_bus *bus, gpa_t addr, int len, const void *val);int kvm_io_bus_read (struct kvm_io_bus *bus,gpa_t addr,int len,void *val); -void __kvm_io_bus_register_dev (struct kvm_io_bus *bus, +int __kvm_io_bus_register_dev (struct kvm_io_bus *bus, +struct kvm_io_device *dev); +int kvm_io_bus_register_dev (struct kvm *kvm,struct kvm_io_bus *bus, +struct kvm_io_device *dev); +void __kvm_io_bus_unregister_dev (struct kvm_io_bus *bus, +struct kvm_io_device *dev); +void kvm_io_bus_unregister_dev (struct kvm *kvm,struct kvm_io_bus *bus,struct kvm_io_device *dev); -void kvm_io_bus_register_dev (struct kvm *kvm,struct kvm_io_bus *bus, -struct kvm_io_device *dev);struct kvm_vcpu {struct kvm *kvm;virt/kvm/coalesced_mmio.c +1
-1@@ -92,6 +92,7 @@ static const struct kvm_io_device_ops coalesced_mmio_ops = {int kvm_coalesced_mmio_init (struct kvm *kvm) {struct kvm_coalesced_mmio_dev *dev; +int ret; dev =kzalloc (sizeof (struct kvm_coalesced_mmio_dev ),GFP_KERNEL );if (!dev)@@ -100,9 +101,12 @@ int kvm_coalesced_mmio_init(struct kvm *kvm)kvm_iodevice_init (&dev->dev, &coalesced_mmio_ops); dev->kvm = kvm; kvm->coalesced_mmio_dev = dev; -kvm_io_bus_register_dev (kvm, &kvm->mmio_bus, &dev->dev);
Quoted 2 lines
virt/kvm/coalesced_mmio.c int kvm_coalesced_mmio_init(struct kvm *kvm) · line 105
Quoted 2 lines
virt/kvm/coalesced_mmio.c +0
-1-return 0 ;
[B]
Quoted 8 lines
virt/kvm/coalesced_mmio.c int kvm_coalesced_mmio_init(struct kvm *kvm) · line 111
Quoted 5 lines
virt/kvm/coalesced_mmio.c +4
-0+ ret =kvm_io_bus_register_dev (kvm, &kvm->mmio_bus, &dev->dev); +if (ret <0 ) +kfree (dev); +kill empty line
Why do you object here especially when there is precedence with something like the space before the return with [B]? I think big mono-blocks of code are ugly and harder to read, personally.
Quoted 15 lines
Quoted 15 lines
virt/kvm/coalesced_mmio.c +1
-0+return ret; }int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm,
virt/kvm/ioapic.c +1
-0@@ -340,6 +340,7 @@ static const struct kvm_io_device_ops ioapic_mmio_ops = {int kvm_ioapic_init (struct kvm *kvm) {struct kvm_ioapic *ioapic; +int ret;
Quoted 15 lines
virt/kvm/ioapic.c int kvm_ioapic_init(struct kvm *kvm) · line 355
Quoted 12 lines
virt/kvm/ioapic.c +3
-2ioapic =kzalloc (sizeof (struct kvm_ioapic ),GFP_KERNEL );if (!ioapic)@@ -348,7 +349,10 @@ int kvm_ioapic_init(struct kvm *kvm)kvm_ioapic_reset (ioapic);kvm_iodevice_init (&ioapic->dev, &ioapic_mmio_ops); ioapic->kvm = kvm; -kvm_io_bus_register_dev (kvm, &kvm->mmio_bus, &ioapic->dev); -return 0 ; + ret =kvm_io_bus_register_dev (kvm, &kvm->mmio_bus, &ioapic->dev); +if (ret <0 ) +kfree (ioapic);kill empty line
Ditto for all of these.
Quoted 13 lines
Quoted 13 lines
virt/kvm/ioapic.c +2
-0+ +return ret; }virt/kvm/kvm_main.c +0
-0@@ -2533,21 +2533,52 @@ int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val)return -EOPNOTSUPP ; }
Quoted 7 lines
virt/kvm/kvm_main.c int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) · line 2547
Quoted 4 lines
virt/kvm/kvm_main.c +1
-1-void kvm_io_bus_register_dev (struct kvm *kvm,struct kvm_io_bus *bus, +int kvm_io_bus_register_dev (struct kvm *kvm,struct kvm_io_bus *bus,struct kvm_io_device *dev)Let's document return value?
Ok
Quoted 79 lines
virt/kvm/kvm_main.c int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) · line 2547
Quoted 9 lines
virt/kvm/kvm_main.c +3
-1{ +int ret; +down_write (&kvm->slots_lock); -__kvm_io_bus_register_dev (bus, dev); + ret =__kvm_io_bus_register_dev (bus, dev);up_write (&kvm->slots_lock);kill empty line? this one is kind of iffy
virt/kvm/kvm_main.c int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) · line 2554
Quoted 13 lines
virt/kvm/kvm_main.c +5
-3+ +return ret; }/* An unlocked version. Caller must have write lock on slots_lock. */ -void __kvm_io_bus_register_dev (struct kvm_io_bus *bus, -struct kvm_io_device *dev) +int __kvm_io_bus_register_dev (struct kvm_io_bus *bus, +struct kvm_io_device *dev) { -BUG_ON (bus->dev_count > (NR_IOBUS_DEVS -1 )); +if (bus->dev_count > (NR_IOBUS_DEVS -1 ))as long as we are touching this: (NR_IOBUS_DEVS-1) ->
NR_IOBUS_DEVS- 1?virt/kvm/kvm_main.c int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) · line 2555
Quoted 4 lines
virt/kvm/kvm_main.c +1
-0+return -ENOSPC ; bus->devs[bus->dev_count++] = dev;kill empty line
Quoted 12 lines
virt/kvm/kvm_main.c +11
-0+ +return 0 ; +} + +void kvm_io_bus_unregister_dev (struct kvm *kvm, +struct kvm_io_bus *bus, +struct kvm_io_device *dev) +{ +down_write (&kvm->slots_lock); +__kvm_io_bus_unregister_dev (bus, dev); +up_write (&kvm->slots_lock);virt/kvm/kvm_main.c int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) · line 2576
Quoted 10 lines
virt/kvm/kvm_main.c +10
-0+} + +/* An unlocked version. Caller must have write lock on slots_lock. */ +void __kvm_io_bus_unregister_dev (struct kvm_io_bus *bus, +struct kvm_io_device *dev) +{ +int i; + +for (i =0 ; i < bus->dev_count; i++) { +kill empty line
virt/kvm/kvm_main.c int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) · line 2581
Quoted 6 lines
virt/kvm/kvm_main.c +5
-0+if (bus->devs[i] == dev) { + bus->devs[i] = bus->devs[--bus->dev_count]; +break ; + } + }no {} around single statement
Quoted 4 lines
}
static struct
notifier_blockkvm_cpu_notifier= {
Re: [KVM PATCH v9 1/2] KVM: make io_bus interface more robust
Quoted 5 lines · Gregory Haskins
These patches pass checkpatch.pl and I happen to like the extra whitespace for readability. I agree that a random isolated whitespace hunk, or double whitespace in a row are probably inadvertent and should be pointed out. But these little one liners in the middle of code I generally do on purpose (for instance, [A]).
Where it's on purpose, it's on purpose. I am just trying to convey a rather obvious point that each line of code should have a purpose in life, and that includes empty lines :)
Quoted 2 lines
I suppose its personal preference either way, so I guess unless Avi objects lets just each have our own style in that regard.
I think Avi already said we don't need to standardize everything. I hope at least some of the comments were helpful.
Quoted 14 lines
Quoted 13 lines
arch/x86/kvm/i8259.c struct kvm_pic *kvm_create_pic(struct kvm *kvm) · line 559
Quoted 8 lines
arch/x86/kvm/i8259.c +2
-1@@ -552,6 +554,11 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)* Initialize PIO device */ kvm_iodevice_init (&s->dev, &picdev_ops); -kvm_io_bus_register_dev (kvm, &kvm->pio_bus, &s->dev); + ret =kvm_io_bus_register_dev (kvm, &kvm->pio_bus, &s->dev); +if (ret <0 ) {I thought the function returns 0 on success?
If so can we just if (ret) all over?
Quoted 1 line
I guess, but what does that churn buy us?
It's not that important really. I think we need to document the return value, and check it according to how it is documented. The reason I commented, I see < 0 and ask "what if it is > 0"? I look it up and it turns out it's never > 0. So why check < 0?
Quoted 10 lines
Quoted 8 lines
virt/kvm/coalesced_mmio.c int kvm_coalesced_mmio_init(struct kvm *kvm) · line 111
Quoted 5 lines
virt/kvm/coalesced_mmio.c +4
-0+ ret =kvm_io_bus_register_dev (kvm, &kvm->mmio_bus, &dev->dev); +if (ret <0 ) +kfree (dev); +kill empty line
Why do you object here especially when there is precedence
How do you mean, precedence?
Quoted 3 lines
with
something like the space before the return with [B]? I think big mono-blocks of code are ugly and harder to read, personally.
I don't intend to keep arguing and I agree it's a question of style. But since you ask why I'll try to answer. I think an
empty line should help delimit a block of code with some common meaning, like a paragraph. But if overused it loses meaning and stops being helpful.
E.g., it does not make sense to put it between every 2 lines of code in a function. It also does not make sense to put it after } which is already delimiting a block in a visible way; it does not make sense to put it around a multiline comment which is delimited by /**/. It does not make sense to put it around an idented block which is already delimited by indentation.
Quoted 8 lines
Quoted 8 lines
virt/kvm/kvm_main.c int kvm_io_bus_read(struct kvm_io_bus *bus, gpa_t addr, int len, void *val) · line 2581
Quoted 6 lines
virt/kvm/kvm_main.c +5
-0+if (bus->devs[i] == dev) { + bus->devs[i] = bus->devs[--bus->dev_count]; +break ; + } + }no {} around single statement
This is actually part of style IMO, it is just hard for a perl script to catch :).
Quoted 8 lines
Quoted 6 lines
Quoted 6 lines
}
static struct
notifier_blockkvm_cpu_notifier= {
Re: [KVM PATCH v9 1/2] KVM: make io_bus interface more robust
Quoted 11 lines · Michael S. Tsirkin
Quoted 3 lines · Gregory Haskins
I suppose its personal preference either way, so I guess unless Avi objects lets just each have our own style in that regard.
I think Avi already said we don't need to standardize everything. I hope at least some of the comments were helpful.
Yes, it was very helpful and I really *do* appreciate the time you take to review the code. I think you will see that aside from the things we agree are whitespace style, I addressed your feedback in v10. The one notable omission (and this was not intentional) was that I forgot to document the return value like you requested. If a v11 is needed after review comments, I will update it then. Otherwise, Ill just submit a trivial doc patch after v10 is accepted.
Thanks again, Michael,
-Greg
PATCH v9 2/2 KVM: add iosignalfd support
In reply to Gregory Haskinsiosignalfd is a mechanism to register PIO/MMIO regions to trigger an eventfd signal when written to by a guest. Host userspace can register any arbitrary IO address with a corresponding eventfd and then pass the eventfd to a specific end-point of interest for handling.
Normal IO requires a blocking round-trip since the operation may cause side-effects in the emulated model or may return data to the caller. Therefore, an IO in KVM traps from the guest to the host, causes a VMX/SVM "heavy-weight" exit back to userspace, and is ultimately serviced by qemu's device model synchronously before returning control back to the vcpu.
However, there is a subclass of IO which acts purely as a trigger for other IO (such as to kick off an out-of-band DMA request, etc). For these patterns, the synchronous call is particularly expensive since we really only want to simply get our notification transmitted asychronously and return as quickly as possible. All the sychronous infrastructure to ensure proper data-dependencies are met in the normal IO case are just unecessary overhead for signalling. This adds additional computational load on the system, as well as latency to the signalling path.
Therefore, we provide a mechanism for registration of an in-kernel trigger point that allows the VCPU to only require a very brief, lightweight exit just long enough to signal an eventfd. This also means that any clients compatible with the eventfd interface (which includes userspace and kernelspace equally well) can now register to be notified. The end result should be a more flexible and higher performance notification API for the backend KVM hypervisor and perhipheral components.
To test this theory, we built a test-harness called "doorbell". This module has a function called "doorbell_ring()" which simply increments a counter for each time the doorbell is signaled. It supports signalling from either an eventfd, or an ioctl().
We then wired up two paths to the doorbell: One via QEMU via a registered io region and through the doorbell ioctl(). The other is direct via iosignalfd.
You can download this test harness here:
ftp://ftp.novell.com/dev/ghaskins/doorbell.tar.bz2
The measured results are as follows:
qemu-mmio: 110000 iops, 9.09us rtt iosignalfd-mmio: 200100 iops, 5.00us rtt iosignalfd-pio: 367300 iops, 2.72us rtt
I didn't measure qemu-pio, because I have to figure out how to register a PIO region with qemu's device model, and I got lazy. However, for now we can extrapolate based on the data from the NULLIO runs of +2.56us for MMIO, and -350ns for HC, we get:
qemu-pio: 153139 iops, 6.53us rtt iosignalfd-hc: 412585 iops, 2.37us rtt
these are just for fun, for now, until I can gather more data.
Here is a graph for your convenience:
http://developer.novell.com/wiki/images/7/76/Iofd-chart.png
The conclusion to draw is that we save about 4us by skipping the userspace hop.
--------------------
---
arch/x86/kvm/x86.c | 1 include/linux/kvm.h | 15 ++ include/linux/kvm_host.h | 10 +- virt/kvm/eventfd.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++ virt/kvm/kvm_main.c | 11 ++ 5 files changed, 313 insertions(+), 4 deletions(-)
arch/x86/kvm/x86.c +1 -0
@@ -1204,6 +1204,7 @@ int kvm_dev_ioctl_check_extension(long ext)case KVM_CAP_IRQ_INJECT_STATUS :case KVM_CAP_ASSIGN_DEV_IRQ :case KVM_CAP_IRQFD : +case KVM_CAP_IOSIGNALFD :case KVM_CAP_PIT2 : r =1 ;break ;
include/linux/kvm.h +15 -0
@@ -307,6 +307,19 @@ struct kvm_guest_debug {struct kvm_guest_debug_arch arch; }; +#define KVM_IOSIGNALFD_FLAG_TRIGGER (1 << 0)/* trigger is valid */ +#define KVM_IOSIGNALFD_FLAG_PIO (1 << 1)/* is a pio (otherwise mmio) */ +#define KVM_IOSIGNALFD_FLAG_DEASSIGN (1 << 2) + +struct kvm_iosignalfd { +__u64 trigger; +__u64 addr;/* legal pio/mmio address */ +__u32 len;/* 1, 2, 4, or 8 bytes */ +__s32 fd; +__u32 flags; +__u8 pad[36 ]; +}; +#define KVM_TRC_SHIFT 16/* * kvm trace categories
@@ -409,6 +422,7 @@ struct kvm_guest_debug {#define KVM_CAP_PIT2 33#endif #define KVM_CAP_SET_BOOT_CPU_ID 34 +#define KVM_CAP_IOSIGNALFD 35#ifdef KVM_CAP_IRQ_ROUTING
@@ -517,6 +531,7 @@ struct kvm_irqfd {#define KVM_IRQFD _IOW(KVMIO, 0x76, 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_IOSIGNALFD _IOW(KVMIO, 0x79, struct kvm_iosignalfd)/* * ioctls for vcpu fds
include/linux/kvm_host.h +8 -2
@@ -154,6 +154,7 @@ struct kvm {spinlock_t lock; struct list_head items; } irqfds; +struct list_head iosignalfds;#endif struct kvm_vm_stat stat;struct kvm_arch arch;
@@ -532,19 +533,24 @@ static inline void kvm_free_irq_routing(struct kvm *kvm) {}#ifdef CONFIG_HAVE_KVM_EVENTFD -void kvm_irqfd_init (struct kvm *kvm); +void kvm_eventfd_init (struct kvm *kvm);int kvm_irqfd (struct kvm *kvm,int fd,int gsi,int flags);void kvm_irqfd_release (struct kvm *kvm); +int kvm_iosignalfd (struct kvm *kvm,struct kvm_iosignalfd *args);#else -static inline void kvm_irqfd_init (struct kvm *kvm) {} +static inline void kvm_eventfd_init (struct kvm *kvm) {}static inline int kvm_irqfd (struct kvm *kvm,int fd,int gsi,int flags) {return -EINVAL ; }static inline void kvm_irqfd_release (struct kvm *kvm) {} +static inline int kvm_iosignalfd (struct kvm *kvm,struct kvm_iosignalfd *args) +{ +return -ENOSYS ; +}#endif /* CONFIG_HAVE_KVM_EVENTFD */
virt/kvm/eventfd.c +279 -1
304 lines not on this page · raw message
virt/kvm/kvm_main.c +10 -1
@@ -979,7 +979,7 @@ static struct kvm *kvm_create_vm(void)spin_lock_init (&kvm->mmu_lock);spin_lock_init (&kvm->requests_lock);kvm_io_bus_init (&kvm->pio_bus); -kvm_irqfd_init (kvm); +kvm_eventfd_init (kvm);mutex_init (&kvm->lock);mutex_init (&kvm->irq_lock);kvm_io_bus_init (&kvm->mmio_bus);
@@ -2271,6 +2271,15 @@ static long kvm_vm_ioctl(struct file *filp, r =kvm_irqfd (kvm, data.fd, data.gsi, data.flags);break ; } +case KVM_IOSIGNALFD : { +struct kvm_iosignalfd data; + + r = -EFAULT ; +if (copy_from_user (&data, argp,sizeof data)) + goto out; + r =kvm_iosignalfd (kvm, &data); +break ; + }#ifdef CONFIG_KVM_APIC_ARCHITECTURE case KVM_SET_BOOT_CPU_ID : r =0 ;
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
Some comments below. Sorry, I know it's late in the series, but previously I've been too confused with complicated locking to notice anything else :(.
Quoted 93 lines · Gregory Haskins
iosignalfd is a mechanism to register PIO/MMIO regions to trigger an eventfd signal when written to by a guest. Host userspace can register any arbitrary IO address with a corresponding eventfd and then pass the eventfd to a specific end-point of interest for handling.
Normal IO requires a blocking round-trip since the operation may cause side-effects in the emulated model or may return data to the caller. Therefore, an IO in KVM traps from the guest to the host, causes a VMX/SVM "heavy-weight" exit back to userspace, and is ultimately serviced by qemu's device model synchronously before returning control back to the vcpu.
However, there is a subclass of IO which acts purely as a trigger for other IO (such as to kick off an out-of-band DMA request, etc). For these patterns, the synchronous call is particularly expensive since we really only want to simply get our notification transmitted asychronously and return as quickly as possible. All the sychronous infrastructure to ensure proper data-dependencies are met in the normal IO case are just unecessary overhead for signalling. This adds additional computational load on the system, as well as latency to the signalling path.
Therefore, we provide a mechanism for registration of an in-kernel trigger point that allows the VCPU to only require a very brief, lightweight exit just long enough to signal an eventfd. This also means that any clients compatible with the eventfd interface (which includes userspace and kernelspace equally well) can now register to be notified. The end result should be a more flexible and higher performance notification API for the backend KVM hypervisor and perhipheral components.
To test this theory, we built a test-harness called "doorbell". This module has a function called "
doorbell_ring()" which simply increments a counter for each time the doorbell is signaled. It supports signalling from either an eventfd, or anioctl().We then wired up two paths to the doorbell: One via QEMU via a registered io region and through the doorbell
ioctl(). The other is direct via iosignalfd.You can download this test harness here:
ftp://ftp.novell.com/dev/ghaskins/doorbell.tar.bz2
The measured results are as follows:
qemu-mmio: 110000 iops, 9.09us rtt iosignalfd-mmio: 200100 iops, 5.00us rtt iosignalfd-pio: 367300 iops, 2.72us rttI didn't measure qemu-pio, because I have to figure out how to register a PIO region with qemu's device model, and I got lazy. However, for now we can extrapolate based on the data from the NULLIO runs of +2.56us for MMIO, and -350ns for HC, we get:
qemu-pio: 153139 iops, 6.53us rtt iosignalfd-hc: 412585 iops, 2.37us rttthese are just for fun, for now, until I can gather more data.
Here is a graph for your convenience:
http://developer.novell.com/wiki/images/7/76/Iofd-chart.png
The conclusion to draw is that we save about 4us by skipping the userspace hop.
--------------------
Signed-off-by Gregory Haskins <[email protected]>---
arch/x86/kvm/x86.c | 1 include/linux/kvm.h | 15 ++ include/linux/kvm_host.h | 10 +- virt/kvm/eventfd.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++ virt/kvm/kvm_main.c | 11 ++ 5 files changed, 313 insertions(+), 4 deletions(-)arch/x86/kvm/x86.c +1
-0@@ -1204,6 +1204,7 @@ int kvm_dev_ioctl_check_extension(long ext)case KVM_CAP_IRQ_INJECT_STATUS :case KVM_CAP_ASSIGN_DEV_IRQ :case KVM_CAP_IRQFD : +case KVM_CAP_IOSIGNALFD :case KVM_CAP_PIT2 : r =1 ;break ;include/linux/kvm.h +0
-0
include/linux/kvm.h struct kvm_guest_debug { · line 310
Quoted 4 lines
include/linux/kvm.h +1
-0@@ -307,6 +307,19 @@ struct kvm_guest_debug {struct kvm_guest_debug_arch arch; }; +#define KVM_IOSIGNALFD_FLAG_TRIGGER (1 << 0)/* trigger is valid */
can we rename trigger -> value?
include/linux/kvm.h struct kvm_guest_debug { · line 315
Quoted 5 lines
include/linux/kvm.h +5
-0+#define KVM_IOSIGNALFD_FLAG_PIO (1 << 1)/* is a pio (otherwise mmio) */ +#define KVM_IOSIGNALFD_FLAG_DEASSIGN (1 << 2) + +struct kvm_iosignalfd { +__u64 trigger;
for length <8, it's the 8*len least significant bits that are used, right? That's a bit ugly ... Maybe just put an 8 byte array here instead, then the first len bytes are valid.
Quoted 88 lines
include/linux/kvm.h +9
-0+__u64 addr;/* legal pio/mmio address */ +__u32 len;/* 1, 2, 4, or 8 bytes */ +__s32 fd; +__u32 flags; +__u8 pad[36 ]; +}; +#define KVM_TRC_SHIFT 16/* * kvm trace categories @@ -409,6 +422,7 @@ struct kvm_guest_debug {#define KVM_CAP_PIT2 33#endif #define KVM_CAP_SET_BOOT_CPU_ID 34 +#define KVM_CAP_IOSIGNALFD 35#ifdef KVM_CAP_IRQ_ROUTING @@ -517,6 +531,7 @@ struct kvm_irqfd {#define KVM_IRQFD _IOW(KVMIO, 0x76, 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_IOSIGNALFD _IOW(KVMIO, 0x79, struct kvm_iosignalfd)/* * ioctls for vcpu fds include/linux/kvm_host.h +8
-2@@ -154,6 +154,7 @@ struct kvm {spinlock_t lock; struct list_head items; } irqfds; +struct list_head iosignalfds;#endif struct kvm_vm_stat stat;struct kvm_arch arch;@@ -532,19 +533,24 @@ static inline void kvm_free_irq_routing(struct kvm *kvm) {}#ifdef CONFIG_HAVE_KVM_EVENTFD -void kvm_irqfd_init (struct kvm *kvm); +void kvm_eventfd_init (struct kvm *kvm);int kvm_irqfd (struct kvm *kvm,int fd,int gsi,int flags);void kvm_irqfd_release (struct kvm *kvm); +int kvm_iosignalfd (struct kvm *kvm,struct kvm_iosignalfd *args);#else -static inline void kvm_irqfd_init (struct kvm *kvm) {} +static inline void kvm_eventfd_init (struct kvm *kvm) {}static inline int kvm_irqfd (struct kvm *kvm,int fd,int gsi,int flags) {return -EINVAL ; }static inline void kvm_irqfd_release (struct kvm *kvm) {} +static inline int kvm_iosignalfd (struct kvm *kvm,struct kvm_iosignalfd *args) +{ +return -ENOSYS ; +}#endif /* CONFIG_HAVE_KVM_EVENTFD */ virt/kvm/eventfd.c +4
-0@@ -21,6 +21,7 @@*/ #include <linux/kvm_host.h> +#include <linux/kvm.h> #include <linux/workqueue.h> #include <linux/syscalls.h> #include <linux/wait.h> @@ -28,6 +29,9 @@#include <linux/file.h> #include <linux/list.h> #include <linux/eventfd.h> +#include <linux/kernel.h> + +#include "iodev.h" /* * --------------------------------------------------------------------
virt/kvm/eventfd.c fail: · line 245
Quoted 9 lines
virt/kvm/eventfd.c +2
-1@@ -234,10 +238,12 @@ fail: }void -kvm_irqfd_init (struct kvm *kvm) +kvm_eventfd_init (struct kvm *kvm) {spin_lock_init (&kvm->irqfds.lock);INIT_LIST_HEAD (&kvm->irqfds.items); +
don't need this empty line
Quoted 5 lines
virt/kvm/eventfd.c +1
-0+INIT_LIST_HEAD (&kvm->iosignalfds); }/*
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 341
Quoted 9 lines
virt/kvm/eventfd.c +6
-0@@ -327,3 +333,275 @@ static void __exit irqfd_module_exit(void)module_init (irqfd_module_init);module_exit (irqfd_module_exit); + +/* +* -------------------------------------------------------------------- +* iosignalfd: translate a PIO/MMIO memory write to an eventfd signal. +* +* userspace can register a PIO/MMIO address with an eventfd for recieving
recieving -> receiving
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 349
Quoted 8 lines
virt/kvm/eventfd.c +8
-0+* notification when the memory has been touched. +* -------------------------------------------------------------------- +*/ + +struct _iosignalfd { +struct list_head list; +u64 addr; +size_t length;
"int length" should be enough: the value is 1, 2, 4 or 8. and put wildcard near it if you want to save some space
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 351
Quoted 2 lines
virt/kvm/eventfd.c +2
-0+struct eventfd_ctx *eventfd; +u64 match;
match -> value
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 353
Quoted 2 lines
virt/kvm/eventfd.c +2
-0+struct kvm_io_device dev; + int wildcard:1;
don't use bitfields
Quoted 12 lines
virt/kvm/eventfd.c +12
-0+}; + +static inline struct _iosignalfd * +to_iosignalfd (struct kvm_io_device *dev) +{ + return container_of(dev, struct _iosignalfd, dev); +} + +static void +iosignalfd_release (struct _iosignalfd *p) +{ +eventfd_ctx_put (p->eventfd);
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 375
Quoted 10 lines
virt/kvm/eventfd.c +10
-0+list_del (&p->list); +kfree (p); +} + +static bool +iosignalfd_in_range (struct _iosignalfd *p,gpa_t addr,int len,const void *val) +{ +u64 _val; + +if (!(addr == p->addr && len == p->length))
de-morgan's laws can help simplify this
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 376
Quoted 1 line
virt/kvm/eventfd.c +1
-0+/* address-range must be precise for a hit */
So there's apparently no way to specify that
you want 1,2, or 4 byte writes at address X?
Quoted 18 lines
virt/kvm/eventfd.c +18
-0+return false; + +if (p->wildcard) +/* all else equal, wildcard is always a hit */ +return true; + +/* otherwise, we have to actually compare the data */ + +BUG_ON (!IS_ALIGNED ((unsigned long )val, len)); + +switch (len) { +case 1 : + _val = *(u8 *)val; +break ; +case 2 : + _val = *(u16 *)val; +break ; +case 4 :
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 404
Quoted 10 lines
virt/kvm/eventfd.c +10
-0+ _val = *(u32 *)val; +break ; +case 8 : + _val = *(u64 *)val; +break ; +default : +return false; + } + +return _val == p->match ? true : false;
Life be simpler if we use an 8 byte array for match and just do memcmp here.
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 409
Quoted 5 lines
virt/kvm/eventfd.c +5
-0+} + +/* +* MMIO/PIO writes trigger an event if the addr/val match +*/
single line comment can look like this:
/* MMIO/PIO writes trigger an event if the addr/val match */
Quoted 22 lines
virt/kvm/eventfd.c +22
-0+static int +iosignalfd_write (struct kvm_io_device *this,gpa_t addr,int len, +const void *val) +{ +struct _iosignalfd *p =to_iosignalfd (this); + +if (!iosignalfd_in_range (p, addr, len, val)) +return -EOPNOTSUPP ; + +eventfd_signal (p->eventfd,1 ); +return 0 ; +} + +/* +* This function is called as KVM is completely shutting down. We do not +* need to worry about locking just nuke anything we have as quickly as possible +*/ +static void +iosignalfd_destructor (struct kvm_io_device *this) +{ +struct _iosignalfd *p =to_iosignalfd (this); +
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 441
Quoted 10 lines
virt/kvm/eventfd.c +10
-0+iosignalfd_release (p); +} + +static const struct kvm_io_device_ops iosignalfd_ops = { + .write = iosignalfd_write, + .destructor = iosignalfd_destructor, +}; + +static bool +iosignalfd_overlap (struct _iosignalfd *lhs,struct _iosignalfd *rhs)
this checks both region overlap and data collision. better split into two helpers?
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 447
Quoted 6 lines
virt/kvm/eventfd.c +6
-0+{ +/* +* Check for completely non-overlapping regions. We can simply +* return "false" for non-overlapping regions and be done with +* it. +*/
done with it -> ignore the value
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 449
Quoted 2 lines
virt/kvm/eventfd.c +2
-0+if ((rhs->addr + rhs->length) <= lhs->addr) +return false;
rhs->addr + rhs->length <= lhs->addr
is not less clear, as precedence for simple math
follows the familiar rules from school.
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 451
Quoted 2 lines
virt/kvm/eventfd.c +2
-0+ +if ((lhs->addr + lhs->length) <= rhs->addr)
this math can overflow.
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 452
Quoted 1 line
virt/kvm/eventfd.c +1
-0+return false;
or shorter:
if (rhs->addr + rhs->length <= lhs->addr ||
lhs->addr + lhs->length <= rhs->addr)
return true;
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void)
Quoted 4 lines
virt/kvm/eventfd.c +4
-0+ +/* +* If we get here, we know there is *some* overlap, but we don't +* yet know how much.
how much?
Quoted 1 line
Make sure its a "precise" overlap, or
precise overlap -> address/len pairs match
virt/kvm/eventfd.c
Quoted 2 lines
virt/kvm/eventfd.c +2
-0+* its rejected as incompatible +*/
"rejected" does not seem to make sense in the context of a boolean function
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 464
Quoted 6 lines
virt/kvm/eventfd.c +6
-0+if (lhs->addr != rhs->addr) +return true; + +if (lhs->length != rhs->length) +return true; +
or shorter:
if (lhs->addr != rhs->addr || lhs->length != rhs->length)
return true;Quoted 7 lines
virt/kvm/eventfd.c +7
-0+/* +* If we get here, the request should be a precise overlap +* between rhs+lhs. The only thing left to check is for +* data-match overlap. If the data match is distinctly different +* we can allow the two to co-exist. Any kind of wild-card +* consitutes an incompatible range, so reject any wild-cards, +* or if the match token is identical.
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 479
Quoted 10 lines
virt/kvm/eventfd.c +8
-0+*/ +if (lhs->wildcard || rhs->wildcard || lhs->match == rhs->match) +return true; + +return false; +} + +/* assumes kvm->slots_lock write-lock held */
it seems you only need read lock?
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 486
Quoted 7 lines
virt/kvm/eventfd.c +7
-0+static bool +iosignalfd_check_collision (struct kvm *kvm,struct _iosignalfd *p) +{ +struct _iosignalfd *_p; + +list_for_each_entry (_p, &kvm->iosignalfds, list) +if (iosignalfd_overlap (_p, p))
This looks wrong: let's assume I want one signal with length 1 and one with length 2 at address 0. They never trigger together, so it should be ok to have 2 such devices.
Quoted 17 lines
virt/kvm/eventfd.c +17
-0+return true; + +return false; +} + +static int +kvm_assign_iosignalfd (struct kvm *kvm,struct kvm_iosignalfd *args) +{ +int pio = args->flags &KVM_IOSIGNALFD_FLAG_PIO ; +struct kvm_io_bus *bus = pio ? &kvm->pio_bus : &kvm->mmio_bus; +struct _iosignalfd *p; +struct eventfd_ctx *eventfd; +int ret; + +switch (args->len) { +case 1 : +case 2 :
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 513
Quoted 10 lines
virt/kvm/eventfd.c +10
-0+case 4 : +case 8 : +break ; +default : +return -EINVAL ; + } + + eventfd =eventfd_ctx_fdget (args->fd); +if (IS_ERR (eventfd)) +return PTR_ERR (eventfd);
since this eventfd is kept around indefinitely, we should keep the file * around as well, so that this eventfd is accounted for properly with # of open files limit set by the admin.
Quoted 5 lines
virt/kvm/eventfd.c +5
-0+ + p =kzalloc (sizeof (*p),GFP_KERNEL ); +if (!p) { + ret = -ENOMEM ; + goto fail;
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 528
Quoted 10 lines
virt/kvm/eventfd.c +10
-0+ } + +INIT_LIST_HEAD (&p->list); + p->addr = args->addr; + p->length = args->len; + p->eventfd = eventfd; + +/* +* A trigger address is optional, otherwise this is a wildcard +*/
A single line comment can look like this:
/* A trigger address is optional, otherwise this is a wildcard */
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 530
Quoted 2 lines
virt/kvm/eventfd.c +2
-0+if (args->flags &KVM_IOSIGNALFD_FLAG_TRIGGER ) + p->match = args->trigger;
For len < 8, high bits in trigger are ignored. it's better to check that they are 0, less confusing if the user e.g. gets the endian-ness wrong.
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 536
Quoted 7 lines
virt/kvm/eventfd.c +6
-0+else + p->wildcard = true; + +down_write (&kvm->slots_lock); + +/* Verify that there isnt a match already */
Better to put documentation to where function is declared, not where it is used.
Quoted 7 lines
virt/kvm/eventfd.c +7
-0+if (iosignalfd_check_collision (kvm, p)) { + ret = -EEXIST ; + goto unlock_fail; + } + +kvm_iodevice_init (&p->dev, &iosignalfd_ops); +
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 553
Quoted 10 lines
virt/kvm/eventfd.c +10
-0+ ret =__kvm_io_bus_register_dev (bus, &p->dev); +if (ret <0 ) + goto unlock_fail; + +list_add_tail (&p->list, &kvm->iosignalfds); + +up_write (&kvm->slots_lock); + +return 0 ; +
we probably do not need an empty line after each line of code here
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 560
Quoted 7 lines
virt/kvm/eventfd.c +7
-0+unlock_fail: +up_write (&kvm->slots_lock); +fail: +/* +* it would have never made it to the list in the failure path, so +* we dont need to worry about removing it +*/
of course: you goto fail before list_add
can just kill this comment
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 565
Quoted 5 lines
virt/kvm/eventfd.c +5
-0+kfree (p); + +eventfd_ctx_put (eventfd); + +return ret;
we probably do not need an empty line after each line of code here
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 369
Quoted 3 lines
virt/kvm/eventfd.c +3
-0+} + +
two empty lines
Quoted 7 lines
virt/kvm/eventfd.c +7
-0+static int +kvm_deassign_iosignalfd (struct kvm *kvm,struct kvm_iosignalfd *args) +{ +int pio = args->flags &KVM_IOSIGNALFD_FLAG_PIO ; +struct kvm_io_bus *bus = pio ? &kvm->pio_bus : &kvm->mmio_bus; +struct _iosignalfd *p, *tmp; +struct eventfd_ctx *eventfd;
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 585
Quoted 10 lines
virt/kvm/eventfd.c +10
-0+int ret =0 ; + + eventfd =eventfd_ctx_fdget (args->fd); +if (IS_ERR (eventfd)) +return PTR_ERR (eventfd); + +down_write (&kvm->slots_lock); + +list_for_each_entry_safe (p, tmp, &kvm->iosignalfds, list) { +
kill empty line
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 587
Quoted 2 lines
virt/kvm/eventfd.c +2
-0+if (p->eventfd != eventfd) +continue ;
So for deassign, you ignore all arguments besides fd? Is this intentional? Looks strange - think of multiple addresses triggering a single eventfd. But if so, it's better to have a different ioctl with just the fields we need.
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 590
Quoted 3 lines
virt/kvm/eventfd.c +3
-0+ +__kvm_io_bus_unregister_dev (bus, &p->dev); +iosignalfd_release (p);
a single deassign removed multiple irqfds? Looks ugly.
virt/kvm/eventfd.c
Quoted 2 lines
virt/kvm/eventfd.c +2
-0+ } +
kill empty line
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 566
Quoted 6 lines
virt/kvm/eventfd.c +6
-0+up_write (&kvm->slots_lock); + +eventfd_ctx_put (eventfd); + +return ret; +}
return error status if no device was found?
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 604
Quoted 6 lines
virt/kvm/eventfd.c +6
-0+ +int +kvm_iosignalfd (struct kvm *kvm,struct kvm_iosignalfd *args) +{ +if (args->flags &KVM_IOSIGNALFD_FLAG_DEASSIGN ) +return kvm_deassign_iosignalfd (kvm, args);
Better check that only known flag values are present. Otherwise when you add more flags things just break silently.
Quoted 17 lines
virt/kvm/eventfd.c +3
-0+ +return kvm_assign_iosignalfd (kvm, args); +}virt/kvm/kvm_main.c +1
-1@@ -979,7 +979,7 @@ static struct kvm *kvm_create_vm(void)spin_lock_init (&kvm->mmu_lock);spin_lock_init (&kvm->requests_lock);kvm_io_bus_init (&kvm->pio_bus); -kvm_irqfd_init (kvm); +kvm_eventfd_init (kvm);mutex_init (&kvm->lock);mutex_init (&kvm->irq_lock);kvm_io_bus_init (&kvm->mmio_bus);
virt/kvm/kvm_main.c static long kvm_vm_ioctl(struct file *filp, · line 2277
Quoted 7 lines
virt/kvm/kvm_main.c +4
-0@@ -2271,6 +2271,15 @@ static long kvm_vm_ioctl(struct file *filp, r =kvm_irqfd (kvm, data.fd, data.gsi, data.flags);break ; } +case KVM_IOSIGNALFD : { +struct kvm_iosignalfd data; + + r = -EFAULT ;
this trick is nice, it saves a line of code for the closing brace but why waste it on an empty line above then?
Quoted 8 lines
virt/kvm/kvm_main.c +5
-0+if (copy_from_user (&data, argp,sizeof data)) + goto out; + r =kvm_iosignalfd (kvm, &data); +break ; + }#ifdef CONFIG_KVM_APIC_ARCHITECTURE case KVM_SET_BOOT_CPU_ID : r =0 ;
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
(adding Davide, there's a small comment for you in the middle, search for eventfd)
Quoted 10 lines · Michael S. Tsirkin
include/linux/kvm.h struct kvm_guest_debug { · line 311
Quoted 7 lines
include/linux/kvm.h +1
-0@@ -307,6 +307,19 @@ struct kvm_guest_debug {struct kvm_guest_debug_arch arch; }; +#define KVM_IOSIGNALFD_FLAG_TRIGGER (1<< 0)/* trigger is valid */ can we rename trigger -> value?
Or maybe data_match?
Speaking of renames, how about IOSIGNALFD -> IOEVENTFD? I have some vague uneasiness seeing signals all the time.
Quoted 12 lines
include/linux/kvm.h struct kvm_guest_debug {
Quoted 6 lines
include/linux/kvm.h +5
-0+#define KVM_IOSIGNALFD_FLAG_PIO (1<< 1)/* is a pio (otherwise mmio) */ +#define KVM_IOSIGNALFD_FLAG_DEASSIGN (1<< 2) + +struct kvm_iosignalfd { +__u64 trigger;for length<8, it's the 8*len least significant bits that are used, right? That's a bit ugly ... Maybe just put an 8 byte array here instead, then the first len bytes are valid.
We're matching the value as the guest wrote it. I think this is fine.
Quoted 6 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void)
Quoted 3 lines
virt/kvm/eventfd.c +2
-0+struct kvm_io_device dev; + int wildcard:1;don't use bitfields
Yeah, bool is better.
Quoted 6 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 376
Quoted 2 lines
virt/kvm/eventfd.c +1
-0+/* address-range must be precise for a hit */ So there's apparently no way to specify that
you want 1,2, or 4 byte writes at address X?
Why would you want that?
Quoted 25 lines
Quoted 25 lines
virt/kvm/eventfd.c +24
-0+return false; + +if (p->wildcard) +/* all else equal, wildcard is always a hit */ +return true; + +/* otherwise, we have to actually compare the data */ + +BUG_ON (!IS_ALIGNED ((unsigned long )val, len)); + +switch (len) { +case 1 : + _val = *(u8 *)val; +break ; +case 2 : + _val = *(u16 *)val; +break ; +case 4 : + _val = *(u32 *)val; +break ; +case 8 : + _val = *(u64 *)val; +break ; +default :
Quoted 9 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 404
Quoted 5 lines
virt/kvm/eventfd.c +4
-0+return false; + } + +return _val == p->match ? true : false;Life be simpler if we use an 8 byte array for match and just do memcmp here.
My plan is to change the io_dev interface to pass a u64.
Quoted 10 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 513
Quoted 5 lines
virt/kvm/eventfd.c +4
-0+ + eventfd =eventfd_ctx_fdget (args->fd); +if (IS_ERR (eventfd)) +return PTR_ERR (eventfd);since this eventfd is kept around indefinitely, we should keep the file * around as well, so that this eventfd is accounted for properly with # of open files limit set by the admin.
Won't all eventfd_ctx_get() uses suffer from that?
Davide, I think this is better handled in eventfd. Or else we can ignore it and trust whoever holds the eventfd_ctx to limit the mount of objects.
Quoted 12 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 604
Quoted 7 lines
virt/kvm/eventfd.c +6
-0+ +int +kvm_iosignalfd (struct kvm *kvm,struct kvm_iosignalfd *args) +{ +if (args->flags&KVM_IOSIGNALFD_FLAG_DEASSIGN ) +return kvm_deassign_iosignalfd (kvm, args);Better check that only known flag values are present. Otherwise when you add more flags things just break silently.
Good comment and something that we miss a lot.
Quoted 9 lines
virt/kvm/kvm_main.c static long kvm_vm_ioctl(struct file *filp, · line 2277
Quoted 5 lines
virt/kvm/kvm_main.c +4
-0+case KVM_IOSIGNALFD : { +struct kvm_iosignalfd data; + + r = -EFAULT ;this trick is nice, it saves a line of code for the closing brace but why waste it on an empty line above then?
Traditionally C code separates declarations from code.
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
Quoted 8 lines · Avi Kivity
Quoted 6 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 376
Quoted 2 lines
virt/kvm/eventfd.c +1
-0+/* address-range must be precise for a hit */ So there's apparently no way to specify that
you want 1,2, or 4 byte writes at address X?Why would you want that?
Donnu. Why would anyone want to catch 8 byte writes at all? Seriously, why add artificial limitations?
IMO, addr=0,len=1 and addr=0,len=2 should not conflict.
Signature · 1 line
MST
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
Quoted 9 lines · Michael S. Tsirkin
Quoted 7 lines · Avi Kivity
Quoted 7 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 376
Quoted 3 lines
virt/kvm/eventfd.c +1
-0+/* address-range must be precise for a hit */ So there's apparently no way to specify that
you want 1,2, or 4 byte writes at address X?
Quoted 5 lines
Quoted 2 lines
Why would you want that?
Donnu. Why would anyone want to catch 8 byte writes at all?
One of the natural write sizes.
Quoted 4 lines
Seriously, why add artificial limitations? IMO, addr=0,len=1 and addr=0,len=2 should not conflict.
They should not conflict, but a two byte write need not hit a one byte registration.
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
Quoted 18 lines · Avi Kivity
Quoted 9 lines · Michael S. Tsirkin
Quoted 7 lines · Avi Kivity
Quoted 7 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 376
Quoted 3 lines
virt/kvm/eventfd.c +1
-0+/* address-range must be precise for a hit */ So there's apparently no way to specify that
you want 1,2, or 4 byte writes at address X?Quoted 5 lines
Quoted 2 lines
Why would you want that?
Donnu. Why would anyone want to catch 8 byte writes at all?
One of the natural write sizes.
Quoted 7 lines
Quoted 4 lines
Seriously, why add artificial limitations? IMO, addr=0,len=1 and addr=0,len=2 should not conflict.
They should not conflict, but a two byte write need not hit a one byte registration.
Yes. That's exactly what I'm saying. I think it should be possible to create 2 fds:
addr = 0
len = 1
addr = 0
len = 2
and at most one will ever trigger.
But current code will not let you create the second one.
Signature · 1 line
MST
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
Quoted 13 lines · Michael S. Tsirkin
Quoted 9 lines
Quoted 6 lines
Seriously, why add artificial limitations? IMO, addr=0,len=1 and addr=0,len=2 should not conflict.
They should not conflict, but a two byte write need not hit a one byte registration.
Yes. That's exactly what I'm saying. I think it should be possible to create 2 fds:
Quoted 8 lines
addr = 0
len = 1
addr = 0
len = 2
and at most one will ever trigger.But current code will not let you create the second one.
I agree then. Good catch.
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
In reply to Michael S. TsirkinQuoted 37 lines · Michael S. Tsirkin
Quoted 23 lines · Avi Kivity
Quoted 12 lines · Michael S. Tsirkin
Quoted 9 lines · Avi Kivity
Quoted 9 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 376
Quoted 4 lines
virt/kvm/eventfd.c +1
-0+/* address-range must be precise for a hit */ So there's apparently no way to specify that
you want 1,2, or 4 byte writes at address X?Quoted 6 lines
Quoted 3 lines
Why would you want that?
Donnu. Why would anyone want to catch 8 byte writes at all?
One of the natural write sizes.
Quoted 8 lines
Quoted 5 lines
Seriously, why add artificial limitations? IMO, addr=0,len=1 and addr=0,len=2 should not conflict.
They should not conflict, but a two byte write need not hit a one byte registration.
Yes. That's exactly what I'm saying. I think it should be possible to create 2 fds:
Quoted 9 lines
addr = 0
len = 1
addr = 0
len = 2
and at most one will ever trigger.But current code will not let you create the second one.
Note that this was by design to keep the code simple since we don't have a (known) use case for overlap. At the very least, you have to address how data subsets are handled. But do we really need that functionality?
-Greg
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
Quoted 44 lines · Gregory Haskins
Quoted 43 lines · Michael S. Tsirkin
Quoted 23 lines · Avi Kivity
Quoted 12 lines · Michael S. Tsirkin
Quoted 9 lines · Avi Kivity
Quoted 9 lines
Review
Quoted 4 lines
(quoted diff) +1
-0+ /* address-range must be precise for a hit */So there's apparently no way to specify that
you want 1,2, or 4 byte writes at address X?Quoted 6 lines
Quoted 3 lines
Why would you want that?
Donnu. Why would anyone want to catch 8 byte writes at all?
One of the natural write sizes.
Quoted 8 lines
Quoted 5 lines
Seriously, why add artificial limitations? IMO, addr=0,len=1 and addr=0,len=2 should not conflict.
They should not conflict, but a two byte write need not hit a one byte registration.
Yes. That's exactly what I'm saying. I think it should be possible to create 2 fds:
addr = 0
len = 1
addr = 0
len = 2
and at most one will ever trigger.
Quoted 9 lines
Quoted 3 lines
But current code will not let you create the second one.
Note that this was by design to keep the code simple since we don't have a (known) use case for overlap. At the very least, you have to address how data subsets are handled. But do we really need that functionality?
-Greg
Hey, forget about overlap. Overlap does not exist as a concept. You now spend a lot of effort to detect it. Kill all that code, and just do this on assignment:
list_for_each(...)
if (rhs->add == lhs->addr && rhs->len == lhs->len && (rhs->wildcard || lhs->wildcard || rhs->data == lhs->data)) return -EEXIST;
Signature · 1 line
MST
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
Quoted 68 lines · Michael S. Tsirkin
Quoted 58 lines · Gregory Haskins
Quoted 46 lines · Michael S. Tsirkin
Quoted 30 lines · Avi Kivity
Quoted 15 lines · Michael S. Tsirkin
Quoted 11 lines · Avi Kivity
Quoted 11 lines
Review
Quoted 5 lines
(quoted diff) +1
-0+ /* address-range must be precise for a hit */So there's apparently no way to specify that
you want 1,2, or 4 byte writes at address X?Quoted 8 lines
Quoted 4 lines
Why would you want that?
Donnu. Why would anyone want to catch 8 byte writes at all?
One of the natural write sizes.
Quoted 10 lines
Quoted 6 lines
Seriously, why add artificial limitations? IMO, addr=0,len=1 and addr=0,len=2 should not conflict.
They should not conflict, but a two byte write need not hit a one byte registration.
Yes. That's exactly what I'm saying. I think it should be possible to create 2 fds:
Quoted 10 lines
addr = 0
len = 1
addr = 0
len = 2
and at most one will ever trigger.But current code will not let you create the second one.
Quoted 7 lines
Note that this was by design to keep the code simple since we don't have a (known) use case for overlap. At the very least, you have to address how data subsets are handled. But do we really need that functionality?
-Greg
Quoted 10 lines
Hey, forget about overlap. Overlap does not exist as a concept. You now spend a lot of effort to detect it. Kill all that code, and just do this on assignment:
list_for_each(...)if (rhs->add == lhs->addr && rhs->len == lhs->len && (rhs->wildcard || lhs->wildcard || rhs->data == lhs->data)) return -EEXIST;
I like it. Will do for v10.
Thanks Michael,
-Greg
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
In reply to Avi KivityQuoted 9 lines · Avi Kivity
(adding Davide, there's a small comment for you in the middle, search for eventfd)
Quoted 5 lines · Michael S. Tsirkin
Quoted 5 lines
include/linux/kvm.h +0
-0@@ -307,6 +307,19 @@ struct kvm_guest_debug {struct kvm_guest_debug_arch arch; };
Quoted 7 lines
Quoted 5 lines
Review struct kvm_guest_debug { · line 311
Quoted 2 lines
(quoted diff) +1
-0+#define KVM_IOSIGNALFD_FLAG_TRIGGER (1<< 0) /* trigger is valid */can we rename trigger -> value?
Or maybe
data_match?
Yeah, at the least I should be consistent with trigger/match
Quoted 3 lines
Speaking of renames, how about IOSIGNALFD -> IOEVENTFD? I have some vague uneasiness seeing signals all the time.
Sure, that works for me.
-Greg
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
In reply to Michael S. TsirkinQuoted 7 lines · Michael S. Tsirkin
Some comments below. Sorry, I know it's late in the series, but previously I've been too confused with complicated locking to notice anything else :(.
On Mon, Jul 06, 2009 at 04:33:21PM -0400, Gregory Haskins wrote:
Quoted 11 lines
include/linux/kvm.h struct kvm_guest_debug { · line 315
Quoted 6 lines
include/linux/kvm.h +5
-0+#define KVM_IOSIGNALFD_FLAG_PIO (1 << 1)/* is a pio (otherwise mmio) */ +#define KVM_IOSIGNALFD_FLAG_DEASSIGN (1 << 2) + +struct kvm_iosignalfd { +__u64 trigger;for length <8, it's the 8*len least significant bits that are used, right? That's a bit ugly ... Maybe just put an 8 byte array here instead, then the first len bytes are valid.
The original series uses an array that I kmalloc'ed to size, or left it NULL for a wildcard. Avi didn't like this and requested a u64 for all values. I don't care either way, but since you two are asking for conflicting designs, I will let you debate.
Quoted 13 lines
virt/kvm/eventfd.c fail: · line 245
Quoted 10 lines
void
virt/kvm/eventfd.c +2
-1-kvm_irqfd_init(struct kvm *kvm) +kvm_eventfd_init(struct kvm *kvm) {spin_lock_init (&kvm->irqfds.lock);INIT_LIST_HEAD (&kvm->irqfds.items); +don't need this empty line
Ack
Quoted 7 lines
Quoted 7 lines
virt/kvm/eventfd.c +1
-0+INIT_LIST_HEAD (&kvm->iosignalfds); }/* @@ -327,3 +333,275 @@ static void __exit irqfd_module_exit(void)
Quoted 13 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 341
Quoted 9 lines
virt/kvm/eventfd.c +6
-0module_init (irqfd_module_init);module_exit (irqfd_module_exit); + +/* +* -------------------------------------------------------------------- +* iosignalfd: translate a PIO/MMIO memory write to an eventfd signal. +* +* userspace can register a PIO/MMIO address with an eventfd for recieving recieving -> receiving
Ack
/me is embarrassed
Quoted 4 lines
Quoted 4 lines
virt/kvm/eventfd.c +4
-0+* notification when the memory has been touched. +* -------------------------------------------------------------------- +*/ +
Quoted 10 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 349
Quoted 5 lines
virt/kvm/eventfd.c +4
-0+struct _iosignalfd { +struct list_head list; +u64 addr; +size_t length;"int length" should be enough: the value is 1, 2, 4 or 8. and put wildcard near it if you want to save some space
Ok
Quoted 7 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 351
Quoted 3 lines
virt/kvm/eventfd.c +2
-0+struct eventfd_ctx *eventfd; +u64 match;match -> value
Ok
Quoted 6 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 353
Quoted 3 lines
virt/kvm/eventfd.c +2
-0+struct kvm_io_device dev; + int wildcard:1;don't use bitfields
bool?
Quoted 28 lines
Quoted 14 lines
virt/kvm/eventfd.c +12
-0+}; + +static inline struct _iosignalfd * +to_iosignalfd (struct kvm_io_device *dev) +{ + return container_of(dev, struct _iosignalfd, dev); +} + +static void +iosignalfd_release (struct _iosignalfd *p) +{ +eventfd_ctx_put (p->eventfd);virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 375
Quoted 10 lines
virt/kvm/eventfd.c +10
-0+list_del (&p->list); +kfree (p); +} + +static bool +iosignalfd_in_range (struct _iosignalfd *p,gpa_t addr,int len,const void *val) +{ +u64 _val; + +if (!(addr == p->addr && len == p->length))de-morgan's laws can help simplify this
Quoted 6 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 376
Quoted 2 lines
virt/kvm/eventfd.c +1
-0+/* address-range must be precise for a hit */ So there's apparently no way to specify that
you want 1,2, or 4 byte writes at address X?
No, they can be any legal size (1, 2, 4, or 8). The only limitation is that any overlap of two or more registrations have to be uniform in addr/len.
Quoted 25 lines
Quoted 25 lines
virt/kvm/eventfd.c +24
-0+return false; + +if (p->wildcard) +/* all else equal, wildcard is always a hit */ +return true; + +/* otherwise, we have to actually compare the data */ + +BUG_ON (!IS_ALIGNED ((unsigned long )val, len)); + +switch (len) { +case 1 : + _val = *(u8 *)val; +break ; +case 2 : + _val = *(u16 *)val; +break ; +case 4 : + _val = *(u32 *)val; +break ; +case 8 : + _val = *(u64 *)val; +break ; +default :
Quoted 10 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 404
Quoted 5 lines
virt/kvm/eventfd.c +4
-0+return false; + } + +return _val == p->match ? true : false;Life be simpler if we use an 8 byte array for match and just do memcmp here.
You would need to use an n-byte array, technically (to avoid endian issues). As mentioned earlier, I already did it that way in earlier versions but Avi wanted to see it this current (u64 based) way.
Quoted 11 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 409
Quoted 6 lines
virt/kvm/eventfd.c +5
-0+} + +/* +* MMIO/PIO writes trigger an event if the addr/val match +*/ single line comment can look like this:
/* MMIO/PIO writes trigger an event if the addr/val match */
Ack
Quoted 28 lines
Quoted 28 lines
virt/kvm/eventfd.c +28
-0+static int +iosignalfd_write (struct kvm_io_device *this,gpa_t addr,int len, +const void *val) +{ +struct _iosignalfd *p =to_iosignalfd (this); + +if (!iosignalfd_in_range (p, addr, len, val)) +return -EOPNOTSUPP ; + +eventfd_signal (p->eventfd,1 ); +return 0 ; +} + +/* +* This function is called as KVM is completely shutting down. We do not +* need to worry about locking just nuke anything we have as quickly as possible +*/ +static void +iosignalfd_destructor (struct kvm_io_device *this) +{ +struct _iosignalfd *p =to_iosignalfd (this); + +iosignalfd_release (p); +} + +static const struct kvm_io_device_ops iosignalfd_ops = { + .write = iosignalfd_write, + .destructor = iosignalfd_destructor,
Quoted 10 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 441
Quoted 5 lines
virt/kvm/eventfd.c +4
-0+}; + +static bool +iosignalfd_overlap (struct _iosignalfd *lhs,struct _iosignalfd *rhs)this checks both region overlap and data collision. better split into two helpers?
Why?
Quoted 11 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 447
Quoted 7 lines
virt/kvm/eventfd.c +6
-0+{ +/* +* Check for completely non-overlapping regions. We can simply +* return "false" for non-overlapping regions and be done with +* it. +*/ done with it -> ignore the value
I think that is a valid expression (at least here in the states), but ok. Note that "false" means we are accepting the request, not ignoring any value. I will construct a better comment either way.
Quoted 9 lines
Review static void __exit irqfd_module_exit(void) · line 449
Quoted 3 lines
(quoted diff) +2
-0+ if ((rhs->addr + rhs->length) <= lhs->addr) + return false;
rhs->addr+rhs->length<=lhs->addr
is not less clear, as precedence for simple math
follows the familiar rules from school.
Yes, but the "eye compiler" isn't as efficient as a machine driven tool. ;) The annotation is for the readers benefit (or at least me), not technical/mathematical correctness.
But whatever, I'll take it out.
Quoted 7 lines
Review static void __exit irqfd_module_exit(void) · line 451
Quoted 3 lines
(quoted diff) +2
-0+ + if ((lhs->addr + lhs->length) <= rhs->addr)this math can overflow.
Well, we should probably have vetted that during assign since addr+length that overflows is not a valid region. I will put a check in for that.
Review
Quoted 9 lines
Review static void __exit irqfd_module_exit(void) · line 452
Quoted 2 lines
(quoted diff) +1
-0+ return false;or shorter:
(quoted diff) +0
-0if (rhs->addr + rhs->length <= lhs->addr || lhs->addr + lhs->length <= rhs->addr) return true;
Ok
Quoted 8 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void)
Quoted 5 lines
virt/kvm/eventfd.c +4
-0+ +/* +* If we get here, we know there is *some* overlap, but we don't +* yet know how much. how much?
Well, as stated we don't know yet.
Quoted 7 lines
Quoted 3 lines
Make sure its a "precise" overlap, or
precise overlap -> address/len pairs match
Precisely.
Quoted 8 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ * its rejected as incompatible + */"rejected" does not seem to make sense in the context of a boolean function
Why? true = rejected, false = accepted. Seems boolean to me. Whats wrong with that?
Quoted 9 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 464
Quoted 7 lines
virt/kvm/eventfd.c +6
-0+if (lhs->addr != rhs->addr) +return true; + +if (lhs->length != rhs->length) +return true; +or shorter:
Quoted 3 lines
if (lhs->addr != rhs->addr || lhs->length != rhs->length)
return true;Ok
Quoted 19 lines
Quoted 16 lines
virt/kvm/eventfd.c +13
-0+/* +* If we get here, the request should be a precise overlap +* between rhs+lhs. The only thing left to check is for +* data-match overlap. If the data match is distinctly different +* we can allow the two to co-exist. Any kind of wild-card +* consitutes an incompatible range, so reject any wild-cards, +* or if the match token is identical. +*/ +if (lhs->wildcard || rhs->wildcard || lhs->match == rhs->match) +return true; + +return false; +}
Quoted 7 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ +/* assumes kvm->slots_lock write-lock held */it seems you only need read lock?
The caller needs write-lock, so we just inherit that state. I can update the comment though (I just ran a find/replace on "kvm->lock held" while updating to your new interface, thus the vague comment)
Quoted 4 lines
Quoted 4 lines
virt/kvm/eventfd.c +4
-0+static bool +iosignalfd_check_collision (struct kvm *kvm,struct _iosignalfd *p) +{ +struct _iosignalfd *_p;
Quoted 9 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 486
Quoted 4 lines
virt/kvm/eventfd.c +3
-0+ +list_for_each_entry (_p, &kvm->iosignalfds, list) +if (iosignalfd_overlap (_p, p))This looks wrong: let's assume I want one signal with length 1 and one with length 2 at address 0. They never trigger together, so it should be ok to have 2 such devices.
We have previously decided to not support mis-matched overlaps. It's more complicated to handle, and there isn't a compelling use-case for it that I am aware of.
Quoted 25 lines
Quoted 25 lines
virt/kvm/eventfd.c +24
-0+return true; + +return false; +} + +static int +kvm_assign_iosignalfd (struct kvm *kvm,struct kvm_iosignalfd *args) +{ +int pio = args->flags &KVM_IOSIGNALFD_FLAG_PIO ; +struct kvm_io_bus *bus = pio ? &kvm->pio_bus : &kvm->mmio_bus; +struct _iosignalfd *p; +struct eventfd_ctx *eventfd; +int ret; + +switch (args->len) { +case 1 : +case 2 : +case 4 : +case 8 : +break ; +default : +return -EINVAL ; + } +
Quoted 9 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 513
Quoted 4 lines
virt/kvm/eventfd.c +3
-0+ eventfd =eventfd_ctx_fdget (args->fd); +if (IS_ERR (eventfd)) +return PTR_ERR (eventfd);since this eventfd is kept around indefinitely, we should keep the file * around as well, so that this eventfd is accounted for properly with # of open files limit set by the admin.
I agree. The fact that I am missing that is a side-effect to the recent change in eventfd-upstream. If I acquire both a file* and ctx* and hold them, it should work around the issue, but perhaps we should let the eventfd interface handle this.
Quoted 92 lines
Quoted 7 lines
virt/kvm/eventfd.c +5
-0+ + p =kzalloc (sizeof (*p),GFP_KERNEL ); +if (!p) { + ret = -ENOMEM ; + goto fail;virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 528
Quoted 10 lines
virt/kvm/eventfd.c +10
-0+ } + +INIT_LIST_HEAD (&p->list); + p->addr = args->addr; + p->length = args->len; + p->eventfd = eventfd; + +/* +* A trigger address is optional, otherwise this is a wildcard +*/ A single line comment can look like this:
/* A trigger address is optional, otherwise this is a wildcard */virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 530
Quoted 3 lines
virt/kvm/eventfd.c +2
-0+if (args->flags &KVM_IOSIGNALFD_FLAG_TRIGGER ) + p->match = args->trigger;For len < 8, high bits in trigger are ignored. it's better to check that they are 0, less confusing if the user e.g. gets the endian-ness wrong.
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 536
Quoted 10 lines
virt/kvm/eventfd.c +6
-0+else + p->wildcard = true; + +down_write (&kvm->slots_lock); + +/* Verify that there isnt a match already */ Better to put documentation to where function is declared, not where it is used.
Quoted 8 lines
virt/kvm/eventfd.c +7
-0+if (iosignalfd_check_collision (kvm, p)) { + ret = -EEXIST ; + goto unlock_fail; + } + +kvm_iodevice_init (&p->dev, &iosignalfd_ops); +virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 553
Quoted 10 lines
virt/kvm/eventfd.c +10
-0+ ret =__kvm_io_bus_register_dev (bus, &p->dev); +if (ret <0 ) + goto unlock_fail; + +list_add_tail (&p->list, &kvm->iosignalfds); + +up_write (&kvm->slots_lock); + +return 0 ; +we probably do not need an empty line after each line of code here
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 560
Quoted 8 lines
virt/kvm/eventfd.c +7
-0+unlock_fail: +up_write (&kvm->slots_lock); +fail: +/* +* it would have never made it to the list in the failure path, so +* we dont need to worry about removing it +*/ of course: you goto fail before
list_add
can just kill this commentvirt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 565
Quoted 6 lines
virt/kvm/eventfd.c +5
-0+kfree (p); + +eventfd_ctx_put (eventfd); + +return ret;we probably do not need an empty line after each line of code here
Quoted 7 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 369
Quoted 4 lines
virt/kvm/eventfd.c +3
-0+} + +two empty lines
Ack
Quoted 23 lines
Quoted 9 lines
virt/kvm/eventfd.c +7
-0+static int +kvm_deassign_iosignalfd (struct kvm *kvm,struct kvm_iosignalfd *args) +{ +int pio = args->flags &KVM_IOSIGNALFD_FLAG_PIO ; +struct kvm_io_bus *bus = pio ? &kvm->pio_bus : &kvm->mmio_bus; +struct _iosignalfd *p, *tmp; +struct eventfd_ctx *eventfd;virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 585
Quoted 10 lines
virt/kvm/eventfd.c +10
-0+int ret =0 ; + + eventfd =eventfd_ctx_fdget (args->fd); +if (IS_ERR (eventfd)) +return PTR_ERR (eventfd); + +down_write (&kvm->slots_lock); + +list_for_each_entry_safe (p, tmp, &kvm->iosignalfds, list) { +kill empty line
Quoted 9 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 587
Quoted 3 lines
virt/kvm/eventfd.c +2
-0+if (p->eventfd != eventfd) +continue ;So for deassign, you ignore all arguments besides fd? Is this intentional? Looks strange - think of multiple addresses triggering a single eventfd. But if so, it's better to have a different ioctl with just the fields we need.
Hmm... I suspect the check for a range-match got lost along the way. I agree we should probably qualify this with more than just the eventfd.
Quoted 8 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 590
Quoted 5 lines
virt/kvm/eventfd.c +3
-0+ +__kvm_io_bus_unregister_dev (bus, &p->dev); +iosignalfd_release (p);a single deassign removed multiple irqfds? Looks ugly.
Avi requested this general concept.
Quoted 8 lines
Review
Quoted 4 lines
(quoted diff) +2
-0+ } +kill empty line
Quoted 10 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 566
Quoted 7 lines
virt/kvm/eventfd.c +6
-0+up_write (&kvm->slots_lock); + +eventfd_ctx_put (eventfd); + +return ret; +}return error status if no device was found?
Ack
Quoted 13 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 604
Quoted 8 lines
virt/kvm/eventfd.c +6
-0+ +int +kvm_iosignalfd (struct kvm *kvm,struct kvm_iosignalfd *args) +{ +if (args->flags &KVM_IOSIGNALFD_FLAG_DEASSIGN ) +return kvm_deassign_iosignalfd (kvm, args);Better check that only known flag values are present. Otherwise when you add more flags things just break silently.
Ok
Quoted 40 lines
Quoted 18 lines
virt/kvm/eventfd.c +3
-0+ +return kvm_assign_iosignalfd (kvm, args); +}virt/kvm/kvm_main.c +1
-1@@ -979,7 +979,7 @@ static struct kvm *kvm_create_vm(void)spin_lock_init (&kvm->mmu_lock);spin_lock_init (&kvm->requests_lock);kvm_io_bus_init (&kvm->pio_bus); -kvm_irqfd_init (kvm); +kvm_eventfd_init (kvm);mutex_init (&kvm->lock);mutex_init (&kvm->irq_lock);kvm_io_bus_init (&kvm->mmio_bus);virt/kvm/kvm_main.c static long kvm_vm_ioctl(struct file *filp, · line 2278
Quoted 8 lines
virt/kvm/kvm_main.c +4
-0@@ -2271,6 +2271,15 @@ static long kvm_vm_ioctl(struct file *filp, r =kvm_irqfd (kvm, data.fd, data.gsi, data.flags);break ; } +case KVM_IOSIGNALFD : { +struct kvm_iosignalfd data; + + r = -EFAULT ;this trick is nice, it saves a line of code for the closing brace but why waste it on an empty line above then?
Quoted 9 lines
virt/kvm/kvm_main.c +5
-0+if (copy_from_user (&data, argp,sizeof data)) + goto out; + r =kvm_iosignalfd (kvm, &data); +break ; + }#ifdef CONFIG_KVM_APIC_ARCHITECTURE case KVM_SET_BOOT_CPU_ID :r = 0;
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
Quoted 20 lines · Gregory Haskins
Quoted 7 lines · Michael S. Tsirkin
Some comments below. Sorry, I know it's late in the series, but previously I've been too confused with complicated locking to notice anything else :(.
On Mon, Jul 06, 2009 at 04:33:21PM -0400, Gregory Haskins wrote:
Quoted 11 lines
include/linux/kvm.h struct kvm_guest_debug { · line 315
Quoted 6 lines
include/linux/kvm.h +5
-0+#define KVM_IOSIGNALFD_FLAG_PIO (1 << 1)/* is a pio (otherwise mmio) */ +#define KVM_IOSIGNALFD_FLAG_DEASSIGN (1 << 2) + +struct kvm_iosignalfd { +__u64 trigger;for length <8, it's the 8*len least significant bits that are used, right? That's a bit ugly ... Maybe just put an 8 byte array here instead, then the first len bytes are valid.
Quoted 4 lines
The original series uses an array that I kmalloc'ed to size, or left it NULL for a wildcard. Avi didn't like this and requested a u64 for all values. I don't care either way, but since you two are asking for conflicting designs, I will let you debate.
It turns out the io bus will be changed in the future. Let's just document the usage, and check that unused bits are zeroed.
Quoted 8 lines
Quoted 6 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 353
Quoted 3 lines
virt/kvm/eventfd.c +2
-0+struct kvm_io_device dev; + int wildcard:1;don't use bitfields
bool?
sure
Quoted 51 lines
Quoted 11 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 409
Quoted 6 lines
virt/kvm/eventfd.c +5
-0+} + +/* +* MMIO/PIO writes trigger an event if the addr/val match +*/ single line comment can look like this:
/* MMIO/PIO writes trigger an event if the addr/val match */Ack
Quoted 28 lines
Quoted 28 lines
virt/kvm/eventfd.c +28
-0+static int +iosignalfd_write (struct kvm_io_device *this,gpa_t addr,int len, +const void *val) +{ +struct _iosignalfd *p =to_iosignalfd (this); + +if (!iosignalfd_in_range (p, addr, len, val)) +return -EOPNOTSUPP ; + +eventfd_signal (p->eventfd,1 ); +return 0 ; +} + +/* +* This function is called as KVM is completely shutting down. We do not +* need to worry about locking just nuke anything we have as quickly as possible +*/ +static void +iosignalfd_destructor (struct kvm_io_device *this) +{ +struct _iosignalfd *p =to_iosignalfd (this); + +iosignalfd_release (p); +} + +static const struct kvm_io_device_ops iosignalfd_ops = { + .write = iosignalfd_write, + .destructor = iosignalfd_destructor,Quoted 10 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 441
Quoted 5 lines
virt/kvm/eventfd.c +4
-0+}; + +static bool +iosignalfd_overlap (struct _iosignalfd *lhs,struct _iosignalfd *rhs)this checks both region overlap and data collision. better split into two helpers?
Quoted 1 line
Why?
Because it says iosignalfd_overlap but that's not what it does?
Quoted 11 lines
Quoted 11 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 447
Quoted 7 lines
virt/kvm/eventfd.c +6
-0+{ +/* +* Check for completely non-overlapping regions. We can simply +* return "false" for non-overlapping regions and be done with +* it. +*/ done with it -> ignore the value
Quoted 1 line
I think that is a valid expression (at least here in the states),
I'm always interested in improving my english :) here's what I thought:
"done with it" says we skip the rest of the function. "ignore the value" says skip the value check. So I was trying to say let's be more specific.
Isn't that what it means?
Quoted 3 lines
but
ok. Note that "false" means we are accepting the request, not ignoring any value. I will construct a better comment either way.
Maybe name a function in a way that makes this explicit?
Quoted 10 lines
Quoted 7 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ + if ((lhs->addr + lhs->length) <= rhs->addr)this math can overflow.
Well, we should probably have vetted that during assign since addr+length that overflows is not a valid region. I will put a check in for that.
add = ~0x0ULL, len = 1 should be valid.
You'll have to make the math not overflow.
Quoted 9 lines
Quoted 8 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void)
Quoted 5 lines
virt/kvm/eventfd.c +4
-0+ +/* +* If we get here, we know there is *some* overlap, but we don't +* yet know how much. how much?
Well, as stated we don't know yet.
So why tell me :)?
What I mean is this statement (especially the the part of the statement after the comma) does not add useful information.
Quoted 9 lines
Quoted 7 lines
Quoted 3 lines
Make sure its a "precise" overlap, or
precise overlap -> address/len pairs match
Precisely.
so say so :)
Quoted 10 lines
Quoted 8 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ * its rejected as incompatible + */"rejected" does not seem to make sense in the context of a boolean function
Why? true = rejected, false = accepted. Seems boolean to me.
How should I know that? Rename it to iosignalfd_rejected?
Quoted 2 lines
Whats
wrong with that?
If you want to return 0 on success, != 0 on failure, make the function int.
Quoted 11 lines
Quoted 7 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ +/* assumes kvm->slots_lock write-lock held */it seems you only need read lock?
The caller needs write-lock, so we just inherit that state. I can update the comment though (I just ran a find/replace on "
kvm->lockheld" while updating to your new interface, thus the vague comment)
I guess so.
Quoted 14 lines
Quoted 4 lines
Quoted 4 lines
virt/kvm/eventfd.c +4
-0+static bool +iosignalfd_check_collision (struct kvm *kvm,struct _iosignalfd *p) +{ +struct _iosignalfd *_p;Quoted 9 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 486
Quoted 4 lines
virt/kvm/eventfd.c +3
-0+ +list_for_each_entry (_p, &kvm->iosignalfds, list) +if (iosignalfd_overlap (_p, p))This looks wrong: let's assume I want one signal with length 1 and one with length 2 at address 0. They never trigger together, so it should be ok to have 2 such devices.
Quoted 3 lines
We have previously decided to not support mis-matched overlaps. It's more complicated to handle, and there isn't a compelling use-case for it that I am aware of.
That's not what I propose. By all means len = X should only catch len = X and not len = X - 1.
However, I think it makes sense to
allow both len = 2 and len = 1 at the same address even though they seem to overlap. And all you really need to do is simplify the code: replace the tricky overlap logic with simple
if (rhs->addr == lhs->addr && rhs->len == lhs->len)
reject
else
accept
(+add wildcard thing)
Quoted 22 lines
Quoted 9 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 587
Quoted 3 lines
virt/kvm/eventfd.c +2
-0+if (p->eventfd != eventfd) +continue ;So for deassign, you ignore all arguments besides fd? Is this intentional? Looks strange - think of multiple addresses triggering a single eventfd. But if so, it's better to have a different ioctl with just the fields we need.
Hmm... I suspect the check for a range-match got lost along the way. I agree we should probably qualify this with more than just the eventfd.
Quoted 8 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 590
Quoted 5 lines
virt/kvm/eventfd.c +3
-0+ +__kvm_io_bus_unregister_dev (bus, &p->dev); +iosignalfd_release (p);a single deassign removed multiple irqfds? Looks ugly.
Quoted 1 line
Avi requested this general concept.
Really? Avi, could you explain? I would think each assign needs to be matched with 1 deassign. No?
Signature · 1 line
MST
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
Quoted 8 lines · Michael S. Tsirkin
Quoted 8 lines
Quoted 8 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 432
Quoted 5 lines
virt/kvm/eventfd.c +3
-0+ +__kvm_io_bus_unregister_dev (bus,&p->dev); +iosignalfd_release (p);a single deassign removed multiple irqfds? Looks ugly.
Quoted 6 lines
Quoted 2 lines
Avi requested this general concept.
Really? Avi, could you explain? I would think each assign needs to be matched with 1 deassign. No?
Doesn't it follow naturally? How can a single deassign remove multiple fds (unless all were registered with exactly the same arguments)?
Maybe we should instead detect that the duplicate iosignaldfds are registered.
Note that we do need to allow the same fd to be multiple times, but not with exactly the same address/match etc.
Signature · 1 line
error compiling committee.c: too many arguments to function
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
Quoted 9 lines · Avi Kivity
Quoted 8 lines · Michael S. Tsirkin
Quoted 8 lines
Quoted 8 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 432
Quoted 5 lines
virt/kvm/eventfd.c +3
-0+ +__kvm_io_bus_unregister_dev (bus,&p->dev); +iosignalfd_release (p);a single deassign removed multiple irqfds? Looks ugly.
Quoted 8 lines
Quoted 6 lines
Quoted 2 lines
Avi requested this general concept.
Really? Avi, could you explain? I would think each assign needs to be matched with 1 deassign. No?
Doesn't it follow naturally?
Yes.
Quoted 7 lines
How can a single deassign remove multiple
fds (unless all were registered with exactly the same arguments)? Maybe we should instead detect that the duplicate iosignaldfds are registered.Note that we do need to allow the same fd to be multiple times, but not with exactly the same address/match etc.
Signature · 1 line
MST
Re: [KVM PATCH v9 2/2] KVM: add iosignalfd support
In reply to Michael S. TsirkinQuoted 102 lines · Michael S. Tsirkin
Quoted 22 lines · Gregory Haskins
Quoted 8 lines · Michael S. Tsirkin
Some comments below. Sorry, I know it's late in the series, but previously I've been too confused with complicated locking to notice anything else :(.
On Mon, Jul 06, 2009 at 04:33:21PM -0400, Gregory Haskins wrote:
Quoted 12 lines
include/linux/kvm.h struct kvm_guest_debug { · line 315
Quoted 7 lines
include/linux/kvm.h +5
-0+#define KVM_IOSIGNALFD_FLAG_PIO (1 << 1)/* is a pio (otherwise mmio) */ +#define KVM_IOSIGNALFD_FLAG_DEASSIGN (1 << 2) + +struct kvm_iosignalfd { +__u64 trigger;for length <8, it's the 8*len least significant bits that are used, right? That's a bit ugly ... Maybe just put an 8 byte array here instead, then the first len bytes are valid.
Quoted 5 lines
The original series uses an array that I kmalloc'ed to size, or left it NULL for a wildcard. Avi didn't like this and requested a u64 for all values. I don't care either way, but since you two are asking for conflicting designs, I will let you debate.
It turns out the io bus will be changed in the future. Let's just document the usage, and check that unused bits are zeroed.
Quoted 9 lines
Quoted 7 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 353
Quoted 4 lines
virt/kvm/eventfd.c +2
-0+struct kvm_io_device dev; + int wildcard:1;don't use bitfields
bool?
sure
Quoted 54 lines
Quoted 12 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 409
Quoted 7 lines
virt/kvm/eventfd.c +5
-0+} + +/* +* MMIO/PIO writes trigger an event if the addr/val match +*/ single line comment can look like this:
/* MMIO/PIO writes trigger an event if the addr/val match */Ack
Quoted 39 lines
Quoted 24 lines
virt/kvm/eventfd.c +22
-0+static int +iosignalfd_write (struct kvm_io_device *this,gpa_t addr,int len, +const void *val) +{ +struct _iosignalfd *p =to_iosignalfd (this); + +if (!iosignalfd_in_range (p, addr, len, val)) +return -EOPNOTSUPP ; + +eventfd_signal (p->eventfd,1 ); +return 0 ; +} + +/* +* This function is called as KVM is completely shutting down. We do not +* need to worry about locking just nuke anything we have as quickly as possible +*/ +static void +iosignalfd_destructor (struct kvm_io_device *this) +{ +struct _iosignalfd *p =to_iosignalfd (this); +virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 441
Quoted 10 lines
virt/kvm/eventfd.c +10
-0+iosignalfd_release (p); +} + +static const struct kvm_io_device_ops iosignalfd_ops = { + .write = iosignalfd_write, + .destructor = iosignalfd_destructor, +}; + +static bool +iosignalfd_overlap (struct _iosignalfd *lhs,struct _iosignalfd *rhs)this checks both region overlap and data collision. better split into two helpers?
Quoted 5 lines
Quoted 2 lines
Why?
Because it says
iosignalfd_overlapbut that's not what it does?
It would seem to me that that is exactly what it does. Given that I wrote it, I'm sure my perspective is skewed, so let me turn it around on you. Why do you think "overlap" is inaccurate?
Quoted 13 lines
Quoted 13 lines
Quoted 13 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 447
Quoted 9 lines
virt/kvm/eventfd.c +6
-0+{ +/* +* Check for completely non-overlapping regions. We can simply +* return "false" for non-overlapping regions and be done with +* it. +*/ done with it -> ignore the value
Quoted 4 lines
Quoted 2 lines
I think that is a valid expression (at least here in the states),
I'm always interested in improving my english :)
I'm sure its slang and not proper english, so don't take it too seriously ;)
Quoted 8 lines
here's what I thought:
"done with it" says we skip the rest of the function. "ignore the value" says skip the value check. So I was trying to say let's be more specific.
Isn't that what it means?
Yes, you are right. I thought you were saying the comment was somehow wrong. But I see now you are just clarifying it.
Quoted 9 lines
Quoted 5 lines
but
ok. Note that "false" means we are accepting the request, not ignoring any value. I will construct a better comment either way.Maybe name a function in a way that makes this explicit?
Sure
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Review
Quoted 4 lines
(quoted diff) +2
-0+ + if ((lhs->addr + lhs->length) <= rhs->addr)this math can overflow.
Quoted 9 lines
Quoted 4 lines
Well, we should probably have vetted that during assign since addr+length that overflows is not a valid region. I will put a check in for that.
add = ~0x0ULL, len = 1 should be valid.
You'll have to make the math not overflow.
Yes, understood.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void)
Quoted 6 lines
virt/kvm/eventfd.c +4
-0+ +/* +* If we get here, we know there is *some* overlap, but we don't +* yet know how much. how much?
Quoted 7 lines
Quoted 2 lines
Well, as stated we don't know yet.
So why tell me :)?
What I mean is this statement (especially the the part of the statement after the comma) does not add useful information.
What I was trying to convey is that the next section of code tries to narrow the amount of overlap down further. If it bothers you, I will just remove the comment.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Make sure its a "precise" overlap, or
Quoted 9 lines
Quoted 6 lines
Quoted 4 lines
precise overlap -> address/len pairs match
Precisely.
so say so :)
Ok
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Review
Quoted 5 lines
(quoted diff) +2
-0+ * its rejected as incompatible + */"rejected" does not seem to make sense in the context of a boolean function
Quoted 5 lines
Quoted 2 lines
Why? true = rejected, false = accepted. Seems boolean to me.
How should I know that? Rename it to
iosignalfd_rejected?
Dunno.. Seems clear to me already: collision = true if overlap = true. collision = reject the request to create a new object on grounds that we already have one in that spot. I don't really care what we call it, but I don't currently see a superior way to describe what I am doing that isn't just a synonym.
Quoted 9 lines
Quoted 4 lines
Whats
wrong with that?If you want to return 0 on success, != 0 on failure, make the function int.
I don't want that. I want to know true or false on whether we have a collision. A collision is defined by whether there is overlap with any existing object.
Quoted 43 lines
Quoted 8 lines
Quoted 8 lines
Review
Quoted 4 lines
(quoted diff) +2
-0+ +/* assumes kvm->slots_lock write-lock held */it seems you only need read lock?
Quoted 4 lines
The caller needs write-lock, so we just inherit that state. I can update the comment though (I just ran a find/replace on "
kvm->lockheld" while updating to your new interface, thus the vague comment)I guess so.
Quoted 14 lines
Quoted 4 lines
Quoted 4 lines
virt/kvm/eventfd.c +4
-0+static bool +iosignalfd_check_collision (struct kvm *kvm,struct _iosignalfd *p) +{ +struct _iosignalfd *_p;Quoted 10 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 486
Quoted 5 lines
virt/kvm/eventfd.c +3
-0+ +list_for_each_entry (_p, &kvm->iosignalfds, list) +if (iosignalfd_overlap (_p, p))This looks wrong: let's assume I want one signal with length 1 and one with length 2 at address 0. They never trigger together, so it should be ok to have 2 such devices.
Quoted 4 lines
We have previously decided to not support mis-matched overlaps. It's more complicated to handle, and there isn't a compelling use-case for it that I am aware of.
That's not what I propose. By all means len = X should only catch len = X and not len = X - 1.
However, I think it makes sense to
allow both len = 2 and len = 1 at the same address even though they seem to overlap. And all you really need to do is simplify the code: replace the tricky overlap logic with simple
Quoted 7 lines
if (
rhs->addr==lhs->addr&&rhs->len==lhs->len)
reject
else
accept(+add wildcard thing)
Hmm..ok. I can't imagine anyone using that, but it seems simple enough to implement.
Quoted 32 lines
Quoted 25 lines
Quoted 11 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 587
Quoted 5 lines
virt/kvm/eventfd.c +2
-0+if (p->eventfd != eventfd) +continue ;So for deassign, you ignore all arguments besides fd? Is this intentional? Looks strange - think of multiple addresses triggering a single eventfd. But if so, it's better to have a different ioctl with just the fields we need.
Hmm... I suspect the check for a range-match got lost along the way. I agree we should probably qualify this with more than just the eventfd.
Quoted 10 lines
virt/kvm/eventfd.c static void __exit irqfd_module_exit(void) · line 590
Quoted 7 lines
virt/kvm/eventfd.c +3
-0+ +__kvm_io_bus_unregister_dev (bus, &p->dev); +iosignalfd_release (p);a single deassign removed multiple irqfds? Looks ugly.
Quoted 2 lines
Avi requested this general concept.
Really? Avi, could you explain? I would think each assign needs to be matched with 1 deassign. No?
Quoted 5 lines · Gregory Haskins
(Applies to kvm.git/master:c5b13264e)
This is v9 of the series. For more details, please see the header to patch 2/2.
Quoted 9 lines
This series has been tested against the kvm-eventfd unit test, and appears to be functioning properly. You can download this test here:
ftp://ftp.novell.com/dev/ghaskins/kvm-eventfd.tar.bz2
(Note: unit test has been updated to accomodate new feature-set)
Please consider for inclusion to kvm.git
Looks good to me, but would appreciate a second opinion from Michael or anyone else who wants to review.
Signature · 1 line
error compiling committee.c: too many arguments to function