summaryrefslogtreecommitdiff
path: root/arch/x86/kernel/apic/apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r--arch/x86/kernel/apic/apic.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 54f04355aaa2..4c15bf29ea2c 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -50,6 +50,7 @@
#include <asm/io_apic.h>
#include <asm/desc.h>
#include <asm/hpet.h>
+#include <asm/msidef.h>
#include <asm/mtrr.h>
#include <asm/time.h>
#include <asm/smp.h>
@@ -2480,6 +2481,37 @@ int hard_smp_processor_id(void)
return read_apic_id();
}
+void __irq_msi_compose_msg(struct irq_cfg *cfg, struct msi_msg *msg,
+ bool dmar)
+{
+ msg->address_hi = MSI_ADDR_BASE_HI;
+
+ msg->address_lo =
+ MSI_ADDR_BASE_LO |
+ (apic->dest_mode_logical ?
+ MSI_ADDR_DEST_MODE_LOGICAL :
+ MSI_ADDR_DEST_MODE_PHYSICAL) |
+ MSI_ADDR_REDIRECTION_CPU |
+ MSI_ADDR_DEST_ID(cfg->dest_apicid);
+
+ msg->data =
+ MSI_DATA_TRIGGER_EDGE |
+ MSI_DATA_LEVEL_ASSERT |
+ MSI_DATA_DELIVERY_FIXED |
+ MSI_DATA_VECTOR(cfg->vector);
+
+ /*
+ * Only the IOMMU itself can use the trick of putting destination
+ * APIC ID into the high bits of the address. Anything else would
+ * just be writing to memory if it tried that, and needs IR to
+ * address higher APIC IDs.
+ */
+ if (dmar)
+ msg->address_hi |= MSI_ADDR_EXT_DEST_ID(cfg->dest_apicid);
+ else
+ WARN_ON_ONCE(MSI_ADDR_EXT_DEST_ID(cfg->dest_apicid));
+}
+
/*
* Override the generic EOI implementation with an optimized version.
* Only called during early boot when only one CPU is active and with