Commit fb43cf73 authored by Liu, Yi L's avatar Liu, Yi L Committed by Michael S. Tsirkin
Browse files

intel_iommu: scalable mode emulation



Intel(R) VT-d 3.0 spec introduces scalable mode address translation to
replace extended context mode. This patch extends current emulator to
support Scalable Mode which includes root table, context table and new
pasid table format change. Now intel_iommu emulates both legacy mode
and scalable mode (with legacy-equivalent capability set).

The key points are below:
1. Extend root table operations to support both legacy mode and scalable
   mode.
2. Extend context table operations to support both legacy mode and
   scalable mode.
3. Add pasid tabled operations to support scalable mode.

Signed-off-by: default avatarLiu, Yi L <yi.l.liu@intel.com>
[Yi Sun is co-developer to contribute much to refine the whole commit.]
Signed-off-by: default avatarYi Sun <yi.y.sun@linux.intel.com>
Message-Id: <1551753295-30167-2-git-send-email-yi.y.sun@linux.intel.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Reviewed-by: default avatarPeter Xu <peterx@redhat.com>
parent b13919ab
Loading
Loading
Loading
Loading
+402 −92

File changed.

Preview size limit exceeded, changes collapsed.

+39 −2
Original line number Diff line number Diff line
@@ -172,6 +172,7 @@

/* RTADDR_REG */
#define VTD_RTADDR_RTT              (1ULL << 11)
#define VTD_RTADDR_SMT              (1ULL << 10)
#define VTD_RTADDR_ADDR_MASK(aw)    (VTD_HAW_MASK(aw) ^ 0xfffULL)

