diff mbox

[v7,07/25] intel_iommu: define several structs for IOMMU IR

Message ID 1463469353-25642-8-git-send-email-peterx@redhat.com
State New
Headers show

Commit Message

Peter Xu May 17, 2016, 7:15 a.m. UTC
Several data structs are defined to better support the rest of the
patches: IRTE to parse remapping table entries, and IOAPIC/MSI related
structure bits to parse interrupt entries to be filled in by guest
kernel.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/hw/i386/intel_iommu.h | 60 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

Comments

David Kiarie May 29, 2016, 8:20 a.m. UTC | #1
On Tue, May 17, 2016 at 10:15 AM, Peter Xu <peterx@redhat.com> wrote:
> Several data structs are defined to better support the rest of the
> patches: IRTE to parse remapping table entries, and IOAPIC/MSI related
> structure bits to parse interrupt entries to be filled in by guest
> kernel.
>
> Signed-off-by: Peter Xu <peterx@redhat.com>
> ---
>  include/hw/i386/intel_iommu.h | 60 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 60 insertions(+)
>
> diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
> index cc49839..4914fe6 100644
> --- a/include/hw/i386/intel_iommu.h
> +++ b/include/hw/i386/intel_iommu.h
> @@ -52,6 +52,9 @@ typedef struct IntelIOMMUState IntelIOMMUState;
>  typedef struct VTDAddressSpace VTDAddressSpace;
>  typedef struct VTDIOTLBEntry VTDIOTLBEntry;
>  typedef struct VTDBus VTDBus;
> +typedef union VTD_IRTE VTD_IRTE;
> +typedef union VTD_IR_IOAPICEntry VTD_IR_IOAPICEntry;
> +typedef union VTD_IR_MSIAddress VTD_IR_MSIAddress;
>
>  /* Context-Entry */
>  struct VTDContextEntry {
> @@ -90,6 +93,63 @@ struct VTDIOTLBEntry {
>      bool write_flags;
>  };
>
> +/* Interrupt Remapping Table Entry Definition */
> +union VTD_IRTE {
> +    struct {
> +        uint8_t present:1;          /* Whether entry present/available */
> +        uint8_t fault_disable:1;    /* Fault Processing Disable */
> +        uint8_t dest_mode:1;        /* Destination Mode */
> +        uint8_t redir_hint:1;       /* Redirection Hint */
> +        uint8_t trigger_mode:1;     /* Trigger Mode */
> +        uint8_t delivery_mode:3;    /* Delivery Mode */
> +        uint8_t __avail:4;          /* Available spaces for software */
> +        uint8_t __reserved_0:3;     /* Reserved 0 */
> +        uint8_t irte_mode:1;        /* IRTE Mode */
> +        uint8_t vector:8;           /* Interrupt Vector */
> +        uint8_t __reserved_1:8;     /* Reserved 1 */
> +        uint32_t dest_id:32;        /* Destination ID */
> +        uint16_t source_id:16;      /* Source-ID */
> +        uint8_t sid_q:2;            /* Source-ID Qualifier */
> +        uint8_t sid_vtype:2;        /* Source-ID Validation Type */
> +        uint64_t __reserved_2:44;   /* Reserved 2 */
> +    } QEMU_PACKED;
> +    uint64_t data[2];
> +};
> +
> +/* Programming format for IOAPIC table entries */
> +union VTD_IR_IOAPICEntry {
> +    struct {
> +        uint8_t vector:8;           /* Vector */
> +        uint8_t __zeros:3;          /* Reserved (all zero) */
> +        uint8_t index_h:1;          /* Interrupt Index bit 15 */
> +        uint8_t status:1;           /* Deliver Status */
> +        uint8_t polarity:1;         /* Interrupt Polarity */
> +        uint8_t remote_irr:1;       /* Remote IRR */
> +        uint8_t trigger_mode:1;     /* Trigger Mode */
> +        uint8_t mask:1;             /* Mask */
> +        uint32_t __reserved:31;     /* Reserved (should all zero) */
> +        uint8_t int_mode:1;         /* Interrupt Format */
> +        uint16_t index_l:15;        /* Interrupt Index bits 14-0 */
> +    } QEMU_PACKED;
> +    uint64_t data;
> +};
> +
> +/* Programming format for MSI/MSI-X addresses */
> +union VTD_IR_MSIAddress {
> +    struct {
> +        uint8_t __not_care:2;
> +        uint8_t index_h:1;          /* Interrupt index bit 15 */
> +        uint8_t sub_valid:1;        /* SHV: Sub-Handle Valid bit */
> +        uint8_t int_mode:1;         /* Interrupt format */
> +        uint16_t index_l:15;        /* Interrupt index bit 14-0 */
> +        uint16_t __head:12;         /* Should always be: 0x0fee */
> +    } QEMU_PACKED;
> +    uint32_t data;
> +};

In a recent discussion, it was brought to my attention that you might
have a problem with bitfields when the host cpu is not x86. Have you
considered this ?

> +
> +/* When IR is enabled, all MSI/MSI-X data bits should be zero */
> +#define VTD_IR_MSI_DATA          (0)
> +
>  /* The iommu (DMAR) device state struct */
>  struct IntelIOMMUState {
>      SysBusDevice busdev;
> --
> 2.4.11
>
David Kiarie May 29, 2016, 8:21 a.m. UTC | #2
On Sun, May 29, 2016 at 11:20 AM, David Kiarie <davidkiarie4@gmail.com> wrote:
> On Tue, May 17, 2016 at 10:15 AM, Peter Xu <peterx@redhat.com> wrote:
>> Several data structs are defined to better support the rest of the
>> patches: IRTE to parse remapping table entries, and IOAPIC/MSI related
>> structure bits to parse interrupt entries to be filled in by guest
>> kernel.
>>
>> Signed-off-by: Peter Xu <peterx@redhat.com>
>> ---
>>  include/hw/i386/intel_iommu.h | 60 +++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 60 insertions(+)
>>
>> diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
>> index cc49839..4914fe6 100644
>> --- a/include/hw/i386/intel_iommu.h
>> +++ b/include/hw/i386/intel_iommu.h
>> @@ -52,6 +52,9 @@ typedef struct IntelIOMMUState IntelIOMMUState;
>>  typedef struct VTDAddressSpace VTDAddressSpace;
>>  typedef struct VTDIOTLBEntry VTDIOTLBEntry;
>>  typedef struct VTDBus VTDBus;
>> +typedef union VTD_IRTE VTD_IRTE;
>> +typedef union VTD_IR_IOAPICEntry VTD_IR_IOAPICEntry;
>> +typedef union VTD_IR_MSIAddress VTD_IR_MSIAddress;
>>
>>  /* Context-Entry */
>>  struct VTDContextEntry {
>> @@ -90,6 +93,63 @@ struct VTDIOTLBEntry {
>>      bool write_flags;
>>  };
>>
>> +/* Interrupt Remapping Table Entry Definition */
>> +union VTD_IRTE {
>> +    struct {
>> +        uint8_t present:1;          /* Whether entry present/available */
>> +        uint8_t fault_disable:1;    /* Fault Processing Disable */
>> +        uint8_t dest_mode:1;        /* Destination Mode */
>> +        uint8_t redir_hint:1;       /* Redirection Hint */
>> +        uint8_t trigger_mode:1;     /* Trigger Mode */
>> +        uint8_t delivery_mode:3;    /* Delivery Mode */
>> +        uint8_t __avail:4;          /* Available spaces for software */
>> +        uint8_t __reserved_0:3;     /* Reserved 0 */
>> +        uint8_t irte_mode:1;        /* IRTE Mode */
>> +        uint8_t vector:8;           /* Interrupt Vector */
>> +        uint8_t __reserved_1:8;     /* Reserved 1 */
>> +        uint32_t dest_id:32;        /* Destination ID */
>> +        uint16_t source_id:16;      /* Source-ID */
>> +        uint8_t sid_q:2;            /* Source-ID Qualifier */
>> +        uint8_t sid_vtype:2;        /* Source-ID Validation Type */
>> +        uint64_t __reserved_2:44;   /* Reserved 2 */
>> +    } QEMU_PACKED;
>> +    uint64_t data[2];
>> +};
>> +
>> +/* Programming format for IOAPIC table entries */
>> +union VTD_IR_IOAPICEntry {
>> +    struct {
>> +        uint8_t vector:8;           /* Vector */
>> +        uint8_t __zeros:3;          /* Reserved (all zero) */
>> +        uint8_t index_h:1;          /* Interrupt Index bit 15 */
>> +        uint8_t status:1;           /* Deliver Status */
>> +        uint8_t polarity:1;         /* Interrupt Polarity */
>> +        uint8_t remote_irr:1;       /* Remote IRR */
>> +        uint8_t trigger_mode:1;     /* Trigger Mode */
>> +        uint8_t mask:1;             /* Mask */
>> +        uint32_t __reserved:31;     /* Reserved (should all zero) */
>> +        uint8_t int_mode:1;         /* Interrupt Format */
>> +        uint16_t index_l:15;        /* Interrupt Index bits 14-0 */
>> +    } QEMU_PACKED;
>> +    uint64_t data;
>> +};
>> +
>> +/* Programming format for MSI/MSI-X addresses */
>> +union VTD_IR_MSIAddress {
>> +    struct {
>> +        uint8_t __not_care:2;
>> +        uint8_t index_h:1;          /* Interrupt index bit 15 */
>> +        uint8_t sub_valid:1;        /* SHV: Sub-Handle Valid bit */
>> +        uint8_t int_mode:1;         /* Interrupt format */
>> +        uint16_t index_l:15;        /* Interrupt index bit 14-0 */
>> +        uint16_t __head:12;         /* Should always be: 0x0fee */
>> +    } QEMU_PACKED;
>> +    uint32_t data;
>> +};
>
> In a recent discussion, it was brought to my attention that you might
> have a problem with bitfields when the host cpu is not x86. Have you
> considered this ?

In a case when say the host cpu is little endian.

>
>> +
>> +/* When IR is enabled, all MSI/MSI-X data bits should be zero */
>> +#define VTD_IR_MSI_DATA          (0)
>> +
>>  /* The iommu (DMAR) device state struct */
>>  struct IntelIOMMUState {
>>      SysBusDevice busdev;
>> --
>> 2.4.11
>>
Peter Xu May 30, 2016, 5:45 a.m. UTC | #3
On Sun, May 29, 2016 at 11:21:35AM +0300, David Kiarie wrote:
[...]
> >> +
> >> +/* Programming format for MSI/MSI-X addresses */
> >> +union VTD_IR_MSIAddress {
> >> +    struct {
> >> +        uint8_t __not_care:2;
> >> +        uint8_t index_h:1;          /* Interrupt index bit 15 */
> >> +        uint8_t sub_valid:1;        /* SHV: Sub-Handle Valid bit */
> >> +        uint8_t int_mode:1;         /* Interrupt format */
> >> +        uint16_t index_l:15;        /* Interrupt index bit 14-0 */
> >> +        uint16_t __head:12;         /* Should always be: 0x0fee */
> >> +    } QEMU_PACKED;
> >> +    uint32_t data;
> >> +};
> >
> > In a recent discussion, it was brought to my attention that you might
> > have a problem with bitfields when the host cpu is not x86. Have you
> > considered this ?
> 
> In a case when say the host cpu is little endian.

I assume you mean when host cpu is big endian. x86 was little endian,
and I was testing on x86.

I think you are right. I should do conditional byte swap for all
uint{16/32/64} cases within the fields. For example, index_l field in
above VTD_IR_MSIAddress. And there are several other cases that need
special treatment in the patchset. Will go over and fix corresponding
issues in next version.

Thanks!

-- peterx
Jan Kiszka May 30, 2016, 5:56 a.m. UTC | #4
On 2016-05-30 07:45, Peter Xu wrote:
> On Sun, May 29, 2016 at 11:21:35AM +0300, David Kiarie wrote:
> [...]
>>>> +
>>>> +/* Programming format for MSI/MSI-X addresses */
>>>> +union VTD_IR_MSIAddress {
>>>> +    struct {
>>>> +        uint8_t __not_care:2;
>>>> +        uint8_t index_h:1;          /* Interrupt index bit 15 */
>>>> +        uint8_t sub_valid:1;        /* SHV: Sub-Handle Valid bit */
>>>> +        uint8_t int_mode:1;         /* Interrupt format */
>>>> +        uint16_t index_l:15;        /* Interrupt index bit 14-0 */
>>>> +        uint16_t __head:12;         /* Should always be: 0x0fee */
>>>> +    } QEMU_PACKED;
>>>> +    uint32_t data;
>>>> +};
>>>
>>> In a recent discussion, it was brought to my attention that you might
>>> have a problem with bitfields when the host cpu is not x86. Have you
>>> considered this ?
>>
>> In a case when say the host cpu is little endian.
> 
> I assume you mean when host cpu is big endian. x86 was little endian,
> and I was testing on x86.
> 
> I think you are right. I should do conditional byte swap for all
> uint{16/32/64} cases within the fields. For example, index_l field in
> above VTD_IR_MSIAddress. And there are several other cases that need
> special treatment in the patchset. Will go over and fix corresponding
> issues in next version.

You actually need bit-swap with bit fields, see e.g. hw/net/vmxnet3.h.

Jan
Peter Xu May 30, 2016, 8:14 a.m. UTC | #5
On Mon, May 30, 2016 at 07:56:16AM +0200, Jan Kiszka wrote:
> On 2016-05-30 07:45, Peter Xu wrote:
> > On Sun, May 29, 2016 at 11:21:35AM +0300, David Kiarie wrote:
> > [...]
> >>>> +
> >>>> +/* Programming format for MSI/MSI-X addresses */
> >>>> +union VTD_IR_MSIAddress {
> >>>> +    struct {
> >>>> +        uint8_t __not_care:2;
> >>>> +        uint8_t index_h:1;          /* Interrupt index bit 15 */
> >>>> +        uint8_t sub_valid:1;        /* SHV: Sub-Handle Valid bit */
> >>>> +        uint8_t int_mode:1;         /* Interrupt format */
> >>>> +        uint16_t index_l:15;        /* Interrupt index bit 14-0 */
> >>>> +        uint16_t __head:12;         /* Should always be: 0x0fee */
> >>>> +    } QEMU_PACKED;
> >>>> +    uint32_t data;
> >>>> +};
> >>>
> >>> In a recent discussion, it was brought to my attention that you might
> >>> have a problem with bitfields when the host cpu is not x86. Have you
> >>> considered this ?
> >>
> >> In a case when say the host cpu is little endian.
> > 
> > I assume you mean when host cpu is big endian. x86 was little endian,
> > and I was testing on x86.
> > 
> > I think you are right. I should do conditional byte swap for all
> > uint{16/32/64} cases within the fields. For example, index_l field in
> > above VTD_IR_MSIAddress. And there are several other cases that need
> > special treatment in the patchset. Will go over and fix corresponding
> > issues in next version.
> 
> You actually need bit-swap with bit fields, see e.g. hw/net/vmxnet3.h.

Not noticed about bit-field ordering before... So maybe I need both?

Thanks,

-- peterx
David Kiarie May 30, 2016, 8:54 a.m. UTC | #6
On Mon, May 30, 2016 at 11:14 AM, Peter Xu <peterx@redhat.com> wrote:
> On Mon, May 30, 2016 at 07:56:16AM +0200, Jan Kiszka wrote:
>> On 2016-05-30 07:45, Peter Xu wrote:
>> > On Sun, May 29, 2016 at 11:21:35AM +0300, David Kiarie wrote:
>> > [...]
>> >>>> +
>> >>>> +/* Programming format for MSI/MSI-X addresses */
>> >>>> +union VTD_IR_MSIAddress {
>> >>>> +    struct {
>> >>>> +        uint8_t __not_care:2;
>> >>>> +        uint8_t index_h:1;          /* Interrupt index bit 15 */
>> >>>> +        uint8_t sub_valid:1;        /* SHV: Sub-Handle Valid bit */
>> >>>> +        uint8_t int_mode:1;         /* Interrupt format */
>> >>>> +        uint16_t index_l:15;        /* Interrupt index bit 14-0 */
>> >>>> +        uint16_t __head:12;         /* Should always be: 0x0fee */
>> >>>> +    } QEMU_PACKED;
>> >>>> +    uint32_t data;
>> >>>> +};
>> >>>
>> >>> In a recent discussion, it was brought to my attention that you might
>> >>> have a problem with bitfields when the host cpu is not x86. Have you
>> >>> considered this ?
>> >>
>> >> In a case when say the host cpu is little endian.
>> >
>> > I assume you mean when host cpu is big endian. x86 was little endian,
>> > and I was testing on x86.
>> >
>> > I think you are right. I should do conditional byte swap for all
>> > uint{16/32/64} cases within the fields. For example, index_l field in
>> > above VTD_IR_MSIAddress. And there are several other cases that need
>> > special treatment in the patchset. Will go over and fix corresponding
>> > issues in next version.
>>
>> You actually need bit-swap with bit fields, see e.g. hw/net/vmxnet3.h.
>
> Not noticed about bit-field ordering before... So maybe I need both?

Yes, I think we will need both though, I think, byte swapping the
whole struct will break the code but swapping individual fields is
what we need.

Myself, I'm defining bitfields as below:

  struct CMDCompletionWait {

#ifdef __BIG_ENDIAN_BITFIELD
    uint32_t type:4;               /* command type           */
    uint32_t reserved:8;
    uint64_t store_addr:49;        /* addr to write          */
    uint32_t completion_flush:1;   /* allow more executions  */
    uint32_t completion_int:1;     /* set MMIOWAITINT        */
    uint32_t completion_store:1;   /* write data to address  */
#else
    uint32_t completion_store:1;
    uint32_t completion_int:1;
    uint32_t completion_flush:1;
    uint64_t store_addr:49;
    uint32_t reserved:8;
    uint32_t type:4;
#endif /* __BIG_ENDIAN_BITFIELD */

    uint64_t store_data;           /* data to write          */
if
} QEMU_PACKED;

So, the bitfields are basically aligned to a {1,2,4,8}-byte boundary.
I will have to swap store_addr,type, store_data, e.t.c.

>
> Thanks,
>
> -- peterx
Peter Xu May 30, 2016, 9:16 a.m. UTC | #7
On Mon, May 30, 2016 at 11:54:52AM +0300, David Kiarie wrote:
> On Mon, May 30, 2016 at 11:14 AM, Peter Xu <peterx@redhat.com> wrote:
> > On Mon, May 30, 2016 at 07:56:16AM +0200, Jan Kiszka wrote:
> >> On 2016-05-30 07:45, Peter Xu wrote:
[...]
> >> >
> >> > I assume you mean when host cpu is big endian. x86 was little endian,
> >> > and I was testing on x86.
> >> >
> >> > I think you are right. I should do conditional byte swap for all
> >> > uint{16/32/64} cases within the fields. For example, index_l field in
> >> > above VTD_IR_MSIAddress. And there are several other cases that need
> >> > special treatment in the patchset. Will go over and fix corresponding
> >> > issues in next version.
> >>
> >> You actually need bit-swap with bit fields, see e.g. hw/net/vmxnet3.h.
> >
> > Not noticed about bit-field ordering before... So maybe I need both?
> 
> Yes, I think we will need both though, I think, byte swapping the
> whole struct will break the code but swapping individual fields is
> what we need.
> 
> Myself, I'm defining bitfields as below:
> 
>   struct CMDCompletionWait {
> 
> #ifdef __BIG_ENDIAN_BITFIELD
>     uint32_t type:4;               /* command type           */
>     uint32_t reserved:8;
>     uint64_t store_addr:49;        /* addr to write          */
>     uint32_t completion_flush:1;   /* allow more executions  */
>     uint32_t completion_int:1;     /* set MMIOWAITINT        */
>     uint32_t completion_store:1;   /* write data to address  */

I guess what we need might be this one:

      uint64_t type:4;               /* command type           */
      uint64_t reserved:8;
      uint64_t store_addr:49;        /* addr to write          */
      uint64_t completion_flush:1;   /* allow more executions  */
      uint64_t completion_int:1;     /* set MMIOWAITINT        */
      uint64_t completion_store:1;   /* write data to address  */

IIUC, if we define type:4 as uint32_t rather than uint64_t, it should
be bits [29:32] of the struct on big endian machines, not bits
[61:64].

Thanks,

-- peterx
David Kiarie May 30, 2016, 9:25 a.m. UTC | #8
On Mon, May 30, 2016 at 12:16 PM, Peter Xu <peterx@redhat.com> wrote:
> On Mon, May 30, 2016 at 11:54:52AM +0300, David Kiarie wrote:
>> On Mon, May 30, 2016 at 11:14 AM, Peter Xu <peterx@redhat.com> wrote:
>> > On Mon, May 30, 2016 at 07:56:16AM +0200, Jan Kiszka wrote:
>> >> On 2016-05-30 07:45, Peter Xu wrote:
> [...]
>> >> >
>> >> > I assume you mean when host cpu is big endian. x86 was little endian,
>> >> > and I was testing on x86.
>> >> >
>> >> > I think you are right. I should do conditional byte swap for all
>> >> > uint{16/32/64} cases within the fields. For example, index_l field in
>> >> > above VTD_IR_MSIAddress. And there are several other cases that need
>> >> > special treatment in the patchset. Will go over and fix corresponding
>> >> > issues in next version.
>> >>
>> >> You actually need bit-swap with bit fields, see e.g. hw/net/vmxnet3.h.
>> >
>> > Not noticed about bit-field ordering before... So maybe I need both?
>>
>> Yes, I think we will need both though, I think, byte swapping the
>> whole struct will break the code but swapping individual fields is
>> what we need.
>>
>> Myself, I'm defining bitfields as below:
>>
>>   struct CMDCompletionWait {
>>
>> #ifdef __BIG_ENDIAN_BITFIELD
>>     uint32_t type:4;               /* command type           */
>>     uint32_t reserved:8;
>>     uint64_t store_addr:49;        /* addr to write          */
>>     uint32_t completion_flush:1;   /* allow more executions  */
>>     uint32_t completion_int:1;     /* set MMIOWAITINT        */
>>     uint32_t completion_store:1;   /* write data to address  */
>
> I guess what we need might be this one:
>
>       uint64_t type:4;               /* command type           */
>       uint64_t reserved:8;
>       uint64_t store_addr:49;        /* addr to write          */
>       uint64_t completion_flush:1;   /* allow more executions  */
>       uint64_t completion_int:1;     /* set MMIOWAITINT        */
>       uint64_t completion_store:1;   /* write data to address  */
>
> IIUC, if we define type:4 as uint32_t rather than uint64_t, it should
> be bits [29:32] of the struct on big endian machines, not bits
> [61:64].

Yes, you're right.

>
> Thanks,
>
> -- peterx
diff mbox

Patch

diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index cc49839..4914fe6 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -52,6 +52,9 @@  typedef struct IntelIOMMUState IntelIOMMUState;
 typedef struct VTDAddressSpace VTDAddressSpace;
 typedef struct VTDIOTLBEntry VTDIOTLBEntry;
 typedef struct VTDBus VTDBus;
+typedef union VTD_IRTE VTD_IRTE;
+typedef union VTD_IR_IOAPICEntry VTD_IR_IOAPICEntry;
+typedef union VTD_IR_MSIAddress VTD_IR_MSIAddress;
 
 /* Context-Entry */
 struct VTDContextEntry {
@@ -90,6 +93,63 @@  struct VTDIOTLBEntry {
     bool write_flags;
 };
 
+/* Interrupt Remapping Table Entry Definition */
+union VTD_IRTE {
+    struct {
+        uint8_t present:1;          /* Whether entry present/available */
+        uint8_t fault_disable:1;    /* Fault Processing Disable */
+        uint8_t dest_mode:1;        /* Destination Mode */
+        uint8_t redir_hint:1;       /* Redirection Hint */
+        uint8_t trigger_mode:1;     /* Trigger Mode */
+        uint8_t delivery_mode:3;    /* Delivery Mode */
+        uint8_t __avail:4;          /* Available spaces for software */
+        uint8_t __reserved_0:3;     /* Reserved 0 */
+        uint8_t irte_mode:1;        /* IRTE Mode */
+        uint8_t vector:8;           /* Interrupt Vector */
+        uint8_t __reserved_1:8;     /* Reserved 1 */
+        uint32_t dest_id:32;        /* Destination ID */
+        uint16_t source_id:16;      /* Source-ID */
+        uint8_t sid_q:2;            /* Source-ID Qualifier */
+        uint8_t sid_vtype:2;        /* Source-ID Validation Type */
+        uint64_t __reserved_2:44;   /* Reserved 2 */
+    } QEMU_PACKED;
+    uint64_t data[2];
+};
+
+/* Programming format for IOAPIC table entries */
+union VTD_IR_IOAPICEntry {
+    struct {
+        uint8_t vector:8;           /* Vector */
+        uint8_t __zeros:3;          /* Reserved (all zero) */
+        uint8_t index_h:1;          /* Interrupt Index bit 15 */
+        uint8_t status:1;           /* Deliver Status */
+        uint8_t polarity:1;         /* Interrupt Polarity */
+        uint8_t remote_irr:1;       /* Remote IRR */
+        uint8_t trigger_mode:1;     /* Trigger Mode */
+        uint8_t mask:1;             /* Mask */
+        uint32_t __reserved:31;     /* Reserved (should all zero) */
+        uint8_t int_mode:1;         /* Interrupt Format */
+        uint16_t index_l:15;        /* Interrupt Index bits 14-0 */
+    } QEMU_PACKED;
+    uint64_t data;
+};
+
+/* Programming format for MSI/MSI-X addresses */
+union VTD_IR_MSIAddress {
+    struct {
+        uint8_t __not_care:2;
+        uint8_t index_h:1;          /* Interrupt index bit 15 */
+        uint8_t sub_valid:1;        /* SHV: Sub-Handle Valid bit */
+        uint8_t int_mode:1;         /* Interrupt format */
+        uint16_t index_l:15;        /* Interrupt index bit 14-0 */
+        uint16_t __head:12;         /* Should always be: 0x0fee */
+    } QEMU_PACKED;
+    uint32_t data;
+};
+
+/* When IR is enabled, all MSI/MSI-X data bits should be zero */
+#define VTD_IR_MSI_DATA          (0)
+
 /* The iommu (DMAR) device state struct */
 struct IntelIOMMUState {
     SysBusDevice busdev;