diff --git a/arch/x86/core/pcie.c b/arch/x86/core/pcie.c index add79e3009d..4c5c576a69b 100644 --- a/arch/x86/core/pcie.c +++ b/arch/x86/core/pcie.c @@ -161,6 +161,7 @@ void pcie_conf_write(pcie_bdf_t bdf, unsigned int reg, uint32_t data) #ifdef CONFIG_INTEL_VTD_ICTL #include +#include static const struct device *vtd; @@ -290,11 +291,18 @@ bool arch_pcie_msi_vector_connect(msi_vector_t *vector, { #ifdef CONFIG_INTEL_VTD_ICTL if (vector->arch.remap) { + union acpi_dmar_id id; + if (!get_vtd()) { return false; } - vtd_remap(vtd, vector->arch.irte, vector->arch.vector, flags); + id.bits.bus = PCIE_BDF_TO_BUS(vector->bdf); + id.bits.device = PCIE_BDF_TO_DEV(vector->bdf); + id.bits.function = PCIE_BDF_TO_FUNC(vector->bdf); + + vtd_remap(vtd, vector->arch.irte, vector->arch.vector, + flags, id.raw); } #endif /* CONFIG_INTEL_VTD_ICTL */ diff --git a/drivers/interrupt_controller/intc_intel_vtd.c b/drivers/interrupt_controller/intc_intel_vtd.c index 47596d1b261..772251d0fcd 100644 --- a/drivers/interrupt_controller/intc_intel_vtd.c +++ b/drivers/interrupt_controller/intc_intel_vtd.c @@ -346,7 +346,8 @@ static uint32_t vtd_ictl_remap_msi(const struct device *dev, static int vtd_ictl_remap(const struct device *dev, uint8_t irte_idx, uint16_t vector, - uint32_t flags) + uint32_t flags, + uint16_t src_id) { struct vtd_ictl_data *data = dev->data; union vtd_irte irte = { 0 }; @@ -362,6 +363,11 @@ static int vtd_ictl_remap(const struct device *dev, irte.bits.dst_id = 0xFF << 8; } + if (src_id != USHRT_MAX) { + irte.bits.src_validation_type = 1; + irte.bits.src_id = src_id; + } + delivery_mode = (flags & IOAPIC_DELIVERY_MODE_MASK); if ((delivery_mode != IOAPIC_FIXED) || (delivery_mode != IOAPIC_LOW)) { diff --git a/drivers/interrupt_controller/intc_ioapic.c b/drivers/interrupt_controller/intc_ioapic.c index 8d5c59dbf35..6c8be2695c9 100644 --- a/drivers/interrupt_controller/intc_ioapic.c +++ b/drivers/interrupt_controller/intc_ioapic.c @@ -120,8 +120,11 @@ static void IoApicRedUpdateLo(unsigned int irq, uint32_t value, !defined(CONFIG_INTEL_VTD_ICTL_XAPIC_PASSTHROUGH) #include +#include static const struct device *vtd; +static uint16_t ioapic_id; + static bool get_vtd(void) { @@ -137,6 +140,8 @@ static bool get_vtd(void) #define DT_DRV_COMPAT DRV_COMPAT_BAK #undef DRV_COMPAT_BAK + ioapic_id = z_acpi_get_dev_id_from_dmar(ACPI_DRHD_DEV_SCOPE_IOAPIC); + return vtd == NULL ? false : true; } #endif /* CONFIG_INTEL_VTD_ICTL && !INTEL_VTD_ICTL_XAPIC_PASSTHROUGH */ @@ -400,7 +405,7 @@ void z_ioapic_irq_set(unsigned int irq, unsigned int vector, uint32_t flags) (flags & IOAPIC_POLARITY_MASK); ioApicRedSetLo(irq, rteValue); - vtd_remap(vtd, irte_idx, vector, flags); + vtd_remap(vtd, irte_idx, vector, flags, ioapic_id); } else { no_vtd: #else diff --git a/include/drivers/interrupt_controller/intel_vtd.h b/include/drivers/interrupt_controller/intel_vtd.h index d7db136603d..8d3d0c9adb9 100644 --- a/include/drivers/interrupt_controller/intel_vtd.h +++ b/include/drivers/interrupt_controller/intel_vtd.h @@ -18,7 +18,8 @@ typedef uint32_t (*vtd_remap_msi_f)(const struct device *dev, typedef int (*vtd_remap_f)(const struct device *dev, uint8_t irte_idx, uint16_t vector, - uint32_t flags); + uint32_t flags, + uint16_t src_id); typedef int (*vtd_set_irte_vector_f)(const struct device *dev, uint8_t irte_idx, @@ -102,18 +103,20 @@ static inline uint32_t vtd_remap_msi(const struct device *dev, * @param irte_idx A previoulsy allocated irte entry index number * @param vector An allocated interrupt vector * @param flags interrupt flags + * @param src_id a valid source ID or USHRT_MAX if none * * @return 0 on success, a negative errno otherwise */ static inline int vtd_remap(const struct device *dev, uint8_t irte_idx, uint16_t vector, - uint32_t flags) + uint32_t flags, + uint16_t src_id) { const struct vtd_driver_api *api = (const struct vtd_driver_api *)dev->api; - return api->remap(dev, irte_idx, vector, flags); + return api->remap(dev, irte_idx, vector, flags, src_id); } /**