KVM: PPC: Book3S HV: XIVE: Add a control to sync the sources
authorCédric Le Goater <clg@kaod.org>
Thu, 18 Apr 2019 10:39:33 +0000 (12:39 +0200)
committerPaul Mackerras <paulus@ozlabs.org>
Tue, 30 Apr 2019 09:35:16 +0000 (19:35 +1000)
This control will be used by the H_INT_SYNC hcall from QEMU to flush
event notifications on the XIVE IC owning the source.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Documentation/virtual/kvm/devices/xive.txt
arch/powerpc/include/uapi/asm/kvm.h
arch/powerpc/kvm/book3s_xive_native.c

index 429cbc4..1e7f19d 100644 (file)
@@ -92,3 +92,11 @@ the legacy interrupt mode, referred as XICS (POWER7/8).
     -EINVAL: Invalid queue address
     -EFAULT: Invalid user pointer for attr->addr.
     -EIO:    Configuration of the underlying HW failed
+
+  5. KVM_DEV_XIVE_GRP_SOURCE_SYNC (write only)
+  Synchronize the source to flush event notifications
+  Attributes:
+    Interrupt source number  (64-bit)
+  Errors:
+    -ENOENT: Unknown source number
+    -EINVAL: Not initialized source number
index f045f9d..e4abe30 100644 (file)
@@ -683,6 +683,7 @@ struct kvm_ppc_cpu_char {
 #define KVM_DEV_XIVE_GRP_SOURCE                2       /* 64-bit source identifier */
 #define KVM_DEV_XIVE_GRP_SOURCE_CONFIG 3       /* 64-bit source identifier */
 #define KVM_DEV_XIVE_GRP_EQ_CONFIG     4       /* 64-bit EQ identifier */
+#define KVM_DEV_XIVE_GRP_SOURCE_SYNC   5       /* 64-bit source identifier */
 
 /* Layout of 64-bit XIVE source attribute values */
 #define KVM_XIVE_LEVEL_SENSITIVE       (1ULL << 0)
index b9597d8..6538041 100644 (file)
@@ -335,6 +335,38 @@ static int kvmppc_xive_native_set_source_config(struct kvmppc_xive *xive,
                                                       priority, masked, eisn);
 }
 
+static int kvmppc_xive_native_sync_source(struct kvmppc_xive *xive,
+                                         long irq, u64 addr)
+{
+       struct kvmppc_xive_src_block *sb;
+       struct kvmppc_xive_irq_state *state;
+       struct xive_irq_data *xd;
+       u32 hw_num;
+       u16 src;
+       int rc = 0;
+
+       pr_devel("%s irq=0x%lx", __func__, irq);
+
+       sb = kvmppc_xive_find_source(xive, irq, &src);
+       if (!sb)
+               return -ENOENT;
+
+       state = &sb->irq_state[src];
+
+       rc = -EINVAL;
+
+       arch_spin_lock(&sb->lock);
+
+       if (state->valid) {
+               kvmppc_xive_select_irq(state, &hw_num, &xd);
+               xive_native_sync_source(hw_num);
+               rc = 0;
+       }
+
+       arch_spin_unlock(&sb->lock);
+       return rc;
+}
+
 static int xive_native_validate_queue_size(u32 qshift)
 {
        /*
@@ -670,6 +702,9 @@ static int kvmppc_xive_native_set_attr(struct kvm_device *dev,
        case KVM_DEV_XIVE_GRP_EQ_CONFIG:
                return kvmppc_xive_native_set_queue_config(xive, attr->attr,
                                                           attr->addr);
+       case KVM_DEV_XIVE_GRP_SOURCE_SYNC:
+               return kvmppc_xive_native_sync_source(xive, attr->attr,
+                                                     attr->addr);
        }
        return -ENXIO;
 }
@@ -699,6 +734,7 @@ static int kvmppc_xive_native_has_attr(struct kvm_device *dev,
                break;
        case KVM_DEV_XIVE_GRP_SOURCE:
        case KVM_DEV_XIVE_GRP_SOURCE_CONFIG:
+       case KVM_DEV_XIVE_GRP_SOURCE_SYNC:
                if (attr->attr >= KVMPPC_XIVE_FIRST_IRQ &&
                    attr->attr < KVMPPC_XIVE_NR_IRQS)
                        return 0;