diff --git a/src/arch/arm/pagetable.cc b/src/arch/arm/pagetable.cc index 4987aa7b74..506b615521 100644 --- a/src/arch/arm/pagetable.cc +++ b/src/arch/arm/pagetable.cc @@ -95,15 +95,15 @@ V7LPageTableOps::nextLevelPointer(pte_t pte, unsigned level) const } Addr -V7LPageTableOps::index(Addr va, unsigned level) const +V7LPageTableOps::index(Addr va, unsigned level, int tsz) const { // In theory this should be configurable... const int n = 12; switch (level) { - case 1: return bits(va, 26+n, 30) << 3; break; - case 2: return bits(va, 29, 21) << 3; break; - case 3: return bits(va, 20, 12) << 3; break; + case 1: return bits(va, std::min(26+n, tsz - 1), 30) << 3; break; + case 2: return bits(va, std::min(29, tsz - 1), 21) << 3; break; + case 3: return bits(va, std::min(20, tsz - 1), 12) << 3; break; default: panic("bad level %d", level); } } @@ -189,13 +189,13 @@ V8PageTableOps4k::nextLevelPointer(pte_t pte, unsigned level) const } Addr -V8PageTableOps4k::index(Addr va, unsigned level) const +V8PageTableOps4k::index(Addr va, unsigned level, int tsz) const { switch (level) { - case 0: return bits(va, 47, 39) << 3; break; - case 1: return bits(va, 38, 30) << 3; break; - case 2: return bits(va, 29, 21) << 3; break; - case 3: return bits(va, 20, 12) << 3; break; + case 0: return bits(va, std::min(47, tsz - 1), 39) << 3; break; + case 1: return bits(va, std::min(38, tsz - 1), 30) << 3; break; + case 2: return bits(va, std::min(29, tsz - 1), 21) << 3; break; + case 3: return bits(va, std::min(20, tsz - 1), 12) << 3; break; default: panic("bad level %d", level); } } @@ -298,13 +298,13 @@ V8PageTableOps16k::nextLevelPointer(pte_t pte, unsigned level) const } Addr -V8PageTableOps16k::index(Addr va, unsigned level) const +V8PageTableOps16k::index(Addr va, unsigned level, int tsz) 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; + case 0: return bits(va, std::min(47, tsz - 1), 47) << 3; break; + case 1: return bits(va, std::min(46, tsz - 1), 36) << 3; break; + case 2: return bits(va, std::min(35, tsz - 1), 25) << 3; break; + case 3: return bits(va, std::min(24, tsz - 1), 14) << 3; break; default: panic("bad level %d", level); } } @@ -407,12 +407,12 @@ V8PageTableOps64k::nextLevelPointer(pte_t pte, unsigned level) const } Addr -V8PageTableOps64k::index(Addr va, unsigned level) const +V8PageTableOps64k::index(Addr va, unsigned level, int tsz) const { switch (level) { - case 1: return bits(va, 47, 42) << 3; break; - case 2: return bits(va, 41, 29) << 3; break; - case 3: return bits(va, 28, 16) << 3; break; + case 1: return bits(va, std::min(47, tsz - 1), 42) << 3; break; + case 2: return bits(va, std::min(41, tsz - 1), 29) << 3; break; + case 3: return bits(va, std::min(28, tsz - 1), 16) << 3; break; default: panic("bad level %d", level); } } diff --git a/src/arch/arm/pagetable.hh b/src/arch/arm/pagetable.hh index b03320af3f..9bbf5afd6f 100644 --- a/src/arch/arm/pagetable.hh +++ b/src/arch/arm/pagetable.hh @@ -104,7 +104,7 @@ struct PageTableOps virtual bool isLeaf(pte_t pte, unsigned level) const = 0; virtual bool isWritable(pte_t pte, unsigned level, bool stage2) const = 0; virtual Addr nextLevelPointer(pte_t pte, unsigned level) const = 0; - virtual Addr index(Addr va, unsigned level) const = 0; + virtual Addr index(Addr va, unsigned level, int tsz) const = 0; virtual Addr pageMask(pte_t pte, unsigned level) const = 0; virtual Addr walkMask(unsigned level) const = 0; virtual LookupLevel firstLevel(uint8_t tsz) const = 0; @@ -118,7 +118,7 @@ struct V7LPageTableOps : public PageTableOps bool isLeaf(pte_t pte, unsigned level) const override; bool isWritable(pte_t pte, unsigned level, bool stage2) const override; Addr nextLevelPointer(pte_t pte, unsigned level) const override; - Addr index(Addr va, unsigned level) const override; + Addr index(Addr va, unsigned level, int tsz) const override; Addr pageMask(pte_t pte, unsigned level) const override; Addr walkMask(unsigned level) const override; LookupLevel firstLevel(uint8_t tsz) const override; @@ -131,7 +131,7 @@ struct V8PageTableOps4k : public PageTableOps bool isLeaf(pte_t pte, unsigned level) const override; bool isWritable(pte_t pte, unsigned level, bool stage2) const override; Addr nextLevelPointer(pte_t pte, unsigned level) const override; - Addr index(Addr va, unsigned level) const override; + Addr index(Addr va, unsigned level, int tsz) const override; Addr pageMask(pte_t pte, unsigned level) const override; Addr walkMask(unsigned level) const override; LookupLevel firstLevel(uint8_t tsz) const override; @@ -145,7 +145,7 @@ struct V8PageTableOps16k : public PageTableOps bool isLeaf(pte_t pte, unsigned level) const override; bool isWritable(pte_t pte, unsigned level, bool stage2) const override; Addr nextLevelPointer(pte_t pte, unsigned level) const override; - Addr index(Addr va, unsigned level) const override; + Addr index(Addr va, unsigned level, int tsz) const override; Addr pageMask(pte_t pte, unsigned level) const override; Addr walkMask(unsigned level) const override; LookupLevel firstLevel(uint8_t tsz) const override; @@ -159,7 +159,7 @@ struct V8PageTableOps64k : public PageTableOps bool isLeaf(pte_t pte, unsigned level) const override; bool isWritable(pte_t pte, unsigned level, bool stage2) const override; Addr nextLevelPointer(pte_t pte, unsigned level) const override; - Addr index(Addr va, unsigned level) const override; + Addr index(Addr va, unsigned level, int tsz) const override; Addr pageMask(pte_t pte, unsigned level) const override; Addr walkMask(unsigned level) const override; LookupLevel firstLevel(uint8_t tsz) const override; diff --git a/src/dev/arm/smmu_v3_transl.cc b/src/dev/arm/smmu_v3_transl.cc index e94d2af15e..85554f8bd0 100644 --- a/src/dev/arm/smmu_v3_transl.cc +++ b/src/dev/arm/smmu_v3_transl.cc @@ -745,7 +745,8 @@ SMMUTranslationProcess::walkStage1And2(Yield &yield, Addr addr, doSemaphoreUp(smmu.cycleSem); for (; level <= pt_ops->lastLevel(); level++) { - Addr pte_addr = walkPtr + pt_ops->index(addr, level); + Addr pte_addr = walkPtr + pt_ops->index( + addr, level, 64 - context.t0sz); DPRINTF(SMMUv3, "Fetching S1 L%d PTE from pa=%#08x\n", level, pte_addr); @@ -829,7 +830,8 @@ SMMUTranslationProcess::walkStage2(Yield &yield, Addr addr, bool final_tr, doSemaphoreUp(smmu.cycleSem); for (; level <= pt_ops->lastLevel(); level++) { - Addr pte_addr = walkPtr + pt_ops->index(addr, level); + Addr pte_addr = walkPtr + pt_ops->index( + addr, level, 64 - context.s2t0sz); DPRINTF(SMMUv3, " Fetching S2 L%d PTE from pa=%#08x\n", level, pte_addr);