static int vtd_iova_to_slpte(VTDContextEntry *ce, uint64_t iova, bool is_write,

                             uint64_t *slptep, uint32_t *slpte_level,

                             bool *reads, bool *writes)

{

    dma_addr_t addr = vtd_get_slpt_base_from_context(ce);

    uint32_t level = vtd_get_level_from_context_entry(ce);

    uint32_t offset;

    uint64_t slpte;

    uint32_t ce_agaw = vtd_get_agaw_from_context_entry(ce);

    uint64_t access_right_check;



    /* Check if @iova is above 2^X-1, where X is the minimum of MGAW

     * in CAP_REG and AW in context-entry.

     */

    if (iova & ~((1ULL << MIN(ce_agaw, VTD_MGAW)) - 1)) {

        VTD_DPRINTF(GENERAL, "error: iova 0x%"PRIx64 " exceeds limits", iova);

        return -VTD_FR_ADDR_BEYOND_MGAW;

    }



    /* FIXME: what is the Atomics request here? */

    access_right_check = is_write ? VTD_SL_W : VTD_SL_R;



    while (true) {

        offset = vtd_iova_level_offset(iova, level);

        slpte = vtd_get_slpte(addr, offset);



        if (slpte == (uint64_t)-1) {

            VTD_DPRINTF(GENERAL, "error: fail to access second-level paging "

                        "entry at level %"PRIu32 " for iova 0x%"PRIx64,

                        level, iova);

            if (level == vtd_get_level_from_context_entry(ce)) {

                /* Invalid programming of context-entry */

                return -VTD_FR_CONTEXT_ENTRY_INV;

            } else {

                return -VTD_FR_PAGING_ENTRY_INV;

            }

        }

        *reads = (*reads) && (slpte & VTD_SL_R);

        *writes = (*writes) && (slpte & VTD_SL_W);

        if (!(slpte & access_right_check)) {

            VTD_DPRINTF(GENERAL, "error: lack of %s permission for "

                        "iova 0x%"PRIx64 " slpte 0x%"PRIx64,

                        (is_write ? "write" : "read"), iova, slpte);

            return is_write ? -VTD_FR_WRITE : -VTD_FR_READ;

        }

        if (vtd_slpte_nonzero_rsvd(slpte, level)) {

            VTD_DPRINTF(GENERAL, "error: non-zero reserved field in second "

                        "level paging entry level %"PRIu32 " slpte 0x%"PRIx64,

                        level, slpte);

            return -VTD_FR_PAGING_ENTRY_RSVD;

        }



        if (vtd_is_last_slpte(slpte, level)) {

            *slptep = slpte;

            *slpte_level = level;

            return 0;

        }

        addr = vtd_get_slpte_addr(slpte);

        level--;

    }

}

static int vtd_iova_to_slpte(VTDContextEntry *ce, uint64_t iova, bool is_write,

                             uint64_t *slptep, uint32_t *slpte_level,

                             bool *reads, bool *writes)

{

    dma_addr_t addr = vtd_get_slpt_base_from_context(ce);

    uint32_t level = vtd_get_level_from_context_entry(ce);

    uint32_t offset;

    uint64_t slpte;

    uint32_t ce_agaw = vtd_get_agaw_from_context_entry(ce);

    uint64_t access_right_check;



    





    if (iova & ~((1ULL << MIN(ce_agaw, VTD_MGAW)) - 1)) {

        VTD_DPRINTF(GENERAL, "error: iova 0x%"PRIx64 " exceeds limits", iova);

        return -VTD_FR_ADDR_BEYOND_MGAW;

    }



    

    access_right_check = is_write ? VTD_SL_W : VTD_SL_R;



    while (true) {

        offset = vtd_iova_level_offset(iova, level);

        slpte = vtd_get_slpte(addr, offset);



        if (slpte == (uint64_t)-1) {

            VTD_DPRINTF(GENERAL, "error: fail to access second-level paging "

                        "entry at level %"PRIu32 " for iova 0x%"PRIx64,

                        level, iova);

            if (level == vtd_get_level_from_context_entry(ce)) {

                

                return -VTD_FR_CONTEXT_ENTRY_INV;

            } else {

                return -VTD_FR_PAGING_ENTRY_INV;

            }

        }

        *reads = (*reads) && (slpte & VTD_SL_R);

        *writes = (*writes) && (slpte & VTD_SL_W);

        if (!(slpte & access_right_check)) {

            VTD_DPRINTF(GENERAL, "error: lack of %s permission for "

                        "iova 0x%"PRIx64 " slpte 0x%"PRIx64,

                        (is_write ? "write" : "read"), iova, slpte);

            return is_write ? -VTD_FR_WRITE : -VTD_FR_READ;

        }

        if (vtd_slpte_nonzero_rsvd(slpte, level)) {

            VTD_DPRINTF(GENERAL, "error: non-zero reserved field in second "

                        "level paging entry level %"PRIu32 " slpte 0x%"PRIx64,

                        level, slpte);

            return -VTD_FR_PAGING_ENTRY_RSVD;

        }



        if (vtd_is_last_slpte(slpte, level)) {

            *slptep = slpte;

            *slpte_level = level;

            return 0;

        }

        addr = vtd_get_slpte_addr(slpte);

        level--;

    }

}

static int FUNC_0(VTDContextEntry *VAR_0, uint64_t VAR_1, bool VAR_2,

                             uint64_t *VAR_3, uint32_t *VAR_4,

                             bool *VAR_5, bool *VAR_6)

{

    dma_addr_t addr = vtd_get_slpt_base_from_context(VAR_0);

    uint32_t level = vtd_get_level_from_context_entry(VAR_0);

    uint32_t offset;

    uint64_t slpte;

    uint32_t ce_agaw = vtd_get_agaw_from_context_entry(VAR_0);

    uint64_t access_right_check;



    





    if (VAR_1 & ~((1ULL << MIN(ce_agaw, VTD_MGAW)) - 1)) {

        VTD_DPRINTF(GENERAL, "error: VAR_1 0x%"PRIx64 " exceeds limits", VAR_1);

        return -VTD_FR_ADDR_BEYOND_MGAW;

    }



    

    access_right_check = VAR_2 ? VTD_SL_W : VTD_SL_R;



    while (true) {

        offset = vtd_iova_level_offset(VAR_1, level);

        slpte = vtd_get_slpte(addr, offset);



        if (slpte == (uint64_t)-1) {

            VTD_DPRINTF(GENERAL, "error: fail to access second-level paging "

                        "entry at level %"PRIu32 " for VAR_1 0x%"PRIx64,

                        level, VAR_1);

            if (level == vtd_get_level_from_context_entry(VAR_0)) {

                

                return -VTD_FR_CONTEXT_ENTRY_INV;

            } else {

                return -VTD_FR_PAGING_ENTRY_INV;

            }

        }

        *VAR_5 = (*VAR_5) && (slpte & VTD_SL_R);

        *VAR_6 = (*VAR_6) && (slpte & VTD_SL_W);

        if (!(slpte & access_right_check)) {

            VTD_DPRINTF(GENERAL, "error: lack of %s permission for "

                        "VAR_1 0x%"PRIx64 " slpte 0x%"PRIx64,

                        (VAR_2 ? "write" : "read"), VAR_1, slpte);

            return VAR_2 ? -VTD_FR_WRITE : -VTD_FR_READ;

        }

        if (vtd_slpte_nonzero_rsvd(slpte, level)) {

            VTD_DPRINTF(GENERAL, "error: non-zero reserved field in second "

                        "level paging entry level %"PRIu32 " slpte 0x%"PRIx64,

                        level, slpte);

            return -VTD_FR_PAGING_ENTRY_RSVD;

        }



        if (vtd_is_last_slpte(slpte, level)) {

            *VAR_3 = slpte;

            *VAR_4 = level;

            return 0;

        }

        addr = vtd_get_slpte_addr(slpte);

        level--;

    }

}

static int FUNC_0(VTDContextEntry *VAR_0, uint64_t VAR_1, bool VAR_2,
uint64_t *VAR_3, uint32_t *VAR_4,
bool *VAR_5, bool *VAR_6)
{ dma_addr_t addr = vtd_get_slpt_base_from_context(VAR_0); uint32_t level = vtd_get_level_from_context_entry(VAR_0); uint32_t offset; uint64_t slpte; uint32_t ce_agaw = vtd_get_agaw_from_context_entry(VAR_0); uint64_t access_right_check; if (VAR_1 & ~((1ULL << MIN(ce_agaw, VTD_MGAW)) - 1)) { VTD_DPRINTF(GENERAL, "error: VAR_1 0x%"PRIx64 " exceeds limits", VAR_1); return -VTD_FR_ADDR_BEYOND_MGAW; } access_right_check = VAR_2 ? VTD_SL_W : VTD_SL_R; while (true) { offset = vtd_iova_level_offset(VAR_1, level); slpte = vtd_get_slpte(addr, offset); if (slpte == (uint64_t)-1) { VTD_DPRINTF(GENERAL, "error: fail to access second-level paging "
"entry at level %"PRIu32 " for VAR_1 0x%"PRIx64,
level, VAR_1); if (level == vtd_get_level_from_context_entry(VAR_0)) { return -VTD_FR_CONTEXT_ENTRY_INV; } else { return -VTD_FR_PAGING_ENTRY_INV; } } *VAR_5 = (*VAR_5) && (slpte & VTD_SL_R); *VAR_6 = (*VAR_6) && (slpte & VTD_SL_W); if (!(slpte & access_right_check)) { VTD_DPRINTF(GENERAL, "error: lack of %s permission for "
"VAR_1 0x%"PRIx64 " slpte 0x%"PRIx64,
(VAR_2 ? "write" : "read"), VAR_1, slpte); return VAR_2 ? -VTD_FR_WRITE : -VTD_FR_READ; } if (vtd_slpte_nonzero_rsvd(slpte, level)) { VTD_DPRINTF(GENERAL, "error: non-zero reserved field in second "
"level paging entry level %"PRIu32 " slpte 0x%"PRIx64,
level, slpte); return -VTD_FR_PAGING_ENTRY_RSVD; } if (vtd_is_last_slpte(slpte, level)) { *VAR_3 = slpte; *VAR_4 = level; return 0; } addr = vtd_get_slpte_addr(slpte); level--; } }