From 8d4e72d1020e9c420d2e3150587a8937a4516ec7 Mon Sep 17 00:00:00 2001 From: kajoljain379 Date: Wed, 20 Mar 2019 15:22:55 +0530 Subject: [PATCH] arch-power: Updated Data & Instruction Storage Interrupt Added more checks for DATA and INSTRUCTION Storage Interrupt. Change-Id: I1e386ac007ebd59cc5447a6226360965748073f5 Signed-off-by: kajoljain379 --- src/arch/power/radixwalk.cc | 88 +++++++++++++++++++++++++------------ src/arch/power/radixwalk.hh | 3 +- 2 files changed, 63 insertions(+), 28 deletions(-) diff --git a/src/arch/power/radixwalk.cc b/src/arch/power/radixwalk.cc index 46f47f92e..ded483033 100644 --- a/src/arch/power/radixwalk.cc +++ b/src/arch/power/radixwalk.cc @@ -37,6 +37,17 @@ #define RTS2_SHIFT 5 #define RTS2_MASK ((1 << RTS2_BITS) - 1) +#define NOHPTE 0x0000000040000000 + /*Bit-33 Acc to ISA: no translation found */ +#define PROTFAULT 0x0000000008000000 + /* Bit-36 Acc to ISA:protection fault */ +#define ISSTORE 0x0000000002000000 + /* Bit-38 Acc to ISA:access was a store */ +#define UNSUPP_MMU 0x0000000000080000 + /*Bit-44 P9: Unsupported MMU config */ +#define PRTABLE_FAULT 0x0000000000020000 + /*Bit-46 P9: Fault on process table */ + #define RPN_MASK 0x01fffffffffff000 #define QUADRANT_MASK 0xc000000000000000 @@ -192,18 +203,23 @@ RadixWalk::start(ThreadContext * tc, RequestPtr req, BaseTLB::Mode mode) std::pair AddrTran; Lpcr lpcr = tc->readIntReg(INTREG_LPCR); - - if (lpcr.hr == 0 && lpcr.vc <= 3) { - if (mode == BaseTLB::Execute) - return std::make_shared(); - - return std::make_shared(); + Msr msr = tc->readIntReg(INTREG_MSR); + AddrTran.first = vaddr; + + if (( lpcr.hr == 0 && lpcr.vc <= 3 ) || + ( msr.hv == 1 && msr.pr == 0 && msr.dr == 0 )) { + AddrTran.second = prepareSI(tc, req, mode, + PRTABLE_FAULT); + DPRINTF(RadixWalk,"Fault Generated due to Process table fault\n"); + return AddrTran.second; } - AddrTran = this->walkTree(vaddr, nextLevelBase, tc, mode, + + AddrTran = this->walkTree(vaddr, nextLevelBase, tc, mode, req, nextLevelSize, usefulBits); - if (AddrTran.first) { - req->setPaddr(AddrTran.first); - DPRINTF(RadixWalk,"Radix Translated %#x -> %#x\n", + req->setPaddr(AddrTran.first); + if (AddrTran.second == NoFault) { + + DPRINTF(RadixWalk,"Radix Translated 0x%016lx -> 0x%016lx\n", vaddr,AddrTran.first); } return AddrTran.second; @@ -298,7 +314,7 @@ RadixWalk::getRPDEntry(ThreadContext * tc, Addr vaddr) uint64_t pate1Addr = align(ptcr.patb, TABLE_BASE_ALIGN) + (efflpid*sizeof(uint64_t)*2) + 8; uint64_t dataSize = 8; - uint64_t pate1 = this->readPhysMem(pate1Addr, dataSize); + uint64_t pate1 = betog(this->readPhysMem(pate1Addr, dataSize)); DPRINTF(RadixWalk,"2nd Double word of partition table entry: 0x%016lx\n", pate1); @@ -358,7 +374,7 @@ RadixWalk::getRPDEntry(ThreadContext * tc, Addr vaddr) DPRINTF(RadixWalk,"effPID=%d\n", effPID); uint64_t prte0Addr = prtb + effPID*sizeof(prtb)*2 ; DPRINTF(RadixWalk,"Process table base: 0x%016lx\n",prtb); - uint64_t prte0 = this->readPhysMem(prte0Addr, dataSize); + uint64_t prte0 = betog(this->readPhysMem(prte0Addr, dataSize)); //prte0 ---> Process Table Entry DPRINTF(RadixWalk,"process table entry: 0x%016lx\n",prte0); @@ -367,12 +383,19 @@ RadixWalk::getRPDEntry(ThreadContext * tc, Addr vaddr) std::pair RadixWalk::walkTree(Addr vaddr ,uint64_t curBase ,ThreadContext * tc , - BaseTLB::Mode mode ,uint64_t curSize ,uint64_t usefulBits) + BaseTLB::Mode mode , RequestPtr req, uint64_t curSize ,uint64_t usefulBits) { uint64_t dataSize = 8; + std::pair AddrTran; + if (curSize < 5) { - panic("vaddr = %lx, Radix RPDS = %lx,is less than 5\n", - vaddr, curSize); + DPRINTF(RadixWalk,"[PANIC] vaddr = %lx,Radix RPDS = %lx,< 5\n", + vaddr, curSize); + AddrTran.first = vaddr; + AddrTran.second = prepareSI(tc, req, mode, + UNSUPP_MMU); + DPRINTF(RadixWalk,"Fault due to unsupported Radix Tree config\n"); + return AddrTran; } // vaddr 64 Bit // vaddr |-----------------------------------------------------| @@ -442,21 +465,28 @@ RadixWalk::walkTree(Addr vaddr ,uint64_t curBase ,ThreadContext * tc , uint64_t index = extract(vaddr, shift, mask); uint64_t entryAddr = curBase + (index * sizeof(uint64_t)); - Rpde rpde = this->readPhysMem(entryAddr, dataSize); + Rpde rpde = betog(this->readPhysMem(entryAddr, dataSize)); DPRINTF(RadixWalk,"rpde:0x%016lx\n",(uint64_t)rpde); usefulBits = usefulBits - curSize; - std::pair AddrTran; + Msr msr = tc->readIntReg(INTREG_MSR); if (rpde.valid == 0) { AddrTran.first = vaddr; - if (mode == BaseTLB::Execute) - AddrTran.second = std::make_shared(); - else - AddrTran.second = std::make_shared(); + Lpcr lpcr = tc->readIntReg(INTREG_LPCR); + + if (lpcr.hr == 0) { + AddrTran.second = prepareSI(tc, req, mode, + PRTABLE_FAULT); + DPRINTF(RadixWalk,"Fault generated due to invalid pt entry\n"); + } + else if (msr.dr == 1 || msr.ir == 1) { + AddrTran.second = prepareSI(tc, req, mode, NOHPTE); + DPRINTF(RadixWalk,"Fault due to translation not found\n"); + } return AddrTran; } - //Ref: Power ISA Manual v3.0B, Book-III, section 5.7.10.2 + //Ref: Power ISA Manual v3.0B, Book-III, section 5. 7.10.2 if (rpde.leaf == 1) { Rpte rpte = (uint64_t)rpde; uint64_t realpn = rpde & RPN_MASK; @@ -465,19 +495,23 @@ RadixWalk::walkTree(Addr vaddr ,uint64_t curBase ,ThreadContext * tc , DPRINTF(RadixWalk,"paddr:0x%016lx\n",paddr); AddrTran.second = NoFault; AddrTran.first = paddr; - Msr msr = tc->readIntReg(INTREG_MSR); + //Conditions for checking privileges and permissions if (mode == BaseTLB::Execute && - (!rpte.exe || ( rpte.pri && msr.pr ))) { - AddrTran.second = std::make_shared(); + (!rpte.exe || ( rpte.pri && msr.pr ))) { + AddrTran.second = prepareISI(tc, req, + PROTFAULT); + DPRINTF(RadixWalk,"Fault is due to protection violation\n"); } else if ( ( mode == BaseTLB::Read && !rpte.read ) || ( mode == BaseTLB::Write && !rpte.r_w ) || (( mode != BaseTLB::Execute) && (rpte.pri && msr.pr ))) { - AddrTran.second = std::make_shared(); + AddrTran.second = prepareDSI(tc, req, mode, + PROTFAULT); + DPRINTF(RadixWalk,"Fault is due to protection violation\n"); } return AddrTran; @@ -489,7 +523,7 @@ RadixWalk::walkTree(Addr vaddr ,uint64_t curBase ,ThreadContext * tc , DPRINTF(RadixWalk,"NLS: 0x%lx\n",(uint64_t)nextLevelSize); DPRINTF(RadixWalk,"usefulBits: %lx",(uint64_t)usefulBits); return walkTree(vaddr, nextLevelBase, tc , - mode, nextLevelSize, usefulBits); + mode, req, nextLevelSize, usefulBits); } void diff --git a/src/arch/power/radixwalk.hh b/src/arch/power/radixwalk.hh index 850c952e8..f0ba79ff6 100644 --- a/src/arch/power/radixwalk.hh +++ b/src/arch/power/radixwalk.hh @@ -67,8 +67,9 @@ namespace PowerISA PortID idx = InvalidPortID); Addr getRPDEntry(ThreadContext * tc, Addr vaddr); + std::pair walkTree(Addr vaddr ,uint64_t curBase , - ThreadContext * tc ,BaseTLB::Mode mode , + ThreadContext * tc ,BaseTLB::Mode mode , RequestPtr req, uint64_t curSize ,uint64_t usefulBits); Fault prepareSI(ThreadContext * tc, RequestPtr req, BaseTLB::Mode mode, uint64_t BitMask); -- 2.30.2