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>
This commit is contained in:
Thomas Huth 2023-08-02 15:57:19 +02:00 committed by Michael S. Tsirkin
parent cc2a08480e
commit 642ba89672
2 changed files with 34 additions and 32 deletions

View file

@ -178,37 +178,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 */