hv: Add Interrupt Remapping Enable/Disable APIs

This patch adds IR enable/disable APIs. Upon boot, enabling IR is
deferred until the first interrupt source is programmed. This is done
for UEFI platforms as UEFI bootloader depends on timer interrupt and
the programming of timer interrupt source is done before ACRN gets a
chance to run during boot.

Tracked-On: #2426
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
Sainath Grandhi 2019-01-15 13:31:06 -08:00 committed by Eddie Dong
parent 970821462b
commit f122d6bd32

View File

@ -408,6 +408,25 @@ static bool dmar_unit_support_aw(const struct dmar_drhd_rt *dmar_unit, uint32_t
return (((1U << aw) & iommu_cap_sagaw(dmar_unit->cap)) != 0U);
}
static void dmar_enable_intr_remapping(struct dmar_drhd_rt *dmar_unit)
{
uint32_t status = 0;
spinlock_obtain(&(dmar_unit->lock));
if ((dmar_unit->gcmd & DMA_GCMD_IRE) == 0U) {
dmar_unit->gcmd |= DMA_GCMD_IRE;
iommu_write32(dmar_unit, DMAR_GCMD_REG, dmar_unit->gcmd);
/* 32-bit register */
dmar_wait_completion(dmar_unit, DMAR_GSTS_REG, DMA_GSTS_IRES, false, &status);
#if DBG_IOMMU
status = iommu_read32(dmar_unit, DMAR_GSTS_REG);
#endif
}
spinlock_release(&(dmar_unit->lock));
dev_dbg(ACRN_DBG_IOMMU, "%s: gsr:0x%x", __func__, status);
}
static void dmar_enable_translation(struct dmar_drhd_rt *dmar_unit)
{
uint32_t status = 0;
@ -428,6 +447,21 @@ static void dmar_enable_translation(struct dmar_drhd_rt *dmar_unit)
dev_dbg(ACRN_DBG_IOMMU, "%s: gsr:0x%x", __func__, status);
}
static void dmar_disable_intr_remapping(struct dmar_drhd_rt *dmar_unit)
{
uint32_t status;
spinlock_obtain(&(dmar_unit->lock));
if ((dmar_unit->gcmd & DMA_GCMD_IRE) != 0U) {
dmar_unit->gcmd &= ~DMA_GCMD_IRE;
iommu_write32(dmar_unit, DMAR_GCMD_REG, dmar_unit->gcmd);
/* 32-bit register */
dmar_wait_completion(dmar_unit, DMAR_GSTS_REG, DMA_GSTS_IRES, true, &status);
}
spinlock_release(&(dmar_unit->lock));
}
static void dmar_disable_translation(struct dmar_drhd_rt *dmar_unit)
{
uint32_t status;
@ -999,6 +1033,7 @@ static void dmar_disable(struct dmar_drhd_rt *dmar_unit)
dmar_disable_qi(dmar_unit);
dmar_disable_translation(dmar_unit);
dmar_fault_event_mask(dmar_unit);
dmar_disable_intr_remapping(dmar_unit);
}
static void dmar_suspend(struct dmar_drhd_rt *dmar_unit)
@ -1026,6 +1061,7 @@ static void dmar_resume(struct dmar_drhd_rt *dmar_unit)
}
dmar_prepare(dmar_unit);
dmar_enable(dmar_unit);
dmar_enable_intr_remapping(dmar_unit);
}
static int32_t add_iommu_device(struct iommu_domain *domain, uint16_t segment, uint8_t bus, uint8_t devfun)
@ -1375,6 +1411,7 @@ int32_t dmar_assign_irte(struct intr_source intr_src, union dmar_ir_entry irte,
pr_err("IR table is not set for dmar unit");
ret = -EINVAL;
} else {
dmar_enable_intr_remapping(dmar_unit);
irte.bits.svt = 0x1UL;
irte.bits.sq = 0x0UL;
irte.bits.sid = sid.value;