arch-power: Added Data and Instruction Interrupt Handler
authorkajoljain379 <kajoljain797@gmail.com>
Wed, 16 Jan 2019 11:39:56 +0000 (17:09 +0530)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 24 Jan 2021 03:59:17 +0000 (03:59 +0000)
Added data and instruction storage interrupr handler and
modify radixwalk.cc to check permissions and privileges of
both data and instrustion.

Change-Id: I5d3a820862cde7bd298f0b715777f069fb1e39d1
Signed-off-by: kajoljain379 <kajoljain797@gmail.com>
src/arch/power/faults.hh
src/arch/power/radixwalk.cc
src/arch/power/radixwalk.hh

index 6bcd87923bfbf3dd9fa909ba971e8e38f54d100a..81ea3480bdc4534081d8268cdfc700c6fe35bcb7 100644 (file)
@@ -136,6 +136,96 @@ class PowerInterrupt : public PowerFaultBase
     }
 };
 
+class InstrStorageInterrupt : public PowerInterrupt
+{
+public:
+  InstrStorageInterrupt()
+  {
+  }
+  virtual void invoke(ThreadContext * tc, const StaticInstPtr &inst =
+                       StaticInst::nullStaticInstPtr , uint64_t bitSet = 0)
+    {
+      tc->setIntReg(INTREG_SRR0 , tc->instAddr());
+      PowerInterrupt::updateSRR1(tc, bitSet);
+      PowerInterrupt::updateMsr(tc);
+      tc->pcState(InstrStoragePCSet);
+    }
+};
+
+class InstrInvalidInterrupt : public InstrStorageInterrupt
+{
+public:
+  InstrInvalidInterrupt()
+    {
+    }
+    virtual void invoke(ThreadContext * tc, const StaticInstPtr &inst =
+                       StaticInst::nullStaticInstPtr)
+    {
+      InstrStorageInterrupt::invoke(tc, inst ,setBitMask(INVALID_SET_BIT));
+    }
+};
+
+//When permissions or privilege violates
+class InstrPriStorageInterrupt : public InstrStorageInterrupt
+{
+public:
+  InstrPriStorageInterrupt()
+    {
+    }
+    virtual void invoke(ThreadContext * tc, const StaticInstPtr &inst =
+                       StaticInst::nullStaticInstPtr)
+    {
+      InstrStorageInterrupt::invoke(tc, inst ,setBitMask(PERMISSION_BIT));
+    }
+};
+
+class DataStorageInterrupt :public PowerInterrupt
+{
+public:
+  DataStorageInterrupt()
+    {
+    }
+    virtual void invoke(ThreadContext * tc, const StaticInstPtr &inst =
+                       StaticInst::nullStaticInstPtr ,uint64_t bitSet = 0)
+    {
+      Msr msr = tc->readIntReg(INTREG_MSR);
+      tc->setIntReg(INTREG_SRR0 , tc->instAddr());
+      PowerInterrupt::updateSRR1(tc, 0);
+      uint64_t dsisr = tc->readIntReg(INTREG_DSISR);
+      dsisr = (dsisr & DSISR_MASK) | bitSet;
+      if (msr.dr)
+        dsisr = setbit(33, dsisr);
+      tc->setIntReg(INTREG_DSISR, dsisr);
+      PowerInterrupt::updateMsr(tc);
+      tc->pcState(DataStoragePCSet);
+    }
+};
+
+class DataInvalidInterrupt : public DataStorageInterrupt
+{
+public:
+  DataInvalidInterrupt()
+    {
+    }
+    virtual void invoke(ThreadContext * tc, const StaticInstPtr &inst =
+                       StaticInst::nullStaticInstPtr)
+    {
+      DataStorageInterrupt::invoke(tc, inst ,setBitMask(INVALID_SET_BIT));
+    }
+};
+
+//When permissions or privilege violates
+class DataPriStorageInterrupt : public DataStorageInterrupt
+{
+public:
+  DataPriStorageInterrupt()
+    {
+    }
+    virtual void invoke(ThreadContext * tc, const StaticInstPtr &inst =
+                       StaticInst::nullStaticInstPtr)
+    {
+      DataStorageInterrupt::invoke(tc, inst ,setBitMask(PERMISSION_BIT));
+    }
 };
 
 //TODO: Need to add Floating point and TM Bad thing fault handler
index 04457960edac7953168e0eccad0d1dc8c9d43d07..7bc671684dc16496e7d72c866f250d0eb011afe3 100644 (file)
@@ -135,17 +135,24 @@ RadixWalk::start(ThreadContext * tc, RequestPtr req, BaseTLB::Mode mode)
     DPRINTF(RadixWalk,"RPDB: 0x%lx\n RPDS: 0x%lx\n usefulBits: %ld\n\n"
             ,rpdb,rpds,usefulBits);
 
