Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / include / kvm / arm_vgic.h
index 5142e2a..540da51 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <kvm/iodev.h>
+#include <linux/list.h>
 
 #define VGIC_V3_MAX_CPUS       255
 #define VGIC_V2_MAX_CPUS       8
@@ -76,6 +77,7 @@ enum vgic_irq_config {
 
 struct vgic_irq {
        spinlock_t irq_lock;            /* Protects the content of the struct */
+       struct list_head lpi_list;      /* Used to link all LPIs together */
        struct list_head ap_list;
 
        struct kvm_vcpu *vcpu;          /* SGIs and PPIs: The VCPU
@@ -96,6 +98,7 @@ struct vgic_irq {
        bool active;                    /* not used for LPIs */
        bool enabled;
        bool hw;                        /* Tied to HW IRQ */
+       struct kref refcount;           /* Used for LPIs */
        u32 hwintid;                    /* HW INTID number */
        union {
                u8 targets;                     /* GICv2 target VCPUs mask */
@@ -107,15 +110,52 @@ struct vgic_irq {
 };
 
 struct vgic_register_region;
+struct vgic_its;
+
+enum iodev_type {
+       IODEV_CPUIF,
+       IODEV_DIST,
+       IODEV_REDIST,
+       IODEV_ITS
+};
 
 struct vgic_io_device {
        gpa_t base_addr;
-       struct kvm_vcpu *redist_vcpu;
+       union {
+               struct kvm_vcpu *redist_vcpu;
+               struct vgic_its *its;
+       };
        const struct vgic_register_region *regions;
+       enum iodev_type iodev_type;
        int nr_regions;
        struct kvm_io_device dev;
 };
 
+struct vgic_its {
+       /* The base address of the ITS control register frame */
+       gpa_t                   vgic_its_base;
+
+       bool                    enabled;
+       bool                    initialized;
+       struct vgic_io_device   iodev;
+       struct kvm_device       *dev;
+
+       /* These registers correspond to GITS_BASER{0,1} */
+       u64                     baser_device_table;
+       u64                     baser_coll_table;
+
+       /* Protects the command queue */
+       struct mutex            cmd_lock;
+       u64                     cbaser;
+       u32                     creadr;
+       u32                     cwriter;
+
+       /* Protects the device and collection lists */
+       struct mutex            its_lock;
+       struct list_head        device_list;
+       struct list_head        collection_list;
+};
+
 struct vgic_dist {
        bool                    in_kernel;
        bool                    ready;
@@ -124,6 +164,9 @@ struct vgic_dist {
        /* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
        u32                     vgic_model;
 
+       /* Do injected MSIs require an additional device ID? */
+       bool                    msis_require_devid;
+
        int                     nr_spis;
 
        /* TODO: Consider moving to global state */
@@ -145,6 +188,21 @@ struct vgic_dist {
        struct vgic_irq         *spis;
 
        struct vgic_io_device   dist_iodev;
+
+       bool                    has_its;
+
+       /*
+        * Contains the attributes and gpa of the LPI configuration table.
+        * Since we report GICR_TYPER.CommonLPIAff as 0b00, we can share
+        * one address across all redistributors.
+        * GICv3 spec: 6.1.2 "LPI Configuration tables"
+        */
+       u64                     propbaser;
+
+       /* Protects the lpi_list and the count value below. */
+       spinlock_t              lpi_list_lock;
+       struct list_head        lpi_list_head;
+       int                     lpi_list_count;
 };
 
 struct vgic_v2_cpu_if {
@@ -199,6 +257,11 @@ struct vgic_cpu {
         */
        struct vgic_io_device   rd_iodev;
        struct vgic_io_device   sgi_iodev;
+
+       /* Contains the attributes and gpa of the LPI pending tables. */
+       u64 pendbaser;
+
+       bool lpis_enabled;
 };
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
@@ -249,4 +312,6 @@ static inline int kvm_vgic_get_max_vcpus(void)
        return kvm_vgic_global_state.max_gic_vcpus;
 }
 
+int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
+
 #endif /* __KVM_ARM_VGIC_H */