#define KVM_FEATURE_STEAL_TIME 5
#define KVM_FEATURE_PV_EOI 6
#define KVM_FEATURE_PV_UNHALT 7
+#define KVM_FEATURE_MSI_EXT_DEST_ID 15
/* The last 8 bits are used to indicate how to interpret the flags field
* in pvclock structure. If no bits are set, all flags are ignored.
#include <linux/acpi_pmtmr.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
+#include <linux/kvm_para.h>
#include <linux/bootmem.h>
#include <linux/ftrace.h>
#include <linux/ioport.h>
/* IR is required if there is APIC ID > 255 even when running
* under KVM
*/
- if (max_physical_apicid > 255 ||
+ unsigned int max_apic = 255;
+#ifdef CONFIG_KVM_GUEST
+ if (kvm_para_has_feature(KVM_FEATURE_MSI_EXT_DEST_ID))
+ max_apic = 32767;
+#endif
+ if (max_physical_apicid > max_apic ||
!hypervisor_x2apic_available()) {
pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n");
x2apic_disable();
msg->address_hi = MSI_ADDR_BASE_HI;
- if (x2apic_enabled())
- msg->address_hi |= MSI_ADDR_EXT_DEST_ID(dest);
-
msg->address_lo =
MSI_ADDR_BASE_LO |
((apic->irq_dest_mode == 0) ?
MSI_DATA_DELIVERY_FIXED :
MSI_DATA_DELIVERY_LOWPRI) |
MSI_DATA_VECTOR(cfg->vector);
+
+ if (x2apic_enabled()) {
+ if (hpet_id == -2) /* DMAR puts it in the high 32 bits */
+ msg->address_hi |= MSI_ADDR_EXT_DEST_ID(dest);
+ else /* With KVM_FEATURE_MSI_EXT_DEST_ID we use the extended dest_id bits */
+ msg->address_lo |= MSI_ADDR_EXT_DEST_ID(dest) >> 3;
+ }
}
static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
msg.data |= MSI_DATA_VECTOR(cfg->vector);
msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+ if (x2apic_enabled())
+ msg.address_lo |= MSI_ADDR_EXT_DEST_ID(dest) >> 3;
__pci_write_msi_msg(data->msi_desc, &msg);
int ret;
struct msi_msg msg;
- ret = msi_compose_msg(NULL, irq, &msg, -1);
+ ret = msi_compose_msg(NULL, irq, &msg, -2);
if (ret < 0)
return ret;
dmar_msi_write(irq, &msg);
msg.data |= MSI_DATA_VECTOR(cfg->vector);
msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+ if (x2apic_enabled())
+ msg.address_lo |= MSI_ADDR_EXT_DEST_ID(dest) >> 3;
hpet_msi_write(data->handler_data, &msg);