hv: Use Interrupt Remapping format for programming interrupt sources

When a corresponding IOMMU is found for the device, this patch adds
support to program Interrupt Remapping hardware RTEs and the original
interrupt sources (MSI or IOAPIC) with IR format.

Tracked-On: #2426
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
Reviewed-by: Binbin Wu <binbin.wu@intel.com>
This commit is contained in:
Sainath Grandhi
2019-01-15 12:51:25 -08:00
committed by Eddie Dong
parent 7104f0a512
commit 970821462b
9 changed files with 350 additions and 25 deletions

View File

@@ -209,6 +209,19 @@ union ioapic_rte {
uint64_t rsvd_1:39;
uint64_t dest_field:8;
} bits __packed;
struct {
uint32_t vector:8;
uint32_t constant:3;
uint32_t intr_index_high:1;
uint32_t intr_polarity:1;
uint32_t remote_irr:1;
uint32_t trigger_mode:1;
uint32_t intr_mask:1;
uint32_t rsvd_1:15;
uint32_t rsvd_2:16;
uint32_t intr_format:1;
uint32_t intr_index_low:15;
} ir_bits __packed;
};
/******************************************************************************

View File

@@ -21,6 +21,7 @@ void ioapic_setup_irqs(void);
bool ioapic_irq_is_gsi(uint32_t irq);
uint32_t ioapic_irq_to_pin(uint32_t irq);
int32_t init_ioapic_id_info(void);
uint8_t ioapic_irq_to_ioapic_id(uint32_t irq);
/**
* @brief Get irq num from pin num

View File

@@ -347,6 +347,11 @@ static inline uint8_t dma_iotlb_invl_addr_am(uint8_t am)
return (am & 0x3fU);
}
static inline uint64_t dma_iec_index(uint16_t index, uint8_t index_mask)
{
return ((((uint64_t)index & 0xFFFFU) << 32U) | (((uint64_t)index_mask & 0x1FU) << 27U));
}
#define DMA_IOTLB_INVL_ADDR_IH_UNMODIFIED (((uint64_t)1UL) << 6U)
/* FECTL_REG */
@@ -474,6 +479,31 @@ struct dmar_info {
struct dmar_drhd *drhd_units;
};
union dmar_ir_entry {
struct {
uint64_t lower;
uint64_t upper;
} entry;
struct {
uint64_t present:1;
uint64_t fpd:1;
uint64_t dest_mode:1;
uint64_t rh:1;
uint64_t trigger_mode:1;
uint64_t delivery_mode:3;
uint64_t sw_bits:4;
uint64_t rsvd_1:3;
uint64_t mode:1;
uint64_t vector:8;
uint64_t rsvd_2:8;
uint64_t dest:32;
uint64_t sid:16;
uint64_t sq:2;
uint64_t svt:2;
uint64_t rsvd_3:44;
} bits __packed;
};
extern struct dmar_info *get_dmar_info(void);
/**
@@ -635,6 +665,27 @@ void init_iommu_sos_vm_domain(struct acrn_vm *sos_vm);
*/
bool iommu_snoop_supported(const struct acrn_vm *vm);
/**
* @brief Assign RTE for Interrupt Remapping Table.
*
* @param[in] intr_src filled with type of interrupt source and the source
* @param[in] irte filled with info about interrupt deliverymode, destination and destination mode
* @param[in] index into Interrupt Remapping Table
*
* @retval -EINVAL if corresponding DMAR is not present
* @retval 0 otherwise
*
*/
int32_t dmar_assign_irte(struct intr_source intr_src, union dmar_ir_entry irte, uint16_t index);
/**
* @brief Free RTE for Interrupt Remapping Table.
*
* @param[in] intr_src filled with type of interrupt source and the source
* @param[in] index into Interrupt Remapping Table
*
*/
void dmar_free_irte(struct intr_source intr_src, uint16_t index);
/**
* @}
*/

View File

@@ -23,6 +23,24 @@ union source_id (name) = {.msi_id = {.bdf = (a), .entry_nr = (b)} }
#define DEFINE_IOAPIC_SID(name, a, b) \
union source_id (name) = {.intx_id = {.pin = (a), .src = (b)} }
union source {
uint16_t ioapic_id;
union pci_bdf msi;
};
struct intr_source {
bool is_msi;
union source src;
};
union irte_index {
uint16_t index;
struct {
uint16_t index_low:15;
uint16_t index_high:1;
} bits __packed;
};
union source_id {
uint64_t value;
struct {
@@ -56,6 +74,16 @@ union msi_addr_reg {
uint32_t addr_base:12;
uint32_t hi_32;
} bits __packed;
struct {
uint32_t rsvd_1:2;
uint32_t intr_index_high:1;
uint32_t shv:1;
uint32_t intr_format:1;
uint32_t intr_index_low:15;
uint32_t constant:12;
uint32_t hi_32;
} ir_bits __packed;
};
/*

View File

@@ -174,6 +174,11 @@ static inline uint8_t pci_func(uint16_t bdf)
return (uint8_t)(bdf & 0x7U);
}
static inline uint8_t pci_devfn(uint16_t bdf)
{
return (uint8_t)(bdf & 0xFFU);
}
uint32_t pci_pdev_read_cfg(union pci_bdf bdf, uint32_t offset, uint32_t bytes);
void pci_pdev_write_cfg(union pci_bdf bdf, uint32_t offset, uint32_t bytes, uint32_t val);
void enable_disable_pci_intx(union pci_bdf bdf, bool enable);