drivers/interrupt_controller: Make IOAPIC VT-D aware when relevant
If VT-D's interrupt remapping is in place, all IOAPIC RTEs need to get remapped as well (or then they will be simply blocked). Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
parent
edef8e6b0d
commit
2efd874dcc
3 changed files with 77 additions and 5 deletions
|
@ -116,6 +116,31 @@ static uint32_t ioApicRedGetLo(unsigned int irq);
|
||||||
static void IoApicRedUpdateLo(unsigned int irq, uint32_t value,
|
static void IoApicRedUpdateLo(unsigned int irq, uint32_t value,
|
||||||
uint32_t mask);
|
uint32_t mask);
|
||||||
|
|
||||||
|
#if defined(CONFIG_INTEL_VTD_ICTL) && \
|
||||||
|
!defined(CONFIG_INTEL_VTD_ICTL_XAPIC_PASSTHROUGH)
|
||||||
|
|
||||||
|
#include <drivers/interrupt_controller/intel_vtd.h>
|
||||||
|
|
||||||
|
static const struct device *vtd;
|
||||||
|
|
||||||
|
static bool get_vtd(void)
|
||||||
|
{
|
||||||
|
if (vtd != NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DRV_COMPAT_BAK DT_DRV_COMPAT
|
||||||
|
#undef DT_DRV_COMPAT
|
||||||
|
#define DT_DRV_COMPAT intel_vt_d
|
||||||
|
vtd = device_get_binding(DT_INST_LABEL(0));
|
||||||
|
#undef DT_DRV_COMPAT
|
||||||
|
#define DT_DRV_COMPAT DRV_COMPAT_BAK
|
||||||
|
#undef DRV_COMPAT_BAK
|
||||||
|
|
||||||
|
return vtd == NULL ? false : true;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_INTEL_VTD_ICTL && !INTEL_VTD_ICTL_XAPIC_PASSTHROUGH */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The functions irq_enable() and irq_disable() are implemented in the
|
* The functions irq_enable() and irq_disable() are implemented in the
|
||||||
* interrupt controller driver due to the IRQ virtualization imposed by
|
* interrupt controller driver due to the IRQ virtualization imposed by
|
||||||
|
@ -346,13 +371,50 @@ __boot_func
|
||||||
void z_ioapic_irq_set(unsigned int irq, unsigned int vector, uint32_t flags)
|
void z_ioapic_irq_set(unsigned int irq, unsigned int vector, uint32_t flags)
|
||||||
{
|
{
|
||||||
uint32_t rteValue; /* value to copy into redirection table entry */
|
uint32_t rteValue; /* value to copy into redirection table entry */
|
||||||
|
#if defined(CONFIG_INTEL_VTD_ICTL) && \
|
||||||
|
!defined(CONFIG_INTEL_VTD_ICTL_XAPIC_PASSTHROUGH)
|
||||||
|
int irte_idx;
|
||||||
|
|
||||||
/* the delivery mode is determined by the flags passed from drivers */
|
if (!get_vtd()) {
|
||||||
|
goto no_vtd;
|
||||||
|
}
|
||||||
|
|
||||||
|
irte_idx = vtd_get_irte_by_vector(vtd, vector);
|
||||||
|
if (irte_idx < 0) {
|
||||||
|
irte_idx = vtd_get_irte_by_irq(vtd, irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irte_idx >= 0 && !vtd_irte_is_msi(vtd, irte_idx)) {
|
||||||
|
/* Enable interrupt remapping format and set the irte index */
|
||||||
|
rteValue = IOAPIC_VTD_REMAP_FORMAT |
|
||||||
|
IOAPIC_VTD_INDEX(irte_idx);
|
||||||
|
ioApicRedSetHi(irq, rteValue);
|
||||||
|
|
||||||
|
/* Remapped: delivery mode is Fixed (000) and
|
||||||
|
* destination mode is no longer present as it is replaced by
|
||||||
|
* the 15th bit of irte index, which is always 0 in our case.
|
||||||
|
*/
|
||||||
|
rteValue = IOAPIC_INT_MASK |
|
||||||
|
(vector & IOAPIC_VEC_MASK) |
|
||||||
|
(flags & IOAPIC_TRIGGER_MASK) |
|
||||||
|
(flags & IOAPIC_POLARITY_MASK);
|
||||||
|
ioApicRedSetLo(irq, rteValue);
|
||||||
|
|
||||||
|
vtd_remap(vtd, irte_idx, vector, flags);
|
||||||
|
} else {
|
||||||
|
no_vtd:
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
#endif /* CONFIG_INTEL_VTD_ICTL && !CONFIG_INTEL_VTD_ICTL_XAPIC_PASSTHROUGH */
|
||||||
|
/* the delivery mode is determined by the flags
|
||||||
|
* passed from drivers
|
||||||
|
*/
|
||||||
rteValue = IOAPIC_INT_MASK | IOAPIC_LOGICAL |
|
rteValue = IOAPIC_INT_MASK | IOAPIC_LOGICAL |
|
||||||
(vector & IOAPIC_VEC_MASK) | flags;
|
(vector & IOAPIC_VEC_MASK) | flags;
|
||||||
ioApicRedSetHi(irq, DEFAULT_RTE_DEST);
|
ioApicRedSetHi(irq, DEFAULT_RTE_DEST);
|
||||||
ioApicRedSetLo(irq, rteValue);
|
ioApicRedSetLo(irq, rteValue);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
|
@ -45,4 +45,13 @@
|
||||||
|
|
||||||
#define IOAPIC_VEC_MASK 0x000000ff
|
#define IOAPIC_VEC_MASK 0x000000ff
|
||||||
|
|
||||||
|
/* VTD related macros */
|
||||||
|
|
||||||
|
#define IOAPIC_VTD_REMAP_FORMAT BIT(16)
|
||||||
|
/* We care only about the first 14 bits.
|
||||||
|
* The 15th bits is in the first 32bits of RTE but since
|
||||||
|
* we don't go up to that value, let's ignore it.
|
||||||
|
*/
|
||||||
|
#define IOAPIC_VTD_INDEX(index) (index << 17)
|
||||||
|
|
||||||
#endif /* ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_IOAPIC_PRIV_H_ */
|
#endif /* ZEPHYR_DRIVERS_INTERRUPT_CONTROLLER_INTC_IOAPIC_PRIV_H_ */
|
||||||
|
|
|
@ -23,6 +23,7 @@ extern "C" {
|
||||||
#define IOAPIC_LEVEL 0x00008000
|
#define IOAPIC_LEVEL 0x00008000
|
||||||
#define IOAPIC_EDGE 0x00000000
|
#define IOAPIC_EDGE 0x00000000
|
||||||
#define IOAPIC_REMOTE 0x00004000
|
#define IOAPIC_REMOTE 0x00004000
|
||||||
|
#define IOAPIC_POLARITY_MASK 0x00002000
|
||||||
#define IOAPIC_LOW 0x00002000
|
#define IOAPIC_LOW 0x00002000
|
||||||
#define IOAPIC_HIGH 0x00000000
|
#define IOAPIC_HIGH 0x00000000
|
||||||
#define IOAPIC_LOGICAL 0x00000800
|
#define IOAPIC_LOGICAL 0x00000800
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue