Merge tag 'kvm-4.9-1' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[cascardo/linux.git] / drivers / iommu / amd_iommu_types.h
index 9652848..0d91785 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <linux/types.h>
 #include <linux/mutex.h>
+#include <linux/msi.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/pci.h>
@@ -69,6 +70,8 @@
 #define MMIO_EXCL_LIMIT_OFFSET  0x0028
 #define MMIO_EXT_FEATURES      0x0030
 #define MMIO_PPR_LOG_OFFSET    0x0038
+#define MMIO_GA_LOG_BASE_OFFSET        0x00e0
+#define MMIO_GA_LOG_TAIL_OFFSET        0x00e8
 #define MMIO_CMD_HEAD_OFFSET   0x2000
 #define MMIO_CMD_TAIL_OFFSET   0x2008
 #define MMIO_EVT_HEAD_OFFSET   0x2010
@@ -76,6 +79,8 @@
 #define MMIO_STATUS_OFFSET     0x2020
 #define MMIO_PPR_HEAD_OFFSET   0x2030
 #define MMIO_PPR_TAIL_OFFSET   0x2038
+#define MMIO_GA_HEAD_OFFSET    0x2040
+#define MMIO_GA_TAIL_OFFSET    0x2048
 #define MMIO_CNTR_CONF_OFFSET  0x4000
 #define MMIO_CNTR_REG_OFFSET   0x40000
 #define MMIO_REG_END_OFFSET    0x80000
@@ -92,6 +97,7 @@
 #define FEATURE_GA             (1ULL<<7)
 #define FEATURE_HE             (1ULL<<8)
 #define FEATURE_PC             (1ULL<<9)
+#define FEATURE_GAM_VAPIC      (1ULL<<21)
 
 #define FEATURE_PASID_SHIFT    32
 #define FEATURE_PASID_MASK     (0x1fULL << FEATURE_PASID_SHIFT)
 #define MMIO_STATUS_EVT_INT_MASK       (1 << 1)
 #define MMIO_STATUS_COM_WAIT_INT_MASK  (1 << 2)
 #define MMIO_STATUS_PPR_INT_MASK       (1 << 6)
+#define MMIO_STATUS_GALOG_RUN_MASK     (1 << 8)
+#define MMIO_STATUS_GALOG_OVERFLOW_MASK        (1 << 9)
+#define MMIO_STATUS_GALOG_INT_MASK     (1 << 10)
 
 /* event logging constants */
 #define EVENT_ENTRY_SIZE       0x10
 #define CONTROL_PPFINT_EN       0x0eULL
 #define CONTROL_PPR_EN          0x0fULL
 #define CONTROL_GT_EN           0x10ULL
+#define CONTROL_GA_EN           0x11ULL
+#define CONTROL_GAM_EN          0x19ULL
+#define CONTROL_GALOG_EN        0x1CULL
+#define CONTROL_GAINT_EN        0x1DULL
 
 #define CTRL_INV_TO_MASK       (7 << CONTROL_INV_TIMEOUT)
 #define CTRL_INV_TO_NONE       0
 
 #define PPR_REQ_FAULT          0x01
 
+/* Constants for GA Log handling */
+#define GA_LOG_ENTRIES         512
+#define GA_LOG_SIZE_SHIFT      56
+#define GA_LOG_SIZE_512                (0x8ULL << GA_LOG_SIZE_SHIFT)
+#define GA_ENTRY_SIZE          8
+#define GA_LOG_SIZE            (GA_ENTRY_SIZE * GA_LOG_ENTRIES)
+
+#define GA_TAG(x)              (u32)(x & 0xffffffffULL)
+#define GA_DEVID(x)            (u16)(((x) >> 32) & 0xffffULL)
+#define GA_REQ_TYPE(x)         (((x) >> 60) & 0xfULL)
+
+#define GA_GUEST_NR            0x1
+
 #define PAGE_MODE_NONE    0x00
 #define PAGE_MODE_1_LEVEL 0x01
 #define PAGE_MODE_2_LEVEL 0x02
 #define IOMMU_CAP_NPCACHE 26
 #define IOMMU_CAP_EFR     27
 
+/* IOMMU Feature Reporting Field (for IVHD type 10h */
+#define IOMMU_FEAT_GASUP_SHIFT 6
+
+/* IOMMU Extended Feature Register (EFR) */
+#define IOMMU_EFR_GASUP_SHIFT  7
+
 #define MAX_DOMAIN_ID 65536
 
 /* Protection domain flags */
