summaryrefslogtreecommitdiff
path: root/src/dev/arm
diff options
context:
space:
mode:
authorGiacomo Travaglini <giacomo.travaglini@arm.com>2019-07-22 16:08:26 +0100
committerGiacomo Travaglini <giacomo.travaglini@arm.com>2019-07-25 12:49:12 +0000
commite71e2d6a35233250ad05b358c27cad5a05609d55 (patch)
tree4c3eea92bda2b3f352cb37e16637225c9c3dd09e /src/dev/arm
parent36da743e0b934c853cab41e5254e1ba2e93f157d (diff)
downloadgem5-e71e2d6a35233250ad05b358c27cad5a05609d55.tar.xz
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 <giacomo.travaglini@arm.com> Reviewed-by: Michiel Van Tol <michiel.vantol@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/19630 Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com> Tested-by: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'src/dev/arm')
-rw-r--r--src/dev/arm/smmu_v3_ptops.cc27
-rw-r--r--src/dev/arm/smmu_v3_ptops.hh10
-rw-r--r--src/dev/arm/smmu_v3_transl.cc16
-rw-r--r--src/dev/arm/smmu_v3_transl.hh2
4 files changed, 38 insertions, 17 deletions
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