-    //TODO:
-    //==========
-    // Fault should be generated as a return value of walkTree. Perhaps
-    // we can pass paddr as a pointer in which the physical address can
-    // be returned.
-    // As of now we assume that there are no faults.
-    Addr paddr = this->walkTree(vaddr, nextLevelBase,
+    std::pair<Addr, Fault> AddrTran;
+
+    Lpcr lpcr = tc->readIntReg(INTREG_LPCR);
+
+    if (lpcr.hr == 0 && lpcr.vc <= 3) {
+        if (mode == BaseTLB::Execute)
+            return std::make_shared<InstrInvalidInterrupt>();
+
+        return std::make_shared<DataInvalidInterrupt>();
+    }
+    AddrTran = this->walkTree(vaddr, nextLevelBase, tc, mode,
                                 nextLevelSize, usefulBits);
-    req->setPaddr(paddr);
-    DPRINTF(RadixWalk,"Radix Translated %#x -> %#x\n",vaddr,paddr);
-    return NoFault;
+    if (AddrTran.first) {
+      req->setPaddr(AddrTran.first);
+      DPRINTF(RadixWalk,"Radix Translated %#x -> %#x\n",
+      vaddr,AddrTran.first);
+    }
+    return AddrTran.second;
 }
 
 uint64_t
@@ -303,12 +310,11 @@ RadixWalk::getRPDEntry(ThreadContext * tc, Addr vaddr)
     return prte0;
 }
 
-Addr
-RadixWalk::walkTree(Addr vaddr ,uint64_t curBase ,
-                    uint64_t curSize ,uint64_t usefulBits)
+std::pair<Addr, Fault>
+RadixWalk::walkTree(Addr vaddr ,uint64_t curBase ,ThreadContext * tc ,
+    BaseTLB::Mode mode ,uint64_t curSize ,uint64_t usefulBits)
 {
         uint64_t dataSize = 8;
-
         if (curSize < 5) {
             panic("vaddr = %lx, Radix RPDS = %lx,is less than 5\n",
                   vaddr, curSize);
@@ -384,19 +390,42 @@ RadixWalk::walkTree(Addr vaddr ,uint64_t curBase ,
         Rpde rpde = this->readPhysMem(entryAddr, dataSize);
         DPRINTF(RadixWalk,"rpde:%lx\n",(uint64_t)rpde);
         usefulBits = usefulBits - curSize;
+        std::pair<Addr, Fault> AddrTran;
+
+        if (rpde.valid == 0) {
+            AddrTran.first = vaddr;
+            if (mode == BaseTLB::Execute)
+                AddrTran.second = std::make_shared<InstrInvalidInterrupt>();
+            else
+                AddrTran.second =  std::make_shared<DataInvalidInterrupt>();
+        return AddrTran;
+           }
+
         //Ref: Power ISA Manual v3.0B, Book-III, section 5.7.10.2
-        if (rpde.leaf == 1)
-        {
+        if (rpde.leaf == 1) {
+                Rpte  rpte = (uint64_t)rpde;
                 uint64_t realpn = rpde & RPN_MASK;
                 uint64_t pageMask = (1UL << usefulBits) - 1;
                 Addr paddr = (realpn & ~pageMask) | (vaddr & pageMask);
-
-                //TODO: Check for permissions.
-                // We aren't doing that right now
-                // If there is a mismatch in the permissions,
-                // generate a fault.
                 DPRINTF(RadixWalk,"paddr:%lx\n",paddr);
-                return 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<InstrPriStorageInterrupt>();
+              }
+
+            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<DataPriStorageInterrupt>();
+              }
+
+          return AddrTran;
         }
 
         uint64_t nextLevelBase = align(rpde.NLB, DIR_BASE_ALIGN);
@@ -404,7 +433,8 @@ RadixWalk::walkTree(Addr vaddr ,uint64_t curBase ,
         DPRINTF(RadixWalk,"NLB: %lx\n",(uint64_t)nextLevelBase);
         DPRINTF(RadixWalk,"NLS: %lx\n",(uint64_t)nextLevelSize);
         DPRINTF(RadixWalk,"usefulBits: %lx",(uint64_t)usefulBits);
-        return walkTree(vaddr, nextLevelBase, nextLevelSize, usefulBits);
+        return walkTree(vaddr, nextLevelBase, tc ,
+                             mode, nextLevelSize, usefulBits);
 }
 
 void
index 11814e0f101d02bf2b7a29b6d5d6309c2bdf0c88..8c9cd3813af65ece5b37ade229506b951f6784f9 100644 (file)
@@ -64,9 +64,11 @@ namespace PowerISA
         Fault start(ThreadContext * _tc, RequestPtr req, BaseTLB::Mode mode);
         BaseMasterPort &getMasterPort(const std::string &if_name,
                                       PortID idx = InvalidPortID);
-      Addr getRPDEntry(ThreadContext * tc, Addr vaddr);
-        Addr walkTree(Addr vaddr ,uint64_t ptbase ,
-                      uint64_t ptsize ,uint64_t psize);
+
+        Addr getRPDEntry(ThreadContext * tc, Addr vaddr);
+        std::pair<Addr,Fault> walkTree(Addr vaddr ,uint64_t curBase ,
+                         ThreadContext * tc ,BaseTLB::Mode mode ,
+                         uint64_t curSize ,uint64_t usefulBits);
 
         typedef PowerRadixWalkParams Params;