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,
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
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 |
|
||||
(vector & IOAPIC_VEC_MASK) | flags;
|
||||
ioApicRedSetHi(irq, DEFAULT_RTE_DEST);
|
||||
ioApicRedSetLo(irq, rteValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -45,4 +45,13 @@
|
|||
|
||||
#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_ */
|
||||
|
|
|
@ -23,6 +23,7 @@ extern "C" {
|
|||
#define IOAPIC_LEVEL 0x00008000
|
||||
#define IOAPIC_EDGE 0x00000000
|
||||
#define IOAPIC_REMOTE 0x00004000
|
||||
#define IOAPIC_POLARITY_MASK 0x00002000
|
||||
#define IOAPIC_LOW 0x00002000
|
||||
#define IOAPIC_HIGH 0x00000000
|
||||
#define IOAPIC_LOGICAL 0x00000800
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue