Commit 3223ade2 authored by Peter Xu's avatar Peter Xu Committed by Paolo Bonzini
Browse files

intel-iommu: add ioapic irq test



IOAPIC irqs are line-based irqs comparing to MSI ones (which are
memory-based). To make it complete, let's also test IOAPIC interrupts
in the IR testcase.
Signed-off-by: default avatarPeter Xu <peterx@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 560586d9
......@@ -284,6 +284,21 @@ struct vtd_msi_data {
} __attribute__ ((packed));
typedef struct vtd_msi_data vtd_msi_data_t;
struct vtd_ioapic_entry {
uint64_t vector:8;
uint64_t __zeros:3;
uint64_t index_15:1;
uint64_t delivery_status:1;
uint64_t polarity:1;
uint64_t remote_irr:1;
uint64_t trigger_mode:1;
uint64_t mask:1;
uint64_t __zeros_2:31;
uint64_t interrupt_format:1;
uint64_t index_0_14:15;
} __attribute__ ((packed));
typedef struct vtd_ioapic_entry vtd_ioapic_entry_t;
/**
* vtd_setup_msi - setup MSI message for a device
*
......@@ -316,6 +331,31 @@ bool vtd_setup_msi(struct pci_dev *dev, int vector, int dest_id)
*(uint32_t *)&msi_data);
}
void vtd_setup_ioapic_irq(struct pci_dev *dev, int vector,
int dest_id, trigger_mode_t trigger)
{
vtd_ioapic_entry_t entry = {};
vtd_irte_t *irte = phys_to_virt(vtd_ir_table());
ioapic_redir_entry_t *entry_2 = (ioapic_redir_entry_t *)&entry;
uint16_t index = vtd_intr_index_alloc();
uint8_t line;
assert(dev);
assert(sizeof(vtd_ioapic_entry_t) == 8);
vtd_setup_irte(dev, irte + index, vector,
dest_id, trigger);
entry.vector = vector;
entry.trigger_mode = trigger;
entry.index_15 = (index >> 15) & 1;
entry.interrupt_format = 1;
entry.index_0_14 = index & 0x7fff;
line = pci_intx_line(dev);
ioapic_write_redir(line, *entry_2);
}
void vtd_init(void)
{
setup_vm();
......
......@@ -22,6 +22,7 @@
#include "desc.h"
#include "pci.h"
#include "asm/io.h"
#include "apic.h"
#define Q35_HOST_BRIDGE_IOMMU_ADDR 0xfed90000ULL
#define VTD_PAGE_SHIFT PAGE_SHIFT
......@@ -142,5 +143,7 @@ static inline uint64_t vtd_readq(unsigned int reg)
void vtd_init(void);
void vtd_map_range(uint16_t sid, phys_addr_t iova, phys_addr_t pa, size_t size);
bool vtd_setup_msi(struct pci_dev *dev, int vector, int dest_id);
void vtd_setup_ioapic_irq(struct pci_dev *dev, int vector,
int dest_id, trigger_mode_t trigger);
#endif
......@@ -16,6 +16,7 @@
#define VTD_TEST_DMAR_4B ("DMAR 4B memcpy test")
#define VTD_TEST_IR_MSI ("IR MSI")
#define VTD_TEST_IR_IOAPIC ("IR IOAPIC")
void vtd_test_dmar(struct pci_edu_dev *dev)
{
......@@ -67,22 +68,48 @@ static void edu_isr(isr_regs_t *regs)
static void vtd_test_ir(struct pci_edu_dev *dev)
{
#define VTD_TEST_VECTOR (0xee)
#define VTD_TEST_VECTOR_IOAPIC (0xed)
#define VTD_TEST_VECTOR_MSI (0xee)
struct pci_dev *pci_dev = &dev->pci_dev;
report_prefix_push("vtd_ir");
irq_enable();
/* This will enable INTx */
pci_msi_set_enable(pci_dev, false);
vtd_setup_ioapic_irq(pci_dev, VTD_TEST_VECTOR_IOAPIC,
0, TRIGGER_EDGE);
handle_irq(VTD_TEST_VECTOR_IOAPIC, edu_isr);
edu_intr_recved = false;
wmb();
/* Manually trigger INTR */
edu_reg_writel(dev, EDU_REG_INTR_RAISE, 1);
while (!edu_intr_recved)
cpu_relax();
/* Clear INTR bits */
edu_reg_writel(dev, EDU_REG_INTR_RAISE, 0);
/* We are good as long as we reach here */
report(VTD_TEST_IR_IOAPIC, edu_intr_recved == true);
/*
* Setup EDU PCI device MSI, using interrupt remapping. By
* default, EDU device is using INTx.
*/
if (!vtd_setup_msi(&dev->pci_dev, VTD_TEST_VECTOR, 0)) {
if (!vtd_setup_msi(pci_dev, VTD_TEST_VECTOR_MSI, 0)) {
printf("edu device does not support MSI, skip test\n");
report_skip(VTD_TEST_IR_MSI);
return;
}
handle_irq(VTD_TEST_VECTOR, edu_isr);
irq_enable();
handle_irq(VTD_TEST_VECTOR_MSI, edu_isr);
edu_intr_recved = false;
wmb();
/* Manually trigger INTR */
edu_reg_writel(dev, EDU_REG_INTR_RAISE, 1);
......@@ -93,7 +120,7 @@ static void vtd_test_ir(struct pci_edu_dev *dev)
edu_reg_writel(dev, EDU_REG_INTR_RAISE, 0);
/* We are good as long as we reach here */
report(VTD_TEST_IR_MSI, true);
report(VTD_TEST_IR_MSI, edu_intr_recved == true);
report_prefix_pop();
}
......@@ -122,6 +149,7 @@ int main(int argc, char *argv[])
printf("Please specify \"-device edu\" to do "
"further IOMMU tests.\n");
report_skip(VTD_TEST_DMAR_4B);
report_skip(VTD_TEST_IR_IOAPIC);
report_skip(VTD_TEST_IR_MSI);
} else {
vtd_test_dmar(&dev);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment