static int vtd_interrupt_remap_msi(IntelIOMMUState *iommu,

                                   MSIMessage *origin,

                                   MSIMessage *translated)

{

    int ret = 0;

    VTD_IR_MSIAddress addr;

    uint16_t index;

    VTDIrq irq = {};



    assert(origin && translated);



    if (!iommu || !iommu->intr_enabled) {

        goto do_not_translate;

    }



    if (origin->address & VTD_MSI_ADDR_HI_MASK) {

        VTD_DPRINTF(GENERAL, "error: MSI addr high 32 bits nonzero"

                    " during interrupt remapping: 0x%"PRIx32,

                    (uint32_t)((origin->address & VTD_MSI_ADDR_HI_MASK) >> \

                    VTD_MSI_ADDR_HI_SHIFT));

        return -VTD_FR_IR_REQ_RSVD;

    }



    addr.data = origin->address & VTD_MSI_ADDR_LO_MASK;

    if (le16_to_cpu(addr.__head) != 0xfee) {

        VTD_DPRINTF(GENERAL, "error: MSI addr low 32 bits invalid: "

                    "0x%"PRIx32, addr.data);

        return -VTD_FR_IR_REQ_RSVD;

    }



    /* This is compatible mode. */

    if (addr.int_mode != VTD_IR_INT_FORMAT_REMAP) {

        goto do_not_translate;

    }



    index = addr.index_h << 15 | le16_to_cpu(addr.index_l);



#define  VTD_IR_MSI_DATA_SUBHANDLE       (0x0000ffff)

#define  VTD_IR_MSI_DATA_RESERVED        (0xffff0000)



    if (addr.sub_valid) {

        /* See VT-d spec 5.1.2.2 and 5.1.3 on subhandle */

        index += origin->data & VTD_IR_MSI_DATA_SUBHANDLE;

    }



    ret = vtd_remap_irq_get(iommu, index, &irq);

    if (ret) {

        return ret;

    }



    if (addr.sub_valid) {

        VTD_DPRINTF(IR, "received MSI interrupt");

        if (origin->data & VTD_IR_MSI_DATA_RESERVED) {

            VTD_DPRINTF(GENERAL, "error: MSI data bits non-zero for "

                        "interrupt remappable entry: 0x%"PRIx32,

                        origin->data);

            return -VTD_FR_IR_REQ_RSVD;

        }

    } else {

        uint8_t vector = origin->data & 0xff;

        VTD_DPRINTF(IR, "received IOAPIC interrupt");

        /* IOAPIC entry vector should be aligned with IRTE vector

         * (see vt-d spec 5.1.5.1). */

        if (vector != irq.vector) {

            VTD_DPRINTF(GENERAL, "IOAPIC vector inconsistent: "

                        "entry: %d, IRTE: %d, index: %d",

                        vector, irq.vector, index);

        }

    }



    /*

     * We'd better keep the last two bits, assuming that guest OS

     * might modify it. Keep it does not hurt after all.

     */

    irq.msi_addr_last_bits = addr.__not_care;



    /* Translate VTDIrq to MSI message */

    vtd_generate_msi_message(&irq, translated);



    VTD_DPRINTF(IR, "mapping MSI 0x%"PRIx64":0x%"PRIx32 " -> "

                "0x%"PRIx64":0x%"PRIx32, origin->address, origin->data,

                translated->address, translated->data);

    return 0;



do_not_translate:

    memcpy(translated, origin, sizeof(*origin));

    return 0;

}

static int vtd_interrupt_remap_msi(IntelIOMMUState *iommu,

                                   MSIMessage *origin,

                                   MSIMessage *translated)

{

    int ret = 0;

    VTD_IR_MSIAddress addr;

    uint16_t index;

    VTDIrq irq = {};



    assert(origin && translated);



    if (!iommu || !iommu->intr_enabled) {

        goto do_not_translate;

    }



    if (origin->address & VTD_MSI_ADDR_HI_MASK) {

        VTD_DPRINTF(GENERAL, "error: MSI addr high 32 bits nonzero"

                    " during interrupt remapping: 0x%"PRIx32,

                    (uint32_t)((origin->address & VTD_MSI_ADDR_HI_MASK) >> \

                    VTD_MSI_ADDR_HI_SHIFT));

        return -VTD_FR_IR_REQ_RSVD;

    }



    addr.data = origin->address & VTD_MSI_ADDR_LO_MASK;

    if (le16_to_cpu(addr.__head) != 0xfee) {

        VTD_DPRINTF(GENERAL, "error: MSI addr low 32 bits invalid: "

                    "0x%"PRIx32, addr.data);

        return -VTD_FR_IR_REQ_RSVD;

    }



    

    if (addr.int_mode != VTD_IR_INT_FORMAT_REMAP) {

        goto do_not_translate;

    }



    index = addr.index_h << 15 | le16_to_cpu(addr.index_l);



#define  VTD_IR_MSI_DATA_SUBHANDLE       (0x0000ffff)

#define  VTD_IR_MSI_DATA_RESERVED        (0xffff0000)



    if (addr.sub_valid) {

        

        index += origin->data & VTD_IR_MSI_DATA_SUBHANDLE;

    }



    ret = vtd_remap_irq_get(iommu, index, &irq);

    if (ret) {

        return ret;

    }



    if (addr.sub_valid) {

        VTD_DPRINTF(IR, "received MSI interrupt");

        if (origin->data & VTD_IR_MSI_DATA_RESERVED) {

            VTD_DPRINTF(GENERAL, "error: MSI data bits non-zero for "

                        "interrupt remappable entry: 0x%"PRIx32,

                        origin->data);

            return -VTD_FR_IR_REQ_RSVD;

        }

    } else {

        uint8_t vector = origin->data & 0xff;

        VTD_DPRINTF(IR, "received IOAPIC interrupt");

        



        if (vector != irq.vector) {

            VTD_DPRINTF(GENERAL, "IOAPIC vector inconsistent: "

                        "entry: %d, IRTE: %d, index: %d",

                        vector, irq.vector, index);

        }

    }



    







    irq.msi_addr_last_bits = addr.__not_care;



    

    vtd_generate_msi_message(&irq, translated);



    VTD_DPRINTF(IR, "mapping MSI 0x%"PRIx64":0x%"PRIx32 " -> "

                "0x%"PRIx64":0x%"PRIx32, origin->address, origin->data,

                translated->address, translated->data);

    return 0;



do_not_translate:

    memcpy(translated, origin, sizeof(*origin));

    return 0;

}

static int FUNC_0(IntelIOMMUState *VAR_0,

                                   MSIMessage *VAR_1,

                                   MSIMessage *VAR_2)

{

    int VAR_3 = 0;

    VTD_IR_MSIAddress addr;

    uint16_t index;

    VTDIrq irq = {};



    assert(VAR_1 && VAR_2);



    if (!VAR_0 || !VAR_0->intr_enabled) {

        goto do_not_translate;

    }



    if (VAR_1->address & VTD_MSI_ADDR_HI_MASK) {

        VTD_DPRINTF(GENERAL, "error: MSI addr high 32 bits nonzero"

                    " during interrupt remapping: 0x%"PRIx32,

                    (uint32_t)((VAR_1->address & VTD_MSI_ADDR_HI_MASK) >> \

                    VTD_MSI_ADDR_HI_SHIFT));

        return -VTD_FR_IR_REQ_RSVD;

    }



    addr.data = VAR_1->address & VTD_MSI_ADDR_LO_MASK;

    if (le16_to_cpu(addr.__head) != 0xfee) {

        VTD_DPRINTF(GENERAL, "error: MSI addr low 32 bits invalid: "

                    "0x%"PRIx32, addr.data);

        return -VTD_FR_IR_REQ_RSVD;

    }



    

    if (addr.int_mode != VTD_IR_INT_FORMAT_REMAP) {

        goto do_not_translate;

    }



    index = addr.index_h << 15 | le16_to_cpu(addr.index_l);



#define  VTD_IR_MSI_DATA_SUBHANDLE       (0x0000ffff)

#define  VTD_IR_MSI_DATA_RESERVED        (0xffff0000)



    if (addr.sub_valid) {

        

        index += VAR_1->data & VTD_IR_MSI_DATA_SUBHANDLE;

    }



    VAR_3 = vtd_remap_irq_get(VAR_0, index, &irq);

    if (VAR_3) {

        return VAR_3;

    }



    if (addr.sub_valid) {

        VTD_DPRINTF(IR, "received MSI interrupt");

        if (VAR_1->data & VTD_IR_MSI_DATA_RESERVED) {

            VTD_DPRINTF(GENERAL, "error: MSI data bits non-zero for "

                        "interrupt remappable entry: 0x%"PRIx32,

                        VAR_1->data);

            return -VTD_FR_IR_REQ_RSVD;

        }

    } else {

        uint8_t vector = VAR_1->data & 0xff;

        VTD_DPRINTF(IR, "received IOAPIC interrupt");

        



        if (vector != irq.vector) {

            VTD_DPRINTF(GENERAL, "IOAPIC vector inconsistent: "

                        "entry: %d, IRTE: %d, index: %d",

                        vector, irq.vector, index);

        }

    }



    







    irq.msi_addr_last_bits = addr.__not_care;



    

    vtd_generate_msi_message(&irq, VAR_2);



    VTD_DPRINTF(IR, "mapping MSI 0x%"PRIx64":0x%"PRIx32 " -> "

                "0x%"PRIx64":0x%"PRIx32, VAR_1->address, VAR_1->data,

                VAR_2->address, VAR_2->data);

    return 0;



do_not_translate:

    memcpy(VAR_2, VAR_1, sizeof(*VAR_1));

    return 0;

}

