diff --git a/src/dev/arm/smmu_v3_ptops.cc b/src/dev/arm/smmu_v3_ptops.cc index c57c16a3a3..96d876ea31 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 8680541c6d..244910c023 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 c1a7ed1d30..84ca5a7c2a 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 6a69460dea..4da35d72d7 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