mirror of
https://github.com/qemu/qemu.git
synced 2024-11-28 22:33:36 +08:00
intel_iommu: add SID validation for IR
This patch enables SID validation. Invalid interrupts will be dropped. Signed-off-by: Peter Xu <peterx@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
28589311b3
commit
ede9c94acf
@ -2008,9 +2008,13 @@ static Property vtd_properties[] = {
|
||||
|
||||
/* Read IRTE entry with specific index */
|
||||
static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
|
||||
VTD_IRTE *entry)
|
||||
VTD_IRTE *entry, uint16_t sid)
|
||||
{
|
||||
static const uint16_t vtd_svt_mask[VTD_SQ_MAX] = \
|
||||
{0xffff, 0xfffb, 0xfff9, 0xfff8};
|
||||
dma_addr_t addr = 0x00;
|
||||
uint16_t mask, source_id;
|
||||
uint8_t bus, bus_max, bus_min;
|
||||
|
||||
addr = iommu->intr_root + index * sizeof(*entry);
|
||||
if (dma_memory_read(&address_space_memory, addr, entry,
|
||||
@ -2037,21 +2041,56 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
|
||||
return -VTD_FR_IR_IRTE_RSVD;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Check Source-ID corresponds to SVT (Source Validation
|
||||
* Type) bits
|
||||
*/
|
||||
if (sid != X86_IOMMU_SID_INVALID) {
|
||||
/* Validate IRTE SID */
|
||||
source_id = le32_to_cpu(entry->source_id);
|
||||
switch (entry->sid_vtype) {
|
||||
case VTD_SVT_NONE:
|
||||
VTD_DPRINTF(IR, "No SID validation for IRTE index %d", index);
|
||||
break;
|
||||
|
||||
case VTD_SVT_ALL:
|
||||
mask = vtd_svt_mask[entry->sid_q];
|
||||
if ((source_id & mask) != (sid & mask)) {
|
||||
VTD_DPRINTF(GENERAL, "SID validation for IRTE index "
|
||||
"%d failed (reqid 0x%04x sid 0x%04x)", index,
|
||||
sid, source_id);
|
||||
return -VTD_FR_IR_SID_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case VTD_SVT_BUS:
|
||||
bus_max = source_id >> 8;
|
||||
bus_min = source_id & 0xff;
|
||||
bus = sid >> 8;
|
||||
if (bus > bus_max || bus < bus_min) {
|
||||
VTD_DPRINTF(GENERAL, "SID validation for IRTE index %d "
|
||||
"failed (bus %d outside %d-%d)", index, bus,
|
||||
bus_min, bus_max);
|
||||
return -VTD_FR_IR_SID_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
VTD_DPRINTF(GENERAL, "Invalid SVT bits (0x%x) in IRTE index "
|
||||
"%d", entry->sid_vtype, index);
|
||||
/* Take this as verification failure. */
|
||||
return -VTD_FR_IR_SID_ERR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fetch IRQ information of specific IR index */
|
||||
static int vtd_remap_irq_get(IntelIOMMUState *iommu, uint16_t index, VTDIrq *irq)
|
||||
static int vtd_remap_irq_get(IntelIOMMUState *iommu, uint16_t index,
|
||||
VTDIrq *irq, uint16_t sid)
|
||||
{
|
||||
VTD_IRTE irte = {};
|
||||
int ret = 0;
|
||||
|
||||
ret = vtd_irte_get(iommu, index, &irte);
|
||||
ret = vtd_irte_get(iommu, index, &irte, sid);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
@ -2103,7 +2142,8 @@ static void vtd_generate_msi_message(VTDIrq *irq, MSIMessage *msg_out)
|
||||
/* Interrupt remapping for MSI/MSI-X entry */
|
||||
static int vtd_interrupt_remap_msi(IntelIOMMUState *iommu,
|
||||
MSIMessage *origin,
|
||||
MSIMessage *translated)
|
||||
MSIMessage *translated,
|
||||
uint16_t sid)
|
||||
{
|
||||
int ret = 0;
|
||||
VTD_IR_MSIAddress addr;
|
||||
@ -2146,7 +2186,7 @@ static int vtd_interrupt_remap_msi(IntelIOMMUState *iommu,
|
||||
index += origin->data & VTD_IR_MSI_DATA_SUBHANDLE;
|
||||
}
|
||||
|
||||
ret = vtd_remap_irq_get(iommu, index, &irq);
|
||||
ret = vtd_remap_irq_get(iommu, index, &irq, sid);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
@ -2193,7 +2233,8 @@ do_not_translate:
|
||||
static int vtd_int_remap(X86IOMMUState *iommu, MSIMessage *src,
|
||||
MSIMessage *dst, uint16_t sid)
|
||||
{
|
||||
return vtd_interrupt_remap_msi(INTEL_IOMMU_DEVICE(iommu), src, dst);
|
||||
return vtd_interrupt_remap_msi(INTEL_IOMMU_DEVICE(iommu),
|
||||
src, dst, sid);
|
||||
}
|
||||
|
||||
static MemTxResult vtd_mem_ir_read(void *opaque, hwaddr addr,
|
||||
@ -2209,11 +2250,17 @@ static MemTxResult vtd_mem_ir_write(void *opaque, hwaddr addr,
|
||||
{
|
||||
int ret = 0;
|
||||
MSIMessage from = {}, to = {};
|
||||
uint16_t sid = X86_IOMMU_SID_INVALID;
|
||||
|
||||
from.address = (uint64_t) addr + VTD_INTERRUPT_ADDR_FIRST;
|
||||
from.data = (uint32_t) value;
|
||||
|
||||
ret = vtd_interrupt_remap_msi(opaque, &from, &to);
|
||||
if (!attrs.unspecified) {
|
||||
/* We have explicit Source ID */
|
||||
sid = attrs.requester_id;
|
||||
}
|
||||
|
||||
ret = vtd_interrupt_remap_msi(opaque, &from, &to, sid);
|
||||
if (ret) {
|
||||
/* TODO: report error */
|
||||
VTD_DPRINTF(GENERAL, "int remap fail for addr 0x%"PRIx64
|
||||
|
@ -102,6 +102,23 @@ struct VTDIOTLBEntry {
|
||||
bool write_flags;
|
||||
};
|
||||
|
||||
/* VT-d Source-ID Qualifier types */
|
||||
enum {
|
||||
VTD_SQ_FULL = 0x00, /* Full SID verification */
|
||||
VTD_SQ_IGN_3 = 0x01, /* Ignore bit 3 */
|
||||
VTD_SQ_IGN_2_3 = 0x02, /* Ignore bits 2 & 3 */
|
||||
VTD_SQ_IGN_1_3 = 0x03, /* Ignore bits 1-3 */
|
||||
VTD_SQ_MAX,
|
||||
};
|
||||
|
||||
/* VT-d Source Validation Types */
|
||||
enum {
|
||||
VTD_SVT_NONE = 0x00, /* No validation */
|
||||
VTD_SVT_ALL = 0x01, /* Do full validation */
|
||||
VTD_SVT_BUS = 0x02, /* Validate bus range */
|
||||
VTD_SVT_MAX,
|
||||
};
|
||||
|
||||
/* Interrupt Remapping Table Entry Definition */
|
||||
union VTD_IRTE {
|
||||
struct {
|
||||
|
Loading…
Reference in New Issue
Block a user