diff options
-rw-r--r-- | hw/arm/smmu-common.c | 48 |
1 files changed, 17 insertions, 31 deletions
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c index e13a5f4a7c..a3f9e47398 100644 --- a/hw/arm/smmu-common.c +++ b/hw/arm/smmu-common.c @@ -186,7 +186,7 @@ static int smmu_ptw_64(SMMUTransCfg *cfg, uint64_t subpage_size = 1ULL << level_shift(level, granule_sz); uint64_t mask = subpage_size - 1; uint32_t offset = iova_level_offset(iova, inputsize, level, granule_sz); - uint64_t pte; + uint64_t pte, gpa; dma_addr_t pte_addr = baseaddr + offset * sizeof(pte); uint8_t ap; @@ -199,56 +199,42 @@ static int smmu_ptw_64(SMMUTransCfg *cfg, if (is_invalid_pte(pte) || is_reserved_pte(pte, level)) { trace_smmu_ptw_invalid_pte(stage, level, baseaddr, pte_addr, offset, pte); - info->type = SMMU_PTW_ERR_TRANSLATION; - goto error; + break; } - if (is_page_pte(pte, level)) { - uint64_t gpa = get_page_pte_address(pte, granule_sz); + if (is_table_pte(pte, level)) { + ap = PTE_APTABLE(pte); - ap = PTE_AP(pte); if (is_permission_fault(ap, perm)) { info->type = SMMU_PTW_ERR_PERMISSION; goto error; } - - tlbe->translated_addr = gpa + (iova & mask); - tlbe->perm = PTE_AP_TO_PERM(ap); + baseaddr = get_table_pte_address(pte, granule_sz); + level++; + continue; + } else if (is_page_pte(pte, level)) { + gpa = get_page_pte_address(pte, granule_sz); trace_smmu_ptw_page_pte(stage, level, iova, baseaddr, pte_addr, pte, gpa); - return 0; - } - if (is_block_pte(pte, level)) { + } else { uint64_t block_size; - hwaddr gpa = get_block_pte_address(pte, level, granule_sz, - &block_size); - - ap = PTE_AP(pte); - if (is_permission_fault(ap, perm)) { - info->type = SMMU_PTW_ERR_PERMISSION; - goto error; - } + gpa = get_block_pte_address(pte, level, granule_sz, + &block_size); trace_smmu_ptw_block_pte(stage, level, baseaddr, pte_addr, pte, iova, gpa, block_size >> 20); - - tlbe->translated_addr = gpa + (iova & mask); - tlbe->perm = PTE_AP_TO_PERM(ap); - return 0; } - - /* table pte */ - ap = PTE_APTABLE(pte); - + ap = PTE_AP(pte); if (is_permission_fault(ap, perm)) { info->type = SMMU_PTW_ERR_PERMISSION; goto error; } - baseaddr = get_table_pte_address(pte, granule_sz); - level++; - } + tlbe->translated_addr = gpa + (iova & mask); + tlbe->perm = PTE_AP_TO_PERM(ap); + return 0; + } info->type = SMMU_PTW_ERR_TRANSLATION; error: |