git: 2a6982e2643f - stable/14 - x86 iommu: move DMAR-independent parts of the interrupt setup code into common
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 11 Sep 2024 08:44:28 UTC
The branch stable/14 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=2a6982e2643fdb3f1c122f0260107afdbf51bc67
commit 2a6982e2643fdb3f1c122f0260107afdbf51bc67
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2024-06-09 19:36:10 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2024-09-11 08:43:59 +0000
x86 iommu: move DMAR-independent parts of the interrupt setup code into common
(cherry picked from commit 5967352a923efe6676bdf794d6b73f7354719a43)
---
sys/x86/iommu/intel_dmar.h | 24 ++-----
sys/x86/iommu/intel_drv.c | 151 ++++++++++++--------------------------------
sys/x86/iommu/intel_fault.c | 16 +++--
sys/x86/iommu/intel_qi.c | 14 ++--
sys/x86/iommu/iommu_utils.c | 105 ++++++++++++++++++++++++++++++
sys/x86/iommu/x86_iommu.h | 23 +++++++
6 files changed, 193 insertions(+), 140 deletions(-)
diff --git a/sys/x86/iommu/intel_dmar.h b/sys/x86/iommu/intel_dmar.h
index 7b4a7900fa25..0242e0cb954f 100644
--- a/sys/x86/iommu/intel_dmar.h
+++ b/sys/x86/iommu/intel_dmar.h
@@ -103,20 +103,6 @@ struct dmar_ctx {
#define CTX2DMAR(ctx) (CTX2DOM(ctx)->dmar)
#define DOM2DMAR(domain) ((domain)->dmar)
-struct dmar_msi_data {
- int irq;
- int irq_rid;
- struct resource *irq_res;
- void *intr_handle;
- int (*handler)(void *);
- int msi_data_reg;
- int msi_addr_reg;
- int msi_uaddr_reg;
- void (*enable_intr)(struct dmar_unit *);
- void (*disable_intr)(struct dmar_unit *);
- const char *name;
-};
-
#define DMAR_INTR_FAULT 0
#define DMAR_INTR_QI 1
#define DMAR_INTR_TOTAL 2
@@ -131,8 +117,6 @@ struct dmar_unit {
int reg_rid;
struct resource *regs;
- struct dmar_msi_data intrs[DMAR_INTR_TOTAL];
-
/* Hardware registers cache */
uint32_t hw_ver;
uint64_t hw_cap;
@@ -216,14 +200,14 @@ uint64_t dmar_get_timeout(void);
void dmar_update_timeout(uint64_t newval);
int dmar_fault_intr(void *arg);
-void dmar_enable_fault_intr(struct dmar_unit *unit);
-void dmar_disable_fault_intr(struct dmar_unit *unit);
+void dmar_enable_fault_intr(struct iommu_unit *unit);
+void dmar_disable_fault_intr(struct iommu_unit *unit);
int dmar_init_fault_log(struct dmar_unit *unit);
void dmar_fini_fault_log(struct dmar_unit *unit);
int dmar_qi_intr(void *arg);
-void dmar_enable_qi_intr(struct dmar_unit *unit);
-void dmar_disable_qi_intr(struct dmar_unit *unit);
+void dmar_enable_qi_intr(struct iommu_unit *unit);
+void dmar_disable_qi_intr(struct iommu_unit *unit);
int dmar_init_qi(struct dmar_unit *unit);
void dmar_fini_qi(struct dmar_unit *unit);
void dmar_qi_invalidate_locked(struct dmar_domain *domain,
diff --git a/sys/x86/iommu/intel_drv.c b/sys/x86/iommu/intel_drv.c
index 66d99748888f..2439ef9e4ef5 100644
--- a/sys/x86/iommu/intel_drv.c
+++ b/sys/x86/iommu/intel_drv.c
@@ -230,22 +230,6 @@ dmar_probe(device_t dev)
return (BUS_PROBE_NOWILDCARD);
}
-static void
-dmar_release_intr(device_t dev, struct dmar_unit *unit, int idx)
-{
- struct dmar_msi_data *dmd;
-
- dmd = &unit->intrs[idx];
- if (dmd->irq == -1)
- return;
- bus_teardown_intr(dev, dmd->irq_res, dmd->intr_handle);
- bus_release_resource(dev, SYS_RES_IRQ, dmd->irq_rid, dmd->irq_res);
- bus_delete_resource(dev, SYS_RES_IRQ, dmd->irq_rid);
- PCIB_RELEASE_MSIX(device_get_parent(device_get_parent(dev)),
- dev, dmd->irq);
- dmd->irq = -1;
-}
-
static void
dmar_release_resources(device_t dev, struct dmar_unit *unit)
{
@@ -256,7 +240,7 @@ dmar_release_resources(device_t dev, struct dmar_unit *unit)
dmar_fini_qi(unit);
dmar_fini_fault_log(unit);
for (i = 0; i < DMAR_INTR_TOTAL; i++)
- dmar_release_intr(dev, unit, i);
+ iommu_release_intr(DMAR2IOMMU(unit), i);
if (unit->regs != NULL) {
bus_deactivate_resource(dev, SYS_RES_MEMORY, unit->reg_rid,
unit->regs);
@@ -274,84 +258,19 @@ dmar_release_resources(device_t dev, struct dmar_unit *unit)
}
}
-static int
-dmar_alloc_irq(device_t dev, struct dmar_unit *unit, int idx)
-{
- device_t pcib;
- struct dmar_msi_data *dmd;
- uint64_t msi_addr;
- uint32_t msi_data;
- int error;
-
- dmd = &unit->intrs[idx];
- pcib = device_get_parent(device_get_parent(dev)); /* Really not pcib */
- error = PCIB_ALLOC_MSIX(pcib, dev, &dmd->irq);
- if (error != 0) {
- device_printf(dev, "cannot allocate %s interrupt, %d\n",
- dmd->name, error);
- goto err1;
- }
- error = bus_set_resource(dev, SYS_RES_IRQ, dmd->irq_rid,
- dmd->irq, 1);
- if (error != 0) {
- device_printf(dev, "cannot set %s interrupt resource, %d\n",
- dmd->name, error);
- goto err2;
- }
- dmd->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &dmd->irq_rid, RF_ACTIVE);
- if (dmd->irq_res == NULL) {
- device_printf(dev,
- "cannot allocate resource for %s interrupt\n", dmd->name);
- error = ENXIO;
- goto err3;
- }
- error = bus_setup_intr(dev, dmd->irq_res, INTR_TYPE_MISC,
- dmd->handler, NULL, unit, &dmd->intr_handle);
- if (error != 0) {
- device_printf(dev, "cannot setup %s interrupt, %d\n",
- dmd->name, error);
- goto err4;
- }
- bus_describe_intr(dev, dmd->irq_res, dmd->intr_handle, "%s", dmd->name);
- error = PCIB_MAP_MSI(pcib, dev, dmd->irq, &msi_addr, &msi_data);
- if (error != 0) {
- device_printf(dev, "cannot map %s interrupt, %d\n",
- dmd->name, error);
- goto err5;
- }
- dmar_write4(unit, dmd->msi_data_reg, msi_data);
- dmar_write4(unit, dmd->msi_addr_reg, msi_addr);
- /* Only for xAPIC mode */
- dmar_write4(unit, dmd->msi_uaddr_reg, msi_addr >> 32);
- return (0);
-
-err5:
- bus_teardown_intr(dev, dmd->irq_res, dmd->intr_handle);
-err4:
- bus_release_resource(dev, SYS_RES_IRQ, dmd->irq_rid, dmd->irq_res);
-err3:
- bus_delete_resource(dev, SYS_RES_IRQ, dmd->irq_rid);
-err2:
- PCIB_RELEASE_MSIX(pcib, dev, dmd->irq);
- dmd->irq = -1;
-err1:
- return (error);
-}
-
#ifdef DEV_APIC
static int
dmar_remap_intr(device_t dev, device_t child, u_int irq)
{
struct dmar_unit *unit;
- struct dmar_msi_data *dmd;
+ struct iommu_msi_data *dmd;
uint64_t msi_addr;
uint32_t msi_data;
int i, error;
unit = device_get_softc(dev);
for (i = 0; i < DMAR_INTR_TOTAL; i++) {
- dmd = &unit->intrs[i];
+ dmd = &unit->x86c.intrs[i];
if (irq == dmd->irq) {
error = PCIB_MAP_MSI(device_get_parent(
device_get_parent(dev)),
@@ -359,11 +278,14 @@ dmar_remap_intr(device_t dev, device_t child, u_int irq)
if (error != 0)
return (error);
DMAR_LOCK(unit);
- (dmd->disable_intr)(unit);
- dmar_write4(unit, dmd->msi_data_reg, msi_data);
- dmar_write4(unit, dmd->msi_addr_reg, msi_addr);
- dmar_write4(unit, dmd->msi_uaddr_reg, msi_addr >> 32);
- (dmd->enable_intr)(unit);
+ dmd->msi_data = msi_data;
+ dmd->msi_addr = msi_addr;
+ (dmd->disable_intr)(DMAR2IOMMU(unit));
+ dmar_write4(unit, dmd->msi_data_reg, dmd->msi_data);
+ dmar_write4(unit, dmd->msi_addr_reg, dmd->msi_addr);
+ dmar_write4(unit, dmd->msi_uaddr_reg,
+ dmd->msi_addr >> 32);
+ (dmd->enable_intr)(DMAR2IOMMU(unit));
DMAR_UNLOCK(unit);
return (0);
}
@@ -407,6 +329,7 @@ dmar_attach(device_t dev)
{
struct dmar_unit *unit;
ACPI_DMAR_HARDWARE_UNIT *dmaru;
+ struct iommu_msi_data *dmd;
uint64_t timeout;
int disable_pmr;
int i, error;
@@ -439,37 +362,47 @@ dmar_attach(device_t dev)
dmar_update_timeout(timeout);
for (i = 0; i < DMAR_INTR_TOTAL; i++)
- unit->intrs[i].irq = -1;
-
- unit->intrs[DMAR_INTR_FAULT].name = "fault";
- unit->intrs[DMAR_INTR_FAULT].irq_rid = DMAR_FAULT_IRQ_RID;
- unit->intrs[DMAR_INTR_FAULT].handler = dmar_fault_intr;
- unit->intrs[DMAR_INTR_FAULT].msi_data_reg = DMAR_FEDATA_REG;
- unit->intrs[DMAR_INTR_FAULT].msi_addr_reg = DMAR_FEADDR_REG;
- unit->intrs[DMAR_INTR_FAULT].msi_uaddr_reg = DMAR_FEUADDR_REG;
- unit->intrs[DMAR_INTR_FAULT].enable_intr = dmar_enable_fault_intr;
- unit->intrs[DMAR_INTR_FAULT].disable_intr = dmar_disable_fault_intr;
- error = dmar_alloc_irq(dev, unit, DMAR_INTR_FAULT);
+ unit->x86c.intrs[i].irq = -1;
+
+ dmd = &unit->x86c.intrs[DMAR_INTR_FAULT];
+ dmd->name = "fault";
+ dmd->irq_rid = DMAR_FAULT_IRQ_RID;
+ dmd->handler = dmar_fault_intr;
+ dmd->msi_data_reg = DMAR_FEDATA_REG;
+ dmd->msi_addr_reg = DMAR_FEADDR_REG;
+ dmd->msi_uaddr_reg = DMAR_FEUADDR_REG;
+ dmd->enable_intr = dmar_enable_fault_intr;
+ dmd->disable_intr = dmar_disable_fault_intr;
+ error = iommu_alloc_irq(DMAR2IOMMU(unit), DMAR_INTR_FAULT);
if (error != 0) {
dmar_release_resources(dev, unit);
dmar_devs[unit->iommu.unit] = NULL;
return (error);
}
+ dmar_write4(unit, dmd->msi_data_reg, dmd->msi_data);
+ dmar_write4(unit, dmd->msi_addr_reg, dmd->msi_addr);
+ dmar_write4(unit, dmd->msi_uaddr_reg, dmd->msi_addr >> 32);
+
if (DMAR_HAS_QI(unit)) {
- unit->intrs[DMAR_INTR_QI].name = "qi";
- unit->intrs[DMAR_INTR_QI].irq_rid = DMAR_QI_IRQ_RID;
- unit->intrs[DMAR_INTR_QI].handler = dmar_qi_intr;
- unit->intrs[DMAR_INTR_QI].msi_data_reg = DMAR_IEDATA_REG;
- unit->intrs[DMAR_INTR_QI].msi_addr_reg = DMAR_IEADDR_REG;
- unit->intrs[DMAR_INTR_QI].msi_uaddr_reg = DMAR_IEUADDR_REG;
- unit->intrs[DMAR_INTR_QI].enable_intr = dmar_enable_qi_intr;
- unit->intrs[DMAR_INTR_QI].disable_intr = dmar_disable_qi_intr;
- error = dmar_alloc_irq(dev, unit, DMAR_INTR_QI);
+ dmd = &unit->x86c.intrs[DMAR_INTR_QI];
+ dmd->name = "qi";
+ dmd->irq_rid = DMAR_QI_IRQ_RID;
+ dmd->handler = dmar_qi_intr;
+ dmd->msi_data_reg = DMAR_IEDATA_REG;
+ dmd->msi_addr_reg = DMAR_IEADDR_REG;
+ dmd->msi_uaddr_reg = DMAR_IEUADDR_REG;
+ dmd->enable_intr = dmar_enable_qi_intr;
+ dmd->disable_intr = dmar_disable_qi_intr;
+ error = iommu_alloc_irq(DMAR2IOMMU(unit), DMAR_INTR_QI);
if (error != 0) {
dmar_release_resources(dev, unit);
dmar_devs[unit->iommu.unit] = NULL;
return (error);
}
+
+ dmar_write4(unit, dmd->msi_data_reg, dmd->msi_data);
+ dmar_write4(unit, dmd->msi_addr_reg, dmd->msi_addr);
+ dmar_write4(unit, dmd->msi_uaddr_reg, dmd->msi_addr >> 32);
}
mtx_init(&unit->iommu.lock, "dmarhw", NULL, MTX_DEF);
diff --git a/sys/x86/iommu/intel_fault.c b/sys/x86/iommu/intel_fault.c
index 59b482720cf1..1064165ea5d7 100644
--- a/sys/x86/iommu/intel_fault.c
+++ b/sys/x86/iommu/intel_fault.c
@@ -127,7 +127,7 @@ dmar_fault_intr(void *arg)
int fri, frir, faultp;
bool enqueue;
- unit = arg;
+ unit = IOMMU2DMAR((struct iommu_unit *)arg);
enqueue = false;
fsts = dmar_read4(unit, DMAR_FSTS_REG);
dmar_fault_intr_clear(unit, fsts);
@@ -276,9 +276,9 @@ dmar_init_fault_log(struct dmar_unit *unit)
"dmar%d fault taskq", unit->iommu.unit);
DMAR_LOCK(unit);
- dmar_disable_fault_intr(unit);
+ dmar_disable_fault_intr(&unit->iommu);
dmar_clear_faults(unit);
- dmar_enable_fault_intr(unit);
+ dmar_enable_fault_intr(&unit->iommu);
DMAR_UNLOCK(unit);
return (0);
@@ -292,7 +292,7 @@ dmar_fini_fault_log(struct dmar_unit *unit)
return;
DMAR_LOCK(unit);
- dmar_disable_fault_intr(unit);
+ dmar_disable_fault_intr(&unit->iommu);
DMAR_UNLOCK(unit);
taskqueue_drain(unit->fault_taskqueue, &unit->fault_task);
@@ -306,10 +306,12 @@ dmar_fini_fault_log(struct dmar_unit *unit)
}
void
-dmar_enable_fault_intr(struct dmar_unit *unit)
+dmar_enable_fault_intr(struct iommu_unit *iommu)
{
+ struct dmar_unit *unit;
uint32_t fectl;
+ unit = IOMMU2DMAR(iommu);
DMAR_ASSERT_LOCKED(unit);
fectl = dmar_read4(unit, DMAR_FECTL_REG);
fectl &= ~DMAR_FECTL_IM;
@@ -317,10 +319,12 @@ dmar_enable_fault_intr(struct dmar_unit *unit)
}
void
-dmar_disable_fault_intr(struct dmar_unit *unit)
+dmar_disable_fault_intr(struct iommu_unit *iommu)
{
+ struct dmar_unit *unit;
uint32_t fectl;
+ unit = IOMMU2DMAR(iommu);
DMAR_ASSERT_LOCKED(unit);
fectl = dmar_read4(unit, DMAR_FECTL_REG);
dmar_write4(unit, DMAR_FECTL_REG, fectl | DMAR_FECTL_IM);
diff --git a/sys/x86/iommu/intel_qi.c b/sys/x86/iommu/intel_qi.c
index d6ce6749e4d4..a4939e337289 100644
--- a/sys/x86/iommu/intel_qi.c
+++ b/sys/x86/iommu/intel_qi.c
@@ -293,7 +293,7 @@ dmar_qi_intr(void *arg)
{
struct dmar_unit *unit;
- unit = arg;
+ unit = IOMMU2DMAR((struct iommu_unit *)arg);
KASSERT(unit->qi_enabled, ("dmar%d: QI is not enabled",
unit->iommu.unit));
taskqueue_enqueue(unit->x86c.qi_taskqueue, &unit->x86c.qi_task);
@@ -379,7 +379,7 @@ dmar_init_qi(struct dmar_unit *unit)
ics = DMAR_ICS_IWC;
dmar_write4(unit, DMAR_ICS_REG, ics);
}
- dmar_enable_qi_intr(unit);
+ dmar_enable_qi_intr(DMAR2IOMMU(unit));
DMAR_UNLOCK(unit);
return (0);
@@ -388,7 +388,7 @@ dmar_init_qi(struct dmar_unit *unit)
static void
dmar_fini_qi_helper(struct iommu_unit *iommu)
{
- dmar_disable_qi_intr(IOMMU2DMAR(iommu));
+ dmar_disable_qi_intr(iommu);
dmar_disable_qi(IOMMU2DMAR(iommu));
}
@@ -402,10 +402,12 @@ dmar_fini_qi(struct dmar_unit *unit)
}
void
-dmar_enable_qi_intr(struct dmar_unit *unit)
+dmar_enable_qi_intr(struct iommu_unit *iommu)
{
+ struct dmar_unit *unit;
uint32_t iectl;
+ unit = IOMMU2DMAR(iommu);
DMAR_ASSERT_LOCKED(unit);
KASSERT(DMAR_HAS_QI(unit), ("dmar%d: QI is not supported",
unit->iommu.unit));
@@ -415,10 +417,12 @@ dmar_enable_qi_intr(struct dmar_unit *unit)
}
void
-dmar_disable_qi_intr(struct dmar_unit *unit)
+dmar_disable_qi_intr(struct iommu_unit *iommu)
{
+ struct dmar_unit *unit;
uint32_t iectl;
+ unit = IOMMU2DMAR(iommu);
DMAR_ASSERT_LOCKED(unit);
KASSERT(DMAR_HAS_QI(unit), ("dmar%d: QI is not supported",
unit->iommu.unit));
diff --git a/sys/x86/iommu/iommu_utils.c b/sys/x86/iommu/iommu_utils.c
index 571e5a2e65cd..04d42799310e 100644
--- a/sys/x86/iommu/iommu_utils.c
+++ b/sys/x86/iommu/iommu_utils.c
@@ -28,7 +28,15 @@
* SUCH DAMAGE.
*/
+#include "opt_acpi.h"
+#if defined(__amd64__)
+#define DEV_APIC
+#else
+#include "opt_apic.h"
+#endif
+
#include <sys/systm.h>
+#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -38,6 +46,7 @@
#include <sys/sysctl.h>
#include <sys/proc.h>
#include <sys/sched.h>
+#include <sys/rman.h>
#include <sys/rwlock.h>
#include <sys/taskqueue.h>
#include <sys/tree.h>
@@ -48,6 +57,7 @@
#include <vm/vm_object.h>
#include <vm/vm_page.h>
#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
#include <machine/atomic.h>
#include <machine/bus.h>
#include <machine/cpu.h>
@@ -56,6 +66,12 @@
#include <dev/iommu/iommu.h>
#include <x86/iommu/x86_iommu.h>
#include <x86/iommu/iommu_intrmap.h>
+#ifdef DEV_APIC
+#include "pcib_if.h"
+#include <machine/intr_machdep.h>
+#include <x86/apicreg.h>
+#include <x86/apicvar.h>
+#endif
vm_page_t
iommu_pgalloc(vm_object_t obj, vm_pindex_t idx, int flags)
@@ -483,3 +499,92 @@ iommu_qi_common_fini(struct iommu_unit *unit, void (*disable_qi)(
x86c->inv_queue = NULL;
x86c->inv_queue_size = 0;
}
+
+int
+iommu_alloc_irq(struct iommu_unit *unit, int idx)
+{
+ device_t dev, pcib;
+ struct iommu_msi_data *dmd;
+ uint64_t msi_addr;
+ uint32_t msi_data;
+ int error;
+
+ MPASS(idx >= 0 || idx < IOMMU_MAX_MSI);
+
+ dev = unit->dev;
+ dmd = &IOMMU2X86C(unit)->intrs[idx];
+ pcib = device_get_parent(device_get_parent(dev)); /* Really not pcib */
+ error = PCIB_ALLOC_MSIX(pcib, dev, &dmd->irq);
+ if (error != 0) {
+ device_printf(dev, "cannot allocate %s interrupt, %d\n",
+ dmd->name, error);
+ goto err1;
+ }
+ error = bus_set_resource(dev, SYS_RES_IRQ, dmd->irq_rid,
+ dmd->irq, 1);
+ if (error != 0) {
+ device_printf(dev, "cannot set %s interrupt resource, %d\n",
+ dmd->name, error);
+ goto err2;
+ }
+ dmd->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &dmd->irq_rid, RF_ACTIVE);
+ if (dmd->irq_res == NULL) {
+ device_printf(dev,
+ "cannot allocate resource for %s interrupt\n", dmd->name);
+ error = ENXIO;
+ goto err3;
+ }
+ error = bus_setup_intr(dev, dmd->irq_res, INTR_TYPE_MISC,
+ dmd->handler, NULL, unit, &dmd->intr_handle);
+ if (error != 0) {
+ device_printf(dev, "cannot setup %s interrupt, %d\n",
+ dmd->name, error);
+ goto err4;
+ }
+ bus_describe_intr(dev, dmd->irq_res, dmd->intr_handle, "%s", dmd->name);
+ error = PCIB_MAP_MSI(pcib, dev, dmd->irq, &msi_addr, &msi_data);
+ if (error != 0) {
+ device_printf(dev, "cannot map %s interrupt, %d\n",
+ dmd->name, error);
+ goto err5;
+ }
+
+ dmd->msi_data = msi_data;
+ dmd->msi_addr = msi_addr;
+
+ return (0);
+
+err5:
+ bus_teardown_intr(dev, dmd->irq_res, dmd->intr_handle);
+err4:
+ bus_release_resource(dev, SYS_RES_IRQ, dmd->irq_rid, dmd->irq_res);
+err3:
+ bus_delete_resource(dev, SYS_RES_IRQ, dmd->irq_rid);
+err2:
+ PCIB_RELEASE_MSIX(pcib, dev, dmd->irq);
+ dmd->irq = -1;
+err1:
+ return (error);
+}
+
+void
+iommu_release_intr(struct iommu_unit *unit, int idx)
+{
+ device_t dev;
+ struct iommu_msi_data *dmd;
+
+ MPASS(idx >= 0 || idx < IOMMU_MAX_MSI);
+
+ dmd = &IOMMU2X86C(unit)->intrs[idx];
+ if (dmd->handler == NULL || dmd->irq == -1)
+ return;
+ dev = unit->dev;
+
+ bus_teardown_intr(dev, dmd->irq_res, dmd->intr_handle);
+ bus_release_resource(dev, SYS_RES_IRQ, dmd->irq_rid, dmd->irq_res);
+ bus_delete_resource(dev, SYS_RES_IRQ, dmd->irq_rid);
+ PCIB_RELEASE_MSIX(device_get_parent(device_get_parent(dev)),
+ dev, dmd->irq);
+ dmd->irq = -1;
+}
diff --git a/sys/x86/iommu/x86_iommu.h b/sys/x86/iommu/x86_iommu.h
index 966a13c19b6e..d6e3ea56bd2c 100644
--- a/sys/x86/iommu/x86_iommu.h
+++ b/sys/x86/iommu/x86_iommu.h
@@ -93,6 +93,24 @@ struct x86_iommu {
void set_x86_iommu(struct x86_iommu *);
struct x86_iommu *get_x86_iommu(void);
+struct iommu_msi_data {
+ int irq;
+ int irq_rid;
+ struct resource *irq_res;
+ void *intr_handle;
+ int (*handler)(void *);
+ int msi_data_reg;
+ int msi_addr_reg;
+ int msi_uaddr_reg;
+ uint64_t msi_addr;
+ uint32_t msi_data;
+ void (*enable_intr)(struct iommu_unit *);
+ void (*disable_intr)(struct iommu_unit *);
+ const char *name;
+};
+
+#define IOMMU_MAX_MSI 3
+
struct x86_unit_common {
uint32_t qi_buf_maxsz;
uint32_t qi_cmd_sz;
@@ -145,6 +163,8 @@ struct x86_unit_common {
struct iommu_map_entry *tlb_flush_tail;
struct task qi_task;
struct taskqueue *qi_taskqueue;
+
+ struct iommu_msi_data intrs[IOMMU_MAX_MSI];
};
void iommu_qi_emit_wait_seq(struct iommu_unit *unit, struct iommu_qi_genseq *
@@ -160,4 +180,7 @@ void iommu_qi_common_init(struct iommu_unit *unit, task_fn_t taskfunc);
void iommu_qi_common_fini(struct iommu_unit *unit, void (*disable_qi)(
struct iommu_unit *));
+int iommu_alloc_irq(struct iommu_unit *unit, int idx);
+void iommu_release_intr(struct iommu_unit *unit, int idx);
+
#endif