static int FUNC_0(IntelIOMMUState *VAR_0,
MSIMessage *VAR_1,
MSIMessage *VAR_2)
{ int VAR_3 = 0; VTD_IR_MSIAddress addr; uint16_t index; VTDIrq irq = {}; assert(VAR_1 && VAR_2); if (!VAR_0 || !VAR_0->intr_enabled) { goto do_not_translate; } if (VAR_1->address & VTD_MSI_ADDR_HI_MASK) { VTD_DPRINTF(GENERAL, "error: MSI addr high 32 bits nonzero"
" during interrupt remapping: 0x%"PRIx32,
(uint32_t)((VAR_1->address & VTD_MSI_ADDR_HI_MASK) >> \
VTD_MSI_ADDR_HI_SHIFT)); return -VTD_FR_IR_REQ_RSVD; } addr.data = VAR_1->address & VTD_MSI_ADDR_LO_MASK; if (le16_to_cpu(addr.__head) != 0xfee) { VTD_DPRINTF(GENERAL, "error: MSI addr low 32 bits invalid: "
"0x%"PRIx32, addr.data); return -VTD_FR_IR_REQ_RSVD; } if (addr.int_mode != VTD_IR_INT_FORMAT_REMAP) { goto do_not_translate; } index = addr.index_h << 15 | le16_to_cpu(addr.index_l); #define  VTD_IR_MSI_DATA_SUBHANDLE       (0x0000ffff)
#define  VTD_IR_MSI_DATA_RESERVED        (0xffff0000)
if (addr.sub_valid) { index += VAR_1->data & VTD_IR_MSI_DATA_SUBHANDLE; } VAR_3 = vtd_remap_irq_get(VAR_0, index, &irq); if (VAR_3) { return VAR_3; } if (addr.sub_valid) { VTD_DPRINTF(IR, "received MSI interrupt"); if (VAR_1->data & VTD_IR_MSI_DATA_RESERVED) { VTD_DPRINTF(GENERAL, "error: MSI data bits non-zero for "
"interrupt remappable entry: 0x%"PRIx32,
VAR_1->data); return -VTD_FR_IR_REQ_RSVD; } } else { uint8_t vector = VAR_1->data & 0xff; VTD_DPRINTF(IR, "received IOAPIC interrupt"); if (vector != irq.vector) { VTD_DPRINTF(GENERAL, "IOAPIC vector inconsistent: "
"entry: %d, IRTE: %d, index: %d",
vector, irq.vector, index); } } irq.msi_addr_last_bits = addr.__not_care; vtd_generate_msi_message(&irq, VAR_2); VTD_DPRINTF(IR, "mapping MSI 0x%"PRIx64":0x%"PRIx32 " -> "
"0x%"PRIx64":0x%"PRIx32, VAR_1->address, VAR_1->data,
VAR_2->address, VAR_2->data); return 0; do_not_translate:
memcpy(VAR_2, VAR_1, sizeof(*VAR_1)); return 0; }