From nobody Sun Apr 27 08:37:06 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=linaro.org Return-Path: <qemu-devel-bounces+importer=patchew.org@nongnu.org> Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1530033590503354.08955677043605; Tue, 26 Jun 2018 10:19:50 -0700 (PDT) Received: from localhost ([::1]:54119 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from <qemu-devel-bounces+importer=patchew.org@nongnu.org>) id 1fXrd3-0001iI-Op for importer@patchew.org; Tue, 26 Jun 2018 13:19:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52058) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from <pm215@archaic.org.uk>) id 1fXrHO-0002Ew-33 for qemu-devel@nongnu.org; Tue, 26 Jun 2018 12:57:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from <pm215@archaic.org.uk>) id 1fXrHM-0007JW-H8 for qemu-devel@nongnu.org; Tue, 26 Jun 2018 12:57:22 -0400 Received: from orth.archaic.org.uk ([2001:8b0:1d0::2]:43046) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from <pm215@archaic.org.uk>) id 1fXrHM-0007IZ-79 for qemu-devel@nongnu.org; Tue, 26 Jun 2018 12:57:20 -0400 Received: from pm215 by orth.archaic.org.uk with local (Exim 4.89) (envelope-from <pm215@archaic.org.uk>) id 1fXrHK-0000CT-U2 for qemu-devel@nongnu.org; Tue, 26 Jun 2018 17:57:18 +0100 From: Peter Maydell <peter.maydell@linaro.org> To: qemu-devel@nongnu.org Date: Tue, 26 Jun 2018 17:56:52 +0100 Message-Id: <20180626165658.31394-27-peter.maydell@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180626165658.31394-1-peter.maydell@linaro.org> References: <20180626165658.31394-1-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2001:8b0:1d0::2 Subject: [Qemu-devel] [PULL 26/32] hw/arm/smmuv3: Fix translate error handling X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: <qemu-devel.nongnu.org> List-Unsubscribe: <https://lists.nongnu.org/mailman/options/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe> List-Archive: <http://lists.nongnu.org/archive/html/qemu-devel/> List-Post: <mailto:qemu-devel@nongnu.org> List-Help: <mailto:qemu-devel-request@nongnu.org?subject=help> List-Subscribe: <https://lists.nongnu.org/mailman/listinfo/qemu-devel>, <mailto:qemu-devel-request@nongnu.org?subject=subscribe> Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" <qemu-devel-bounces+importer=patchew.org@nongnu.org> X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Jia He <hejianet@gmail.com> In case the STE's config is "Bypass" we currently don't set the IOMMUTLBEntry perm flags and the access does not succeed. Also if the config is 0b0xx (Aborted/Reserved), decode_ste and smmuv3_decode_config currently returns -EINVAL and we don't enter the expected code path: we record an event whereas we should not. This patch fixes those bugs and simplifies the error handling. decode_ste and smmuv3_decode_config now return 0 if aborted or bypassed config was found. Only bad config info produces negative error values. In smmuv3_translate we more clearly differentiate errors, bypass/smmu disabled, aborted and success cases. Also trace points are differentiated. Fixes: 9bde7f0674fe ("hw/arm/smmuv3: Implement translate callback") Reported-by: jia.he@hxt-semitech.com Signed-off-by: jia.he@hxt-semitech.com Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1529653501-15358-2-git-send-email-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/arm/smmuv3-internal.h | 12 ++++- hw/arm/smmuv3.c | 96 +++++++++++++++++++++++++++------------- hw/arm/trace-events | 7 +-- 3 files changed, 80 insertions(+), 35 deletions(-) diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h index a9d714b56e6..bab25d640eb 100644 --- a/hw/arm/smmuv3-internal.h +++ b/hw/arm/smmuv3-internal.h @@ -23,6 +23,14 @@ =20 #include "hw/arm/smmu-common.h" =20 +typedef enum SMMUTranslationStatus { + SMMU_TRANS_DISABLE, + SMMU_TRANS_ABORT, + SMMU_TRANS_BYPASS, + SMMU_TRANS_ERROR, + SMMU_TRANS_SUCCESS, +} SMMUTranslationStatus; + /* MMIO Registers */ =20 REG32(IDR0, 0x0) @@ -315,7 +323,7 @@ enum { /* Command completion notification */ /* Events */ =20 typedef enum SMMUEventType { - SMMU_EVT_OK =3D 0x00, + SMMU_EVT_NONE =3D 0x00, SMMU_EVT_F_UUT , SMMU_EVT_C_BAD_STREAMID , SMMU_EVT_F_STE_FETCH , @@ -337,7 +345,7 @@ typedef enum SMMUEventType { } SMMUEventType; =20 static const char *event_stringify[] =3D { - [SMMU_EVT_OK] =3D "SMMU_EVT_OK", + [SMMU_EVT_NONE] =3D "no recorded event", [SMMU_EVT_F_UUT] =3D "SMMU_EVT_F_UUT", [SMMU_EVT_C_BAD_STREAMID] =3D "SMMU_EVT_C_BAD_STREAMID", [SMMU_EVT_F_STE_FETCH] =3D "SMMU_EVT_F_STE_FETCH", diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c index 978330900d5..70b8f295aa9 100644 --- a/hw/arm/smmuv3.c +++ b/hw/arm/smmuv3.c @@ -23,6 +23,7 @@ #include "hw/qdev-core.h" #include "hw/pci/pci.h" #include "exec/address-spaces.h" +#include "cpu.h" #include "trace.h" #include "qemu/log.h" #include "qemu/error-report.h" @@ -154,7 +155,7 @@ void smmuv3_record_event(SMMUv3State *s, SMMUEventInfo = *info) EVT_SET_SID(&evt, info->sid); =20 switch (info->type) { - case SMMU_EVT_OK: + case SMMU_EVT_NONE: return; case SMMU_EVT_F_UUT: EVT_SET_SSID(&evt, info->u.f_uut.ssid); @@ -312,12 +313,11 @@ static int smmu_get_cd(SMMUv3State *s, STE *ste, uint= 32_t ssid, return 0; } =20 -/* Returns <0 if the caller has no need to continue the translation */ +/* Returns < 0 in case of invalid STE, 0 otherwise */ static int decode_ste(SMMUv3State *s, SMMUTransCfg *cfg, STE *ste, SMMUEventInfo *event) { uint32_t config; - int ret =3D -EINVAL; =20 if (!STE_VALID(ste)) { goto bad_ste; @@ -326,13 +326,13 @@ static int decode_ste(SMMUv3State *s, SMMUTransCfg *c= fg, config =3D STE_CONFIG(ste); =20 if (STE_CFG_ABORT(config)) { - cfg->aborted =3D true; /* abort but don't record any event */ - return ret; + cfg->aborted =3D true; + return 0; } =20 if (STE_CFG_BYPASS(config)) { cfg->bypassed =3D true; - return ret; + return 0; } =20 if (STE_CFG_S2_ENABLED(config)) { @@ -509,7 +509,7 @@ bad_cd: * the different configuration decoding steps * @event: must be zero'ed by the caller * - * return < 0 if the translation needs to be aborted (@event is filled + * return < 0 in case of config decoding error (@event is filled * accordingly). Return 0 otherwise. */ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg, @@ -518,19 +518,26 @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr= , SMMUTransCfg *cfg, SMMUDevice *sdev =3D container_of(mr, SMMUDevice, iommu); uint32_t sid =3D smmu_get_sid(sdev); SMMUv3State *s =3D sdev->smmu; - int ret =3D -EINVAL; + int ret; STE ste; CD cd; =20 - if (smmu_find_ste(s, sid, &ste, event)) { + ret =3D smmu_find_ste(s, sid, &ste, event); + if (ret) { return ret; } =20 - if (decode_ste(s, cfg, &ste, event)) { + ret =3D decode_ste(s, cfg, &ste, event); + if (ret) { return ret; } =20 - if (smmu_get_cd(s, &ste, 0 /* ssid */, &cd, event)) { + if (cfg->aborted || cfg->bypassed) { + return 0; + } + + ret =3D smmu_get_cd(s, &ste, 0 /* ssid */, &cd, event); + if (ret) { return ret; } =20 @@ -543,8 +550,9 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion= *mr, hwaddr addr, SMMUDevice *sdev =3D container_of(mr, SMMUDevice, iommu); SMMUv3State *s =3D sdev->smmu; uint32_t sid =3D smmu_get_sid(sdev); - SMMUEventInfo event =3D {.type =3D SMMU_EVT_OK, .sid =3D sid}; + SMMUEventInfo event =3D {.type =3D SMMU_EVT_NONE, .sid =3D sid}; SMMUPTWEventInfo ptw_info =3D {}; + SMMUTranslationStatus status; SMMUTransCfg cfg =3D {}; IOMMUTLBEntry entry =3D { .target_as =3D &address_space_memory, @@ -553,23 +561,28 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegi= on *mr, hwaddr addr, .addr_mask =3D ~(hwaddr)0, .perm =3D IOMMU_NONE, }; - int ret =3D 0; =20 if (!smmu_enabled(s)) { - goto out; + status =3D SMMU_TRANS_DISABLE; + goto epilogue; } =20 - ret =3D smmuv3_decode_config(mr, &cfg, &event); - if (ret) { - goto out; + if (smmuv3_decode_config(mr, &cfg, &event)) { + status =3D SMMU_TRANS_ERROR; + goto epilogue; } =20 if (cfg.aborted) { - goto out; + status =3D SMMU_TRANS_ABORT; + goto epilogue; } =20 - ret =3D smmu_ptw(&cfg, addr, flag, &entry, &ptw_info); - if (ret) { + if (cfg.bypassed) { + status =3D SMMU_TRANS_BYPASS; + goto epilogue; + } + + if (smmu_ptw(&cfg, addr, flag, &entry, &ptw_info)) { switch (ptw_info.type) { case SMMU_PTW_ERR_WALK_EABT: event.type =3D SMMU_EVT_F_WALK_EABT; @@ -609,18 +622,41 @@ static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegi= on *mr, hwaddr addr, default: g_assert_not_reached(); } + status =3D SMMU_TRANS_ERROR; + } else { + status =3D SMMU_TRANS_SUCCESS; } -out: - if (ret) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s translation failed for iova=3D0x%"PRIx64"(%d)\n", - mr->parent_obj.name, addr, ret); - entry.perm =3D IOMMU_NONE; - smmuv3_record_event(s, &event); - } else if (!cfg.aborted) { + +epilogue: + switch (status) { + case SMMU_TRANS_SUCCESS: entry.perm =3D flag; - trace_smmuv3_translate(mr->parent_obj.name, sid, addr, - entry.translated_addr, entry.perm); + trace_smmuv3_translate_success(mr->parent_obj.name, sid, addr, + entry.translated_addr, entry.perm); + break; + case SMMU_TRANS_DISABLE: + entry.perm =3D flag; + entry.addr_mask =3D ~TARGET_PAGE_MASK; + trace_smmuv3_translate_disable(mr->parent_obj.name, sid, addr, + entry.perm); + break; + case SMMU_TRANS_BYPASS: + entry.perm =3D flag; + entry.addr_mask =3D ~TARGET_PAGE_MASK; + trace_smmuv3_translate_bypass(mr->parent_obj.name, sid, addr, + entry.perm); + break; + case SMMU_TRANS_ABORT: + /* no event is recorded on abort */ + trace_smmuv3_translate_abort(mr->parent_obj.name, sid, addr, + entry.perm); + break; + case SMMU_TRANS_ERROR: + qemu_log_mask(LOG_GUEST_ERROR, + "%s translation failed for iova=3D0x%"PRIx64"(%s)\n", + mr->parent_obj.name, addr, smmu_event_string(event.t= ype)); + smmuv3_record_event(s, &event); + break; } =20 return entry; diff --git a/hw/arm/trace-events b/hw/arm/trace-events index 2d927276021..0ab66bb4a86 100644 --- a/hw/arm/trace-events +++ b/hw/arm/trace-events @@ -33,9 +33,10 @@ smmuv3_record_event(const char *type, uint32_t sid) "%s = sid=3D%d" smmuv3_find_ste(uint16_t sid, uint32_t features, uint16_t sid_split) "SID:= 0x%x features:0x%x, sid_split:0x%x" smmuv3_find_ste_2lvl(uint64_t strtab_base, uint64_t l1ptr, int l1_ste_offs= et, uint64_t l2ptr, int l2_ste_offset, int max_l2_ste) "strtab_base:0x%"PRI= x64" l1ptr:0x%"PRIx64" l1_off:0x%x, l2ptr:0x%"PRIx64" l2_off:0x%x max_l2_st= e:%d" smmuv3_get_ste(uint64_t addr) "STE addr: 0x%"PRIx64 -smmuv3_translate_bypass(const char *n, uint16_t sid, uint64_t addr, bool i= s_write) "%s sid=3D%d bypass iova:0x%"PRIx64" is_write=3D%d" -smmuv3_translate_in(uint16_t sid, int pci_bus_num, uint64_t strtab_base) "= SID:0x%x bus:%d strtab_base:0x%"PRIx64 +smmuv3_translate_disable(const char *n, uint16_t sid, uint64_t addr, bool = is_write) "%s sid=3D%d bypass (smmu disabled) iova:0x%"PRIx64" is_write=3D%= d" +smmuv3_translate_bypass(const char *n, uint16_t sid, uint64_t addr, bool i= s_write) "%s sid=3D%d STE bypass iova:0x%"PRIx64" is_write=3D%d" +smmuv3_translate_abort(const char *n, uint16_t sid, uint64_t addr, bool is= _write) "%s sid=3D%d abort on iova:0x%"PRIx64" is_write=3D%d" +smmuv3_translate_success(const char *n, uint16_t sid, uint64_t iova, uint6= 4_t translated, int perm) "%s sid=3D%d iova=3D0x%"PRIx64" translated=3D0x%"= PRIx64" perm=3D0x%x" smmuv3_get_cd(uint64_t addr) "CD addr: 0x%"PRIx64 -smmuv3_translate(const char *n, uint16_t sid, uint64_t iova, uint64_t tran= slated, int perm) "%s sid=3D%d iova=3D0x%"PRIx64" translated=3D0x%"PRIx64" = perm=3D0x%x" smmuv3_decode_cd(uint32_t oas) "oas=3D%d" smmuv3_decode_cd_tt(int i, uint32_t tsz, uint64_t ttb, uint32_t granule_sz= ) "TT[%d]:tsz:%d ttb:0x%"PRIx64" granule_sz:%d" --=20 2.17.1