mirror of https://github.com/proxmox/mirror_qemu
hw/i386/intel_iommu: Fix endianness problems related to VTD_IR_TableEntry
The code already tries to do some endianness handling here, but
currently fails badly:
- While it already swaps the data when logging errors / tracing, it fails
to byteswap the value before e.g. accessing entry->irte.present
- entry->irte.source_id is swapped with le32_to_cpu(), though this is
a 16-bit value
- The whole union is apparently supposed to be swapped via the 64-bit
data[2] array, but the struct is a mixture between 32 bit values
(the first 8 bytes) and 64 bit values (the second 8 bytes), so this
cannot work as expected.
Fix it by converting the struct to two proper 64-bit bitfields, and
by swapping the values only once for everybody right after reading
the data from memory.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20230802135723.178083-3-thuth@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
(cherry picked from commit 642ba89672
)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
parent
cf2be5881f
commit
bbe3627f44
|
@ -3323,14 +3323,15 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
|
|||
return -VTD_FR_IR_ROOT_INVAL;
|
||||
}
|
||||
|
||||
trace_vtd_ir_irte_get(index, le64_to_cpu(entry->data[1]),
|
||||
le64_to_cpu(entry->data[0]));
|
||||
entry->data[0] = le64_to_cpu(entry->data[0]);
|
||||
entry->data[1] = le64_to_cpu(entry->data[1]);
|
||||
|
||||
trace_vtd_ir_irte_get(index, entry->data[1], entry->data[0]);
|
||||
|
||||
if (!entry->irte.present) {
|
||||
error_report_once("%s: detected non-present IRTE "
|
||||
"(index=%u, high=0x%" PRIx64 ", low=0x%" PRIx64 ")",
|
||||
__func__, index, le64_to_cpu(entry->data[1]),
|
||||
le64_to_cpu(entry->data[0]));
|
||||
__func__, index, entry->data[1], entry->data[0]);
|
||||
return -VTD_FR_IR_ENTRY_P;
|
||||
}
|
||||
|
||||
|
@ -3338,14 +3339,13 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
|
|||
entry->irte.__reserved_2) {
|
||||
error_report_once("%s: detected non-zero reserved IRTE "
|
||||
"(index=%u, high=0x%" PRIx64 ", low=0x%" PRIx64 ")",
|
||||
__func__, index, le64_to_cpu(entry->data[1]),
|
||||
le64_to_cpu(entry->data[0]));
|
||||
__func__, index, entry->data[1], entry->data[0]);
|
||||
return -VTD_FR_IR_IRTE_RSVD;
|
||||
}
|
||||
|
||||
if (sid != X86_IOMMU_SID_INVALID) {
|
||||
/* Validate IRTE SID */
|
||||
source_id = le32_to_cpu(entry->irte.source_id);
|
||||
source_id = entry->irte.source_id;
|
||||
switch (entry->irte.sid_vtype) {
|
||||
case VTD_SVT_NONE:
|
||||
break;
|
||||
|
@ -3399,7 +3399,7 @@ static int vtd_remap_irq_get(IntelIOMMUState *iommu, uint16_t index,
|
|||
irq->trigger_mode = irte.irte.trigger_mode;
|
||||
irq->vector = irte.irte.vector;
|
||||
irq->delivery_mode = irte.irte.delivery_mode;
|
||||
irq->dest = le32_to_cpu(irte.irte.dest_id);
|
||||
irq->dest = irte.irte.dest_id;
|
||||
if (!iommu->intr_eime) {
|
||||
#define VTD_IR_APIC_DEST_MASK (0xff00ULL)
|
||||
#define VTD_IR_APIC_DEST_SHIFT (8)
|
||||
|
|
|
@ -142,37 +142,39 @@ enum {
|
|||
union VTD_IR_TableEntry {
|
||||
struct {
|
||||
#if HOST_BIG_ENDIAN
|
||||
uint32_t __reserved_1:8; /* Reserved 1 */
|
||||
uint32_t vector:8; /* Interrupt Vector */
|
||||
uint32_t irte_mode:1; /* IRTE Mode */
|
||||
uint32_t __reserved_0:3; /* Reserved 0 */
|
||||
uint32_t __avail:4; /* Available spaces for software */
|
||||
uint32_t delivery_mode:3; /* Delivery Mode */
|
||||
uint32_t trigger_mode:1; /* Trigger Mode */
|
||||
uint32_t redir_hint:1; /* Redirection Hint */
|
||||
uint32_t dest_mode:1; /* Destination Mode */
|
||||
uint32_t fault_disable:1; /* Fault Processing Disable */
|
||||
uint32_t present:1; /* Whether entry present/available */
|
||||
uint64_t dest_id:32; /* Destination ID */
|
||||
uint64_t __reserved_1:8; /* Reserved 1 */
|
||||
uint64_t vector:8; /* Interrupt Vector */
|
||||
uint64_t irte_mode:1; /* IRTE Mode */
|
||||
uint64_t __reserved_0:3; /* Reserved 0 */
|
||||
uint64_t __avail:4; /* Available spaces for software */
|
||||
uint64_t delivery_mode:3; /* Delivery Mode */
|
||||
uint64_t trigger_mode:1; /* Trigger Mode */
|
||||
uint64_t redir_hint:1; /* Redirection Hint */
|
||||
uint64_t dest_mode:1; /* Destination Mode */
|
||||
uint64_t fault_disable:1; /* Fault Processing Disable */
|
||||
uint64_t present:1; /* Whether entry present/available */
|
||||
#else
|
||||
uint32_t present:1; /* Whether entry present/available */
|
||||
uint32_t fault_disable:1; /* Fault Processing Disable */
|
||||
uint32_t dest_mode:1; /* Destination Mode */
|
||||
uint32_t redir_hint:1; /* Redirection Hint */
|
||||
uint32_t trigger_mode:1; /* Trigger Mode */
|
||||
uint32_t delivery_mode:3; /* Delivery Mode */
|
||||
uint32_t __avail:4; /* Available spaces for software */
|
||||
uint32_t __reserved_0:3; /* Reserved 0 */
|
||||
uint32_t irte_mode:1; /* IRTE Mode */
|
||||
uint32_t vector:8; /* Interrupt Vector */
|
||||
uint32_t __reserved_1:8; /* Reserved 1 */
|
||||
uint64_t present:1; /* Whether entry present/available */
|
||||
uint64_t fault_disable:1; /* Fault Processing Disable */
|
||||
uint64_t dest_mode:1; /* Destination Mode */
|
||||
uint64_t redir_hint:1; /* Redirection Hint */
|
||||
uint64_t trigger_mode:1; /* Trigger Mode */
|
||||
uint64_t delivery_mode:3; /* Delivery Mode */
|
||||
uint64_t __avail:4; /* Available spaces for software */
|
||||
uint64_t __reserved_0:3; /* Reserved 0 */
|
||||
uint64_t irte_mode:1; /* IRTE Mode */
|
||||
uint64_t vector:8; /* Interrupt Vector */
|
||||
uint64_t __reserved_1:8; /* Reserved 1 */
|
||||
uint64_t dest_id:32; /* Destination ID */
|
||||
#endif
|
||||
uint32_t dest_id; /* Destination ID */
|
||||
uint16_t source_id; /* Source-ID */
|
||||
#if HOST_BIG_ENDIAN
|
||||
uint64_t __reserved_2:44; /* Reserved 2 */
|
||||
uint64_t sid_vtype:2; /* Source-ID Validation Type */
|
||||
uint64_t sid_q:2; /* Source-ID Qualifier */
|
||||
uint64_t source_id:16; /* Source-ID */
|
||||
#else
|
||||
uint64_t source_id:16; /* Source-ID */
|
||||
uint64_t sid_q:2; /* Source-ID Qualifier */
|
||||
uint64_t sid_vtype:2; /* Source-ID Validation Type */
|
||||
uint64_t __reserved_2:44; /* Reserved 2 */
|
||||
|
|
Loading…
Reference in New Issue