aboutsummaryrefslogtreecommitdiff
path: root/hw/arm
diff options
context:
space:
mode:
authorMostafa Saleh <smostafa@google.com>2024-07-15 08:45:02 +0000
committerPeter Maydell <peter.maydell@linaro.org>2024-07-18 13:49:29 +0100
commit48f9e9eb2914cf1ccd67bf7a011d2706490d81f0 (patch)
treebef355c877dae92f8dccb6e8db8373d39b487558 /hw/arm
parentbde809f05f66b4be4475ffa9819d82a01686d1c7 (diff)
downloadqemu-48f9e9eb2914cf1ccd67bf7a011d2706490d81f0.zip
qemu-48f9e9eb2914cf1ccd67bf7a011d2706490d81f0.tar.gz
qemu-48f9e9eb2914cf1ccd67bf7a011d2706490d81f0.tar.bz2
hw/arm/smmu: Fix IPA for stage-2 events
For the following events (ARM IHI 0070 F.b - 7.3 Event records): - F_TRANSLATION - F_ACCESS - F_PERMISSION - F_ADDR_SIZE If fault occurs at stage 2, S2 == 1 and: - If translating an IPA for a transaction (whether by input to stage 2-only configuration, or after successful stage 1 translation), CLASS == IN, and IPA is provided. At the moment only CLASS == IN is used which indicates input translation. However, this was not implemented correctly, as for stage 2, the code only sets the S2 bit but not the IPA. This field has the same bits as FetchAddr in F_WALK_EABT which is populated correctly, so we don’t change that. The setting of this field should be done from the walker as the IPA address wouldn't be known in case of nesting. For stage 1, the spec says: If fault occurs at stage 1, S2 == 0 and: CLASS == IN, IPA is UNKNOWN. So, no need to set it to for stage 1, as ptw_info is initialised by zero in smmuv3_translate(). Fixes: e703f7076a “hw/arm/smmuv3: Add page table walk for stage-2” Reviewed-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Reviewed-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Mostafa Saleh <smostafa@google.com> Message-id: 20240715084519.1189624-3-smostafa@google.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/arm')
-rw-r--r--hw/arm/smmu-common.c10
-rw-r--r--hw/arm/smmuv3.c4
2 files changed, 10 insertions, 4 deletions
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index e81b684..e8cdbcd 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -448,7 +448,7 @@ static int smmu_ptw_64_s2(SMMUTransCfg *cfg,
*/
if (ipa >= (1ULL << inputsize)) {
info->type = SMMU_PTW_ERR_TRANSLATION;
- goto error;
+ goto error_ipa;
}
while (level < VMSA_LEVELS) {
@@ -494,13 +494,13 @@ static int smmu_ptw_64_s2(SMMUTransCfg *cfg,
*/
if (!PTE_AF(pte) && !cfg->s2cfg.affd) {
info->type = SMMU_PTW_ERR_ACCESS;
- goto error;
+ goto error_ipa;
}
s2ap = PTE_AP(pte);
if (is_permission_fault_s2(s2ap, perm)) {
info->type = SMMU_PTW_ERR_PERMISSION;
- goto error;
+ goto error_ipa;
}
/*
@@ -509,7 +509,7 @@ static int smmu_ptw_64_s2(SMMUTransCfg *cfg,
*/
if (gpa >= (1ULL << cfg->s2cfg.eff_ps)) {
info->type = SMMU_PTW_ERR_ADDR_SIZE;
- goto error;
+ goto error_ipa;
}
tlbe->entry.translated_addr = gpa;
@@ -522,6 +522,8 @@ static int smmu_ptw_64_s2(SMMUTransCfg *cfg,
}
info->type = SMMU_PTW_ERR_TRANSLATION;
+error_ipa:
+ info->addr = ipa;
error:
info->stage = 2;
tlbe->entry.perm = IOMMU_NONE;
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 445e04d..cab545a 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -949,6 +949,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
if (PTW_RECORD_FAULT(cfg)) {
event.type = SMMU_EVT_F_TRANSLATION;
event.u.f_translation.addr = addr;
+ event.u.f_translation.addr2 = ptw_info.addr;
event.u.f_translation.rnw = flag & 0x1;
}
break;
@@ -956,6 +957,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
if (PTW_RECORD_FAULT(cfg)) {
event.type = SMMU_EVT_F_ADDR_SIZE;
event.u.f_addr_size.addr = addr;
+ event.u.f_addr_size.addr2 = ptw_info.addr;
event.u.f_addr_size.rnw = flag & 0x1;
}
break;
@@ -963,6 +965,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
if (PTW_RECORD_FAULT(cfg)) {
event.type = SMMU_EVT_F_ACCESS;
event.u.f_access.addr = addr;
+ event.u.f_access.addr2 = ptw_info.addr;
event.u.f_access.rnw = flag & 0x1;
}
break;
@@ -970,6 +973,7 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
if (PTW_RECORD_FAULT(cfg)) {
event.type = SMMU_EVT_F_PERMISSION;
event.u.f_permission.addr = addr;
+ event.u.f_permission.addr2 = ptw_info.addr;
event.u.f_permission.rnw = flag & 0x1;
}
break;