x86_iommu/amd: Add interrupt remap support when VAPIC is enabled
Emulate the interrupt remapping support when guest virtual APIC is enabled. For more information refer: IOMMU spec rev 3.0 (section 2.2.5.2) When VAPIC is enabled, it uses interrupt remapping as defined in Table 22 and Figure 17 from IOMMU spec. Signed-off-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Peter Xu <peterx@redhat.com> Cc: Peter Xu <peterx@redhat.com> Cc: "Michael S. Tsirkin" <mst@redhat.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Richard Henderson <rth@twiddle.net> Cc: Eduardo Habkost <ehabkost@redhat.com> Cc: Marcel Apfelbaum <marcel.apfelbaum@gmail.com> Cc: Tom Lendacky <Thomas.Lendacky@amd.com> Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
c028818d57
commit
135f866e60
@ -608,6 +608,7 @@ static void amdvi_handle_control_write(AMDVIState *s)
|
|||||||
s->completion_wait_intr = !!(control & AMDVI_MMIO_CONTROL_COMWAITINTEN);
|
s->completion_wait_intr = !!(control & AMDVI_MMIO_CONTROL_COMWAITINTEN);
|
||||||
s->cmdbuf_enabled = s->enabled && !!(control &
|
s->cmdbuf_enabled = s->enabled && !!(control &
|
||||||
AMDVI_MMIO_CONTROL_CMDBUFLEN);
|
AMDVI_MMIO_CONTROL_CMDBUFLEN);
|
||||||
|
s->ga_enabled = !!(control & AMDVI_MMIO_CONTROL_GAEN);
|
||||||
|
|
||||||
/* update the flags depending on the control register */
|
/* update the flags depending on the control register */
|
||||||
if (s->cmdbuf_enabled) {
|
if (s->cmdbuf_enabled) {
|
||||||
@ -1094,6 +1095,65 @@ static int amdvi_int_remap_legacy(AMDVIState *iommu,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int amdvi_get_irte_ga(AMDVIState *s, MSIMessage *origin, uint64_t *dte,
|
||||||
|
struct irte_ga *irte, uint16_t devid)
|
||||||
|
{
|
||||||
|
uint64_t irte_root, offset;
|
||||||
|
|
||||||
|
irte_root = dte[2] & AMDVI_IR_PHYS_ADDR_MASK;
|
||||||
|
offset = (origin->data & AMDVI_IRTE_OFFSET) << 4;
|
||||||
|
trace_amdvi_ir_irte(irte_root, offset);
|
||||||
|
|
||||||
|
if (dma_memory_read(&address_space_memory, irte_root + offset,
|
||||||
|
irte, sizeof(*irte))) {
|
||||||
|
trace_amdvi_ir_err("failed to get irte_ga");
|
||||||
|
return -AMDVI_IR_GET_IRTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_amdvi_ir_irte_ga_val(irte->hi.val, irte->lo.val);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int amdvi_int_remap_ga(AMDVIState *iommu,
|
||||||
|
MSIMessage *origin,
|
||||||
|
MSIMessage *translated,
|
||||||
|
uint64_t *dte,
|
||||||
|
X86IOMMUIrq *irq,
|
||||||
|
uint16_t sid)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct irte_ga irte;
|
||||||
|
|
||||||
|
/* get interrupt remapping table */
|
||||||
|
ret = amdvi_get_irte_ga(iommu, origin, dte, &irte, sid);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!irte.lo.fields_remap.valid) {
|
||||||
|
trace_amdvi_ir_target_abort("RemapEn is disabled");
|
||||||
|
return -AMDVI_IR_TARGET_ABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irte.lo.fields_remap.guest_mode) {
|
||||||
|
error_report_once("guest mode is not zero");
|
||||||
|
return -AMDVI_IR_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irte.lo.fields_remap.int_type > AMDVI_IOAPIC_INT_TYPE_ARBITRATED) {
|
||||||
|
error_report_once("reserved int_type is set");
|
||||||
|
return -AMDVI_IR_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
irq->delivery_mode = irte.lo.fields_remap.int_type;
|
||||||
|
irq->vector = irte.hi.fields.vector;
|
||||||
|
irq->dest_mode = irte.lo.fields_remap.dm;
|
||||||
|
irq->redir_hint = irte.lo.fields_remap.rq_eoi;
|
||||||
|
irq->dest = irte.lo.fields_remap.destination;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int __amdvi_int_remap_msi(AMDVIState *iommu,
|
static int __amdvi_int_remap_msi(AMDVIState *iommu,
|
||||||
MSIMessage *origin,
|
MSIMessage *origin,
|
||||||
MSIMessage *translated,
|
MSIMessage *translated,
|
||||||
@ -1101,6 +1161,7 @@ static int __amdvi_int_remap_msi(AMDVIState *iommu,
|
|||||||
X86IOMMUIrq *irq,
|
X86IOMMUIrq *irq,
|
||||||
uint16_t sid)
|
uint16_t sid)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
uint8_t int_ctl;
|
uint8_t int_ctl;
|
||||||
|
|
||||||
int_ctl = (dte[2] >> AMDVI_IR_INTCTL_SHIFT) & 3;
|
int_ctl = (dte[2] >> AMDVI_IR_INTCTL_SHIFT) & 3;
|
||||||
@ -1120,7 +1181,13 @@ static int __amdvi_int_remap_msi(AMDVIState *iommu,
|
|||||||
return -AMDVI_IR_ERR;
|
return -AMDVI_IR_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return amdvi_int_remap_legacy(iommu, origin, translated, dte, irq, sid);
|
if (iommu->ga_enabled) {
|
||||||
|
ret = amdvi_int_remap_ga(iommu, origin, translated, dte, irq, sid);
|
||||||
|
} else {
|
||||||
|
ret = amdvi_int_remap_legacy(iommu, origin, translated, dte, irq, sid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Interrupt remapping for MSI/MSI-X entry */
|
/* Interrupt remapping for MSI/MSI-X entry */
|
||||||
|
@ -103,6 +103,7 @@
|
|||||||
#define AMDVI_MMIO_CONTROL_EVENTINTEN (1ULL << 3)
|
#define AMDVI_MMIO_CONTROL_EVENTINTEN (1ULL << 3)
|
||||||
#define AMDVI_MMIO_CONTROL_COMWAITINTEN (1ULL << 4)
|
#define AMDVI_MMIO_CONTROL_COMWAITINTEN (1ULL << 4)
|
||||||
#define AMDVI_MMIO_CONTROL_CMDBUFLEN (1ULL << 12)
|
#define AMDVI_MMIO_CONTROL_CMDBUFLEN (1ULL << 12)
|
||||||
|
#define AMDVI_MMIO_CONTROL_GAEN (1ULL << 17)
|
||||||
|
|
||||||
/* MMIO status register bits */
|
/* MMIO status register bits */
|
||||||
#define AMDVI_MMIO_STATUS_CMDBUF_RUN (1 << 4)
|
#define AMDVI_MMIO_STATUS_CMDBUF_RUN (1 << 4)
|
||||||
@ -263,6 +264,38 @@ union irte {
|
|||||||
} fields;
|
} fields;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Interrupt remapping table fields (Guest VAPIC is enabled) */
|
||||||
|
union irte_ga_lo {
|
||||||
|
uint64_t val;
|
||||||
|
|
||||||
|
/* For int remapping */
|
||||||
|
struct {
|
||||||
|
uint64_t valid:1,
|
||||||
|
no_fault:1,
|
||||||
|
/* ------ */
|
||||||
|
int_type:3,
|
||||||
|
rq_eoi:1,
|
||||||
|
dm:1,
|
||||||
|
/* ------ */
|
||||||
|
guest_mode:1,
|
||||||
|
destination:8,
|
||||||
|
rsvd_1:48;
|
||||||
|
} fields_remap;
|
||||||
|
};
|
||||||
|
|
||||||
|
union irte_ga_hi {
|
||||||
|
uint64_t val;
|
||||||
|
struct {
|
||||||
|
uint64_t vector:8,
|
||||||
|
rsvd_2:56;
|
||||||
|
} fields;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct irte_ga {
|
||||||
|
union irte_ga_lo lo;
|
||||||
|
union irte_ga_hi hi;
|
||||||
|
};
|
||||||
|
|
||||||
#define TYPE_AMD_IOMMU_DEVICE "amd-iommu"
|
#define TYPE_AMD_IOMMU_DEVICE "amd-iommu"
|
||||||
#define AMD_IOMMU_DEVICE(obj)\
|
#define AMD_IOMMU_DEVICE(obj)\
|
||||||
OBJECT_CHECK(AMDVIState, (obj), TYPE_AMD_IOMMU_DEVICE)
|
OBJECT_CHECK(AMDVIState, (obj), TYPE_AMD_IOMMU_DEVICE)
|
||||||
@ -332,6 +365,9 @@ typedef struct AMDVIState {
|
|||||||
|
|
||||||
/* IOTLB */
|
/* IOTLB */
|
||||||
GHashTable *iotlb;
|
GHashTable *iotlb;
|
||||||
|
|
||||||
|
/* Interrupt remapping */
|
||||||
|
bool ga_enabled;
|
||||||
} AMDVIState;
|
} AMDVIState;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -113,6 +113,8 @@ amdvi_ir_intctl(uint8_t val) "int_ctl 0x%"PRIx8
|
|||||||
amdvi_ir_target_abort(const char *str) "%s"
|
amdvi_ir_target_abort(const char *str) "%s"
|
||||||
amdvi_ir_delivery_mode(const char *str) "%s"
|
amdvi_ir_delivery_mode(const char *str) "%s"
|
||||||
amdvi_ir_generate_msi_message(uint8_t vector, uint8_t delivery_mode, uint8_t dest_mode, uint8_t dest, uint8_t rh) "vector %d delivery-mode %d dest-mode %d dest-id %d rh %d"
|
amdvi_ir_generate_msi_message(uint8_t vector, uint8_t delivery_mode, uint8_t dest_mode, uint8_t dest, uint8_t rh) "vector %d delivery-mode %d dest-mode %d dest-id %d rh %d"
|
||||||
|
amdvi_ir_irte_ga(uint64_t addr, uint64_t data) "addr 0x%"PRIx64" offset 0x%"PRIx64
|
||||||
|
amdvi_ir_irte_ga_val(uint64_t hi, uint64_t lo) "hi 0x%"PRIx64" lo 0x%"PRIx64
|
||||||
|
|
||||||
# hw/i386/vmport.c
|
# hw/i386/vmport.c
|
||||||
vmport_register(unsigned char command, void *func, void *opaque) "command: 0x%02x func: %p opaque: %p"
|
vmport_register(unsigned char command, void *func, void *opaque) "command: 0x%02x func: %p opaque: %p"
|
||||||
|
Loading…
Reference in New Issue
Block a user