From: Giacomo Travaglini Date: Mon, 22 Jul 2019 15:08:26 +0000 (+0100) Subject: dev-arm: SMMUv3 Table walks using TnSZ X-Git-Tag: v19.0.0.0~719 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e71e2d6a35233250ad05b358c27cad5a05609d55;p=gem5.git dev-arm: SMMUv3 Table walks using TnSZ TnSZ is needed when selecting the starting level of a table walk, since it directly affects the number of IA bits. This has been implemented by adding T0SZ and S2T0SZ to the translation context. T1SZ is not used at the moment since the current model doesn't support TTB1. Change-Id: I75663475c4dc01e5986cd93f8deafcdf7b1ece82 Signed-off-by: Giacomo Travaglini Reviewed-by: Michiel Van Tol Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/19630 Reviewed-by: Andreas Sandberg Maintainer: Andreas Sandberg Tested-by: kokoro --- diff --git a/src/dev/arm/smmu_v3_ptops.cc b/src/dev/arm/smmu_v3_ptops.cc index c57c16a3a..96d876ea3 100644 --- a/src/dev/arm/smmu_v3_ptops.cc +++ b/src/dev/arm/smmu_v3_ptops.cc @@ -122,7 +122,7 @@ V7LPageTableOps::walkMask(unsigned level) const } unsigned -V7LPageTableOps::firstLevel() const +V7LPageTableOps::firstLevel(uint8_t tsz) const { return 1; } @@ -216,9 +216,13 @@ V8PageTableOps4k::walkMask(unsigned level) const } unsigned -V8PageTableOps4k::firstLevel() const +V8PageTableOps4k::firstLevel(uint8_t tsz) const { - return 0; + if (tsz >= 16 && tsz <= 24) return 0; + if (tsz >= 25 && tsz <= 33) return 1; + if (tsz >= 34 && tsz <= 39) return 2; + + panic("Unsupported TnSZ: %d\n", tsz); } unsigned @@ -312,9 +316,14 @@ V8PageTableOps16k::walkMask(unsigned level) const } unsigned -V8PageTableOps16k::firstLevel() const +V8PageTableOps16k::firstLevel(uint8_t tsz) const { - return 0; + if (tsz == 16) return 0; + if (tsz >= 17 && tsz <= 27) return 1; + if (tsz >= 28 && tsz <= 38) return 2; + if (tsz == 39) return 3; + + panic("Unsupported TnSZ: %d\n", tsz); } unsigned @@ -400,9 +409,13 @@ V8PageTableOps64k::walkMask(unsigned level) const } unsigned -V8PageTableOps64k::firstLevel() const +V8PageTableOps64k::firstLevel(uint8_t tsz) const { - return 1; + if (tsz >= 12 && tsz <= 21) return 1; + if (tsz >= 22 && tsz <= 34) return 2; + if (tsz >= 35 && tsz <= 39) return 3; + + panic("Unsupported TnSZ: %d\n", tsz); } unsigned diff --git a/src/dev/arm/smmu_v3_ptops.hh b/src/dev/arm/smmu_v3_ptops.hh index 8680541c6..244910c02 100644 --- a/src/dev/arm/smmu_v3_ptops.hh +++ b/src/dev/arm/smmu_v3_ptops.hh @@ -55,7 +55,7 @@ struct PageTableOps virtual Addr index(Addr va, unsigned level) const = 0; virtual Addr pageMask(pte_t pte, unsigned level) const = 0; virtual Addr walkMask(unsigned level) const = 0; - virtual unsigned firstLevel() const = 0; + virtual unsigned firstLevel(uint8_t tsz) const = 0; virtual unsigned lastLevel() const = 0; }; @@ -68,7 +68,7 @@ struct V7LPageTableOps : public PageTableOps Addr index(Addr va, unsigned level) const override; Addr pageMask(pte_t pte, unsigned level) const override; Addr walkMask(unsigned level) const override; - unsigned firstLevel() const override; + unsigned firstLevel(uint8_t tsz) const override; unsigned lastLevel() const override; }; @@ -81,7 +81,7 @@ struct V8PageTableOps4k : public PageTableOps Addr index(Addr va, unsigned level) const override; Addr pageMask(pte_t pte, unsigned level) const override; Addr walkMask(unsigned level) const override; - unsigned firstLevel() const override; + unsigned firstLevel(uint8_t tsz) const override; unsigned lastLevel() const override; }; @@ -94,7 +94,7 @@ struct V8PageTableOps16k : public PageTableOps Addr index(Addr va, unsigned level) const override; Addr pageMask(pte_t pte, unsigned level) const override; Addr walkMask(unsigned level) const override; - unsigned firstLevel() const override; + unsigned firstLevel(uint8_t tsz) const override; unsigned lastLevel() const override; }; @@ -107,7 +107,7 @@ struct V8PageTableOps64k : public PageTableOps Addr index(Addr va, unsigned level) const override; Addr pageMask(pte_t pte, unsigned level) const override; Addr walkMask(unsigned level) const override; - unsigned firstLevel() const override; + unsigned firstLevel(uint8_t tsz) const override; unsigned lastLevel() const override; }; diff --git a/src/dev/arm/smmu_v3_transl.cc b/src/dev/arm/smmu_v3_transl.cc index c1a7ed1d3..84ca5a7c2 100644 --- a/src/dev/arm/smmu_v3_transl.cc +++ b/src/dev/arm/smmu_v3_transl.cc @@ -605,10 +605,12 @@ SMMUTranslationProcess::findConfig(Yield &yield, tc.httb = ste.dw3.s2ttb << STE_S2TTB_SHIFT; tc.vmid = ste.dw2.s2vmid; tc.stage2TranslGranule = ste.dw2.s2tg; + tc.s2t0sz = ste.dw2.s2t0sz; } else { tc.httb = 0xdeadbeef; tc.vmid = 0; tc.stage2TranslGranule = TRANS_GRANULE_INVALID; + tc.s2t0sz = 0; } @@ -621,11 +623,13 @@ SMMUTranslationProcess::findConfig(Yield &yield, tc.ttb1 = cd.dw2.ttb1 << CD_TTB_SHIFT; tc.asid = cd.dw0.asid; tc.stage1TranslGranule = cd.dw0.tg0; + tc.t0sz = cd.dw0.t0sz; } else { tc.ttb0 = 0xcafebabe; tc.ttb1 = 0xcafed00d; tc.asid = 0; tc.stage1TranslGranule = TRANS_GRANULE_INVALID; + tc.t0sz = 0; } return true; @@ -875,7 +879,7 @@ SMMUTranslationProcess::translateStage1And2(Yield &yield, Addr addr) // Level here is actually (level+1) so we can count down // to 0 using unsigned int. for (level = pt_ops->lastLevel() + 1; - level > pt_ops->firstLevel(); + level > pt_ops->firstLevel(context.t0sz); level--) { walkCacheLookup(yield, walk_ep, addr, @@ -908,7 +912,8 @@ SMMUTranslationProcess::translateStage1And2(Yield &yield, Addr addr) table_addr = s2tr.addr; } - tr = walkStage1And2(yield, addr, pt_ops, pt_ops->firstLevel(), + tr = walkStage1And2(yield, addr, pt_ops, + pt_ops->firstLevel(context.t0sz), table_addr); } @@ -949,13 +954,13 @@ SMMUTranslationProcess::translateStage2(Yield &yield, Addr addr, bool final_tr) } const WalkCache::Entry *walk_ep = NULL; - unsigned level = pt_ops->firstLevel(); + unsigned level = pt_ops->firstLevel(context.s2t0sz); if (final_tr || smmu.walkCacheNonfinalEnable) { // Level here is actually (level+1) so we can count down // to 0 using unsigned int. for (level = pt_ops->lastLevel() + 1; - level > pt_ops->firstLevel(); + level > pt_ops->firstLevel(context.s2t0sz); level--) { walkCacheLookup(yield, walk_ep, addr, @@ -981,7 +986,8 @@ SMMUTranslationProcess::translateStage2(Yield &yield, Addr addr, bool final_tr) level + 1, walk_ep->pa); } } else { - tr = walkStage2(yield, addr, final_tr, pt_ops, pt_ops->firstLevel(), + tr = walkStage2(yield, addr, final_tr, pt_ops, + pt_ops->firstLevel(context.s2t0sz), context.httb); } diff --git a/src/dev/arm/smmu_v3_transl.hh b/src/dev/arm/smmu_v3_transl.hh index 6a69460de..4da35d72d 100644 --- a/src/dev/arm/smmu_v3_transl.hh +++ b/src/dev/arm/smmu_v3_transl.hh @@ -73,6 +73,8 @@ class SMMUTranslationProcess : public SMMUProcess uint16_t vmid; uint8_t stage1TranslGranule; uint8_t stage2TranslGranule; + uint8_t t0sz; + uint8_t s2t0sz; }; enum FaultType