From 3ed50acb1ebc7a301196ee877253f6d11efb4164 Mon Sep 17 00:00:00 2001 From: Michiel Van Tol Date: Mon, 22 Jul 2019 16:51:48 +0100 Subject: [PATCH] dev-arm: Add 16K granule support to SMMUv3 model Added the necessary PageTableOps that match the 16K granule translation regime. Change-Id: I46ef07939cb4bdc8c0bbbeeeb6a50a9ab0d64de0 Reviewed-by: Michiel Van Tol Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/19628 Reviewed-by: Andreas Sandberg Maintainer: Andreas Sandberg Tested-by: kokoro --- src/dev/arm/smmu_v3.cc | 2 + src/dev/arm/smmu_v3_ptops.cc | 96 ++++++++++++++++++++++++++++++++++++ src/dev/arm/smmu_v3_ptops.hh | 13 +++++ 3 files changed, 111 insertions(+) diff --git a/src/dev/arm/smmu_v3.cc b/src/dev/arm/smmu_v3.cc index d913d55a0..7c4bd3673 100644 --- a/src/dev/arm/smmu_v3.cc +++ b/src/dev/arm/smmu_v3.cc @@ -531,10 +531,12 @@ const PageTableOps* SMMUv3::getPageTableOps(uint8_t trans_granule) { static V8PageTableOps4k ptOps4k; + static V8PageTableOps16k ptOps16k; static V8PageTableOps64k ptOps64k; switch (trans_granule) { case TRANS_GRANULE_4K: return &ptOps4k; + case TRANS_GRANULE_16K: return &ptOps16k; case TRANS_GRANULE_64K: return &ptOps64k; default: panic("Unknown translation granule size %d", trans_granule); diff --git a/src/dev/arm/smmu_v3_ptops.cc b/src/dev/arm/smmu_v3_ptops.cc index 6490b34c7..c57c16a3a 100644 --- a/src/dev/arm/smmu_v3_ptops.cc +++ b/src/dev/arm/smmu_v3_ptops.cc @@ -227,6 +227,102 @@ V8PageTableOps4k::lastLevel() const return 3; } +bool +V8PageTableOps16k::isValid(pte_t pte, unsigned level) const +{ + switch (level) { + case 0: return pte & 0x1; + case 1: return pte & 0x1; + case 2: return pte & 0x1; + case 3: return (pte & 0x1) && (pte & 0x2); + default: panic("bad level %d", level); + } +} + +bool +V8PageTableOps16k::isLeaf(pte_t pte, unsigned level) const +{ + switch (level) { + case 0: return false; + case 1: return false; + case 2: return !(pte & 0x2); + case 3: return true; + default: panic("bad level %d", level); + } +} + +bool +V8PageTableOps16k::isWritable(pte_t pte, unsigned level, bool stage2) const +{ + return stage2 ? bits(pte, 7, 6) == 3 : bits(pte, 7) == 0; +} + +Addr +V8PageTableOps16k::nextLevelPointer(pte_t pte, unsigned level) const +{ + if (isLeaf(pte, level)) { + switch (level) { + // no level 0 here + case 1: return mbits(pte, 47, 36); + case 2: return mbits(pte, 47, 25); + case 3: return mbits(pte, 47, 14); + default: panic("bad level %d", level); + } + } else { + return mbits(pte, 47, 12); + } +} + +Addr +V8PageTableOps16k::index(Addr va, unsigned level) const +{ + switch (level) { + case 0: return bits(va, 47, 47) << 3; break; + case 1: return bits(va, 46, 36) << 3; break; + case 2: return bits(va, 35, 25) << 3; break; + case 3: return bits(va, 24, 14) << 3; break; + default: panic("bad level %d", level); + } +} + +Addr +V8PageTableOps16k::pageMask(pte_t pte, unsigned level) const +{ + switch (level) { + // no level 0 here + case 1: return ~mask(36); + // 16K granule supports contiguous entries also at L2; - 1G + case 2: return bits(pte, 52) ? ~mask(30) : ~mask(25); + // as well as at L3; - 2M + case 3: return bits(pte, 52) ? ~mask(21) : ~mask(14); + default: panic("bad level %d", level); + } +} + +Addr +V8PageTableOps16k::walkMask(unsigned level) const +{ + switch (level) { + case 0: return ~mask(47); + case 1: return ~mask(36); + case 2: return ~mask(25); + case 3: return ~mask(14); + default: panic("bad level %d", level); + } +} + +unsigned +V8PageTableOps16k::firstLevel() const +{ + return 0; +} + +unsigned +V8PageTableOps16k::lastLevel() const +{ + return 3; +} + bool V8PageTableOps64k::isValid(pte_t pte, unsigned level) const { diff --git a/src/dev/arm/smmu_v3_ptops.hh b/src/dev/arm/smmu_v3_ptops.hh index ef9ef0409..1b8c22c4d 100644 --- a/src/dev/arm/smmu_v3_ptops.hh +++ b/src/dev/arm/smmu_v3_ptops.hh @@ -85,6 +85,19 @@ struct V8PageTableOps4k : public PageTableOps virtual unsigned lastLevel() const; }; +struct V8PageTableOps16k : public PageTableOps +{ + virtual bool isValid(pte_t pte, unsigned level) const; + virtual bool isLeaf(pte_t pte, unsigned level) const; + virtual bool isWritable(pte_t pte, unsigned level, bool stage2) const; + virtual Addr nextLevelPointer(pte_t pte, unsigned level) const; + virtual Addr index(Addr va, unsigned level) const; + virtual Addr pageMask(pte_t pte, unsigned level) const; + virtual Addr walkMask(unsigned level) const; + virtual unsigned firstLevel() const; + virtual unsigned lastLevel() const; +}; + struct V8PageTableOps64k : public PageTableOps { virtual bool isValid(pte_t pte, unsigned level) const; -- 2.30.2