/* IRTA_REG */
@@ -294,6 +295,8 @@ typedef enum VTDFaultReason {
                                  * request while disabled */
    VTD_FR_IR_SID_ERR = 0x26,   /* Invalid Source-ID */

    VTD_FR_PASID_TABLE_INV = 0x58,  /*Invalid PASID table entry */

    /* This is not a normal fault reason. We use this to indicate some faults
     * that are not referenced by the VT-d specification.
     * Fault event with such reason should not be recorded.
@@ -411,8 +414,8 @@ typedef struct VTDIOTLBPageInvInfo VTDIOTLBPageInvInfo;
#define VTD_PAGE_MASK_1G            (~((1ULL << VTD_PAGE_SHIFT_1G) - 1))

struct VTDRootEntry {
    uint64_t val;
    uint64_t rsvd;
    uint64_t lo;
    uint64_t hi;
};
typedef struct VTDRootEntry VTDRootEntry;

@@ -423,6 +426,8 @@ typedef struct VTDRootEntry VTDRootEntry;
#define VTD_ROOT_ENTRY_NR           (VTD_PAGE_SIZE / sizeof(VTDRootEntry))
#define VTD_ROOT_ENTRY_RSVD(aw)     (0xffeULL | ~VTD_HAW_MASK(aw))

#define VTD_DEVFN_CHECK_MASK        0x80

/* Masks for struct VTDContextEntry */
/* lo */
#define VTD_CONTEXT_ENTRY_P         (1ULL << 0)
@@ -441,6 +446,38 @@ typedef struct VTDRootEntry VTDRootEntry;

#define VTD_CONTEXT_ENTRY_NR        (VTD_PAGE_SIZE / sizeof(VTDContextEntry))

#define VTD_CTX_ENTRY_LEGACY_SIZE     16
#define VTD_CTX_ENTRY_SCALABLE_SIZE   32

#define VTD_SM_CONTEXT_ENTRY_RID2PASID_MASK 0xfffff
#define VTD_SM_CONTEXT_ENTRY_RSVD_VAL0(aw)  (0x1e0ULL | ~VTD_HAW_MASK(aw))
#define VTD_SM_CONTEXT_ENTRY_RSVD_VAL1      0xffffffffffe00000ULL

/* PASID Table Related Definitions */
#define VTD_PASID_DIR_BASE_ADDR_MASK  (~0xfffULL)
#define VTD_PASID_TABLE_BASE_ADDR_MASK (~0xfffULL)
#define VTD_PASID_DIR_ENTRY_SIZE      8
#define VTD_PASID_ENTRY_SIZE          64
#define VTD_PASID_DIR_BITS_MASK       (0x3fffULL)
#define VTD_PASID_DIR_INDEX(pasid)    (((pasid) >> 6) & VTD_PASID_DIR_BITS_MASK)
#define VTD_PASID_DIR_FPD             (1ULL << 1) /* Fault Processing Disable */
#define VTD_PASID_TABLE_BITS_MASK     (0x3fULL)
#define VTD_PASID_TABLE_INDEX(pasid)  ((pasid) & VTD_PASID_TABLE_BITS_MASK)
#define VTD_PASID_ENTRY_FPD           (1ULL << 1) /* Fault Processing Disable */

/* PASID Granular Translation Type Mask */
#define VTD_SM_PASID_ENTRY_PGTT        (7ULL << 6)
#define VTD_SM_PASID_ENTRY_FLT         (1ULL << 6)
#define VTD_SM_PASID_ENTRY_SLT         (2ULL << 6)
#define VTD_SM_PASID_ENTRY_NESTED      (3ULL << 6)
#define VTD_SM_PASID_ENTRY_PT          (4ULL << 6)

#define VTD_SM_PASID_ENTRY_AW          7ULL /* Adjusted guest-address-width */
#define VTD_SM_PASID_ENTRY_DID(val)    ((val) & VTD_DOMAIN_ID_MASK)

/* Second Level Page Translation Pointer*/
#define VTD_SM_PASID_ENTRY_SLPTPTR     (~0xfffULL)

/* Paging Structure common */
#define VTD_SL_PT_PAGE_SIZE_MASK    (1ULL << 7)
/* Bits to decide the offset for each level */
+1 −1
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ vtd_iotlb_cc_hit(uint8_t bus, uint8_t devfn, uint64_t high, uint64_t low, uint32
vtd_iotlb_cc_update(uint8_t bus, uint8_t devfn, uint64_t high, uint64_t low, uint32_t gen1, uint32_t gen2) "IOTLB context update bus 0x%"PRIx8" devfn 0x%"PRIx8" high 0x%"PRIx64" low 0x%"PRIx64" gen %"PRIu32" -> gen %"PRIu32
vtd_iotlb_reset(const char *reason) "IOTLB reset (reason: %s)"
vtd_fault_disabled(void) "Fault processing disabled for context entry"
vtd_replay_ce_valid(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t domain, uint64_t hi, uint64_t lo) "replay valid context device %02"PRIx8":%02"PRIx8".%02"PRIx8" domain 0x%"PRIx16" hi 0x%"PRIx64" lo 0x%"PRIx64
vtd_replay_ce_valid(const char *mode, uint8_t bus, uint8_t dev, uint8_t fn, uint16_t domain, uint64_t hi, uint64_t lo) "%s: replay valid context device %02"PRIx8":%02"PRIx8".%02"PRIx8" domain 0x%"PRIx16" hi 0x%"PRIx64" lo 0x%"PRIx64
vtd_replay_ce_invalid(uint8_t bus, uint8_t dev, uint8_t fn) "replay invalid context device %02"PRIx8":%02"PRIx8".%02"PRIx8
vtd_page_walk_level(uint64_t addr, uint32_t level, uint64_t start, uint64_t end) "walk (base=0x%"PRIx64", level=%"PRIu32") iova range 0x%"PRIx64" - 0x%"PRIx64
vtd_page_walk_one(uint16_t domain, uint64_t iova, uint64_t gpa, uint64_t mask, int perm) "domain 0x%"PRIu16" iova 0x%"PRIx64" -> gpa 0x%"PRIx64" mask 0x%"PRIx64" perm %d"
+22 −2
Original line number Diff line number Diff line
@@ -66,12 +66,21 @@ typedef struct VTDIOTLBEntry VTDIOTLBEntry;
typedef struct VTDBus VTDBus;
typedef union VTD_IR_TableEntry VTD_IR_TableEntry;
typedef union VTD_IR_MSIAddress VTD_IR_MSIAddress;
typedef struct VTDPASIDDirEntry VTDPASIDDirEntry;
typedef struct VTDPASIDEntry VTDPASIDEntry;

/* Context-Entry */
struct VTDContextEntry {
    union {
        struct {
            uint64_t lo;
            uint64_t hi;
        };
        struct {
            uint64_t val[4];
        };
    };
};

struct VTDContextCacheEntry {
    /* The cache entry is obsolete if
@@ -81,6 +90,16 @@ struct VTDContextCacheEntry {
    struct VTDContextEntry context_entry;
};

/* PASID Directory Entry */
struct VTDPASIDDirEntry {
    uint64_t val;
};

/* PASID Table Entry */
struct VTDPASIDEntry {
    uint64_t val[8];
};

struct VTDAddressSpace {
    PCIBus *bus;
    uint8_t devfn;
@@ -212,6 +231,7 @@ struct IntelIOMMUState {

    dma_addr_t root;                /* Current root table pointer */
    bool root_extended;             /* Type of root table (extended or not) */
    bool root_scalable;             /* Type of root table (scalable or not) */
    bool dmar_enabled;              /* Set if DMA remapping is enabled */

    uint16_t iq_head;               /* Current invalidation queue head */