@@ -400,6 +432,7 @@ struct amd_iommu_fault {
 
 struct iommu_domain;
 struct irq_domain;
+struct amd_irte_ops;
 
 /*
  * This structure contains generic data for  IOMMU protection domains
@@ -490,6 +523,12 @@ struct amd_iommu {
        /* Base of the PPR log, if present */
        u8 *ppr_log;
 
+       /* Base of the GA log, if present */
+       u8 *ga_log;
+
+       /* Tail of the GA log, if present */
+       u8 *ga_log_tail;
+
        /* true if interrupts for this IOMMU are already enabled */
        bool int_enabled;
 
@@ -523,6 +562,8 @@ struct amd_iommu {
 #ifdef CONFIG_IRQ_REMAP
        struct irq_domain *ir_domain;
        struct irq_domain *msi_domain;
+
+       struct amd_irte_ops *irte_ops;
 #endif
 
        volatile u64 __aligned(8) cmd_sem;
@@ -683,4 +724,112 @@ static inline int get_hpet_devid(int id)
        return -EINVAL;
 }
 
+enum amd_iommu_intr_mode_type {
+       AMD_IOMMU_GUEST_IR_LEGACY,
+
+       /* This mode is not visible to users. It is used when
+        * we cannot fully enable vAPIC and fallback to only support
+        * legacy interrupt remapping via 128-bit IRTE.
+        */
+       AMD_IOMMU_GUEST_IR_LEGACY_GA,
+       AMD_IOMMU_GUEST_IR_VAPIC,
+};
+
+#define AMD_IOMMU_GUEST_IR_GA(x)       (x == AMD_IOMMU_GUEST_IR_VAPIC || \
+                                        x == AMD_IOMMU_GUEST_IR_LEGACY_GA)
+
+#define AMD_IOMMU_GUEST_IR_VAPIC(x)    (x == AMD_IOMMU_GUEST_IR_VAPIC)
+
+union irte {
+       u32 val;
+       struct {
+               u32 valid       : 1,
+                   no_fault    : 1,
+                   int_type    : 3,
+                   rq_eoi      : 1,
+                   dm          : 1,
+                   rsvd_1      : 1,
+                   destination : 8,
+                   vector      : 8,
+                   rsvd_2      : 8;
+       } fields;
+};
+
+union irte_ga_lo {
+       u64 val;
+
+       /* For int remapping */
+       struct {
+               u64 valid       : 1,
+                   no_fault    : 1,
+                   /* ------ */
+                   int_type    : 3,
+                   rq_eoi      : 1,
+                   dm          : 1,
+                   /* ------ */
+                   guest_mode  : 1,
+                   destination : 8,
+                   rsvd        : 48;
+       } fields_remap;
+
+       /* For guest vAPIC */
+       struct {
+               u64 valid       : 1,
+                   no_fault    : 1,
+                   /* ------ */
+                   ga_log_intr : 1,
+                   rsvd1       : 3,
+                   is_run      : 1,
+                   /* ------ */
+                   guest_mode  : 1,
+                   destination : 8,
+                   rsvd2       : 16,
+                   ga_tag      : 32;
+       } fields_vapic;
+};
+
+union irte_ga_hi {
+       u64 val;
+       struct {
+               u64 vector      : 8,
+                   rsvd_1      : 4,
+                   ga_root_ptr : 40,
+                   rsvd_2      : 12;
+       } fields;
+};
+
+struct irte_ga {
+       union irte_ga_lo lo;
+       union irte_ga_hi hi;
+};
+
+struct irq_2_irte {
+       u16 devid; /* Device ID for IRTE table */
+       u16 index; /* Index into IRTE table*/
+};
+
+struct amd_ir_data {
+       u32 cached_ga_tag;
+       struct irq_2_irte irq_2_irte;
+       struct msi_msg msi_entry;
+       void *entry;    /* Pointer to union irte or struct irte_ga */
+       void *ref;      /* Pointer to the actual irte */
+};
+
+struct amd_irte_ops {
+       void (*prepare)(void *, u32, u32, u8, u32, int);
+       void (*activate)(void *, u16, u16);
+       void (*deactivate)(void *, u16, u16);
+       void (*set_affinity)(void *, u16, u16, u8, u32);
+       void *(*get)(struct irq_remap_table *, int);
+       void (*set_allocated)(struct irq_remap_table *, int);
+       bool (*is_allocated)(struct irq_remap_table *, int);
+       void (*clear_allocated)(struct irq_remap_table *, int);
+};
+
+#ifdef CONFIG_IRQ_REMAP
+extern struct amd_irte_ops irte_32_ops;
+extern struct amd_irte_ops irte_128_ops;
+#endif
+
 #endif /* _ASM_X86_AMD_IOMMU_TYPES_H */