192
amdvi_writeq_raw(s, addr, amdvi_readq(s, addr) & val);
193
}
194
195
+static void amdvi_build_xt_msi_msg(AMDVIState *s, MSIMessage *msg)
196
+{
197
+ union mmio_xt_intr xt_reg;
198
+ struct X86IOMMUIrq irq;
199
+
200
+ xt_reg.val = amdvi_readq(s, AMDVI_MMIO_XT_GEN_INTR);
201
+
202
+ irq.vector = xt_reg.vector;
203
+ irq.delivery_mode = xt_reg.delivery_mode;
204
+ irq.dest_mode = xt_reg.destination_mode;
205
+ irq.dest = (xt_reg.destination_hi << 24) | xt_reg.destination_lo;
206
+ irq.trigger_mode = 0;
207
+ irq.redir_hint = 0;
208
+
209
+ x86_iommu_irq_to_msi_message(&irq, msg);
210
+}
211
+
212
static void amdvi_generate_msi_interrupt(AMDVIState *s)
213
{
214
MSIMessage msg = {};
198
- MemTxAttrs attrs = {
199
- .requester_id = pci_requester_id(&s->pci->dev)
200
- };
215
202
- if (msi_enabled(&s->pci->dev)) {
216
+ if (s->intcapxten) {
217
+ trace_amdvi_generate_msi_interrupt("XT GEN");
218
+ amdvi_build_xt_msi_msg(s, &msg);
219
+ } else if (msi_enabled(&s->pci->dev)) {
220
+ trace_amdvi_generate_msi_interrupt("MSI");
221
msg = msi_get_message(&s->pci->dev, 0);
204
- address_space_stl_le(&address_space_memory, msg.address, msg.data,
205
- attrs, NULL);
222
+ } else {
223
+ trace_amdvi_generate_msi_interrupt("NO MSI");
224
+ return;
225
}
226
+ apic_get_class(NULL)->send_msi(&msg);
227
}
228
229
static uint32_t get_next_eventlog_entry(AMDVIState *s)
1558
MMIO_REG_TO_STRING(AMDVI_MMIO_PPR_BASE);
1559
MMIO_REG_TO_STRING(AMDVI_MMIO_PPR_HEAD);
1560
MMIO_REG_TO_STRING(AMDVI_MMIO_PPR_TAIL);
1561
+ MMIO_REG_TO_STRING(AMDVI_MMIO_XT_GEN_INTR);
1562
#undef MMIO_REG_TO_STRING
1563
default:
1564
return "UNHANDLED";
1602
s->ga_enabled = !!(control & AMDVI_MMIO_CONTROL_GAEN);
1603
s->xten = !!(control & AMDVI_MMIO_CONTROL_XTEN) && s->xtsup &&
1604
s->ga_enabled;
1605
+ /*
1606
+ * IntCapXTEn controls whether IOMMU-originated interrupts are sent based
1607
+ * on the information in XT IOMMU Interrupt Control Registers rather than
1608
+ * the IOMMU’s MSI capability registers. Therefore it requires IOMMU
1609
+ * x2APIC support capabilities (i.e. XTSup=1), but it is independent of
1610
+ * whether a driver chooses to enable x2APIC mode for interrupt remapping
1611
+ * (i.e. XTEn=1).
1612
+ */
1613
+ s->intcapxten = !!(control & AMDVI_MMIO_CONTROL_INTCAPXTEN) && s->xtsup;
1614
1615
/* update the flags depending on the control register */
1616
if (s->cmdbuf_enabled) {
1820
case AMDVI_MMIO_STATUS:
1821
amdvi_mmio_reg_write(s, size, val, addr);
1822
break;
1823
+ case AMDVI_MMIO_XT_GEN_INTR:
1824
+ amdvi_mmio_reg_write(s, size, val, addr);
1825
+ break;
1826
}
1827
}
1828
2473
s->enabled = false;
2474
s->cmdbuf_enabled = false;
2475
s->xten = false;
2476
+ s->intcapxten = false;
2477
2478
/* reset MMIO */
2479
memset(s->mmior, 0, AMDVI_MMIO_SIZE);
2544
.minimum_version_id = 1,
2545
.fields = (VMStateField[]) {
2546
VMSTATE_BOOL(xten, AMDVIState),
2547
+ VMSTATE_BOOL(intcapxten, AMDVIState),
2548
VMSTATE_END_OF_LIST()
2549
}
2550
};