power: Add support for handling the Decrementer Interrupt
authorPhanikiran Harithas <phanikiran.harithas@gmail.com>
Sun, 10 Jun 2018 09:01:05 +0000 (14:31 +0530)
committerKajol Jain <kajoljain797@gmail.com>
Wed, 12 Jun 2019 06:30:49 +0000 (12:00 +0530)
This patch allows the programming of the decrementer device, which
will count down to zero. As of now, the decrement happens after every
instruction. When the decrementer value hits 0, the CPU is delivered a
decrementer interrupt.

[ego@linux.vnet.ibm.com: Fixed Conflicts in src/arch/power/interrupts.hh]

Change-Id: I3a863a8e2bca434d5a8139df662429d3e83a8542

Signed-off-by: Phanikiran Harithas <phanikiran.harithas@gmail.com>
Signed-off-by: Venkatnarayan Kulkarni <venkatnarayankulkarni@gmail.com>
src/arch/power/faults.hh
src/arch/power/interrupts.hh
src/arch/power/system.cc

index a99ae7b307ee7a9ba5b3dc95e75205341bb60a86..bfb4dd00f724449c19ea46ec03c23abdeeb2a207 100644 (file)
 #ifndef __ARCH_POWER_FAULTS_HH__
 #define __ARCH_POWER_FAULTS_HH__
 
+#include "cpu/thread_context.hh"
 #include "sim/faults.hh"
 
 namespace PowerISA
 {
 
-class PowerFault : public FaultBase
+class PowerFaultBase : public FaultBase
 {
   protected:
     FaultName _name;
 
-    PowerFault(FaultName name)
+    PowerFaultBase(FaultName name)
         : _name(name)
     {
     }
@@ -56,35 +57,66 @@ class PowerFault : public FaultBase
 };
 
 
-class UnimplementedOpcodeFault : public PowerFault
+class UnimplementedOpcodeFault : public PowerFaultBase
 {
   public:
     UnimplementedOpcodeFault()
-        : PowerFault("Unimplemented Opcode")
+        : PowerFaultBase("Unimplemented Opcode")
     {
     }
 };
 
 
-class MachineCheckFault : public PowerFault
+class MachineCheckFault : public PowerFaultBase
 {
   public:
     MachineCheckFault()
-        : PowerFault("Machine Check")
+        : PowerFaultBase("Machine Check")
     {
     }
 };
 
 
-class AlignmentFault : public PowerFault
+class AlignmentFault : public PowerFaultBase
 {
   public:
     AlignmentFault()
-        : PowerFault("Alignment")
+        : PowerFaultBase("Alignment")
     {
     }
 };
 
+
+class PowerInterrupt : public PowerFaultBase
+{
+  public:
+    PowerInterrupt()
+        : PowerFaultBase("Interrupt")
+    {
+    }
+};
+
+
+class DecrementerInterrupt : public PowerInterrupt
+{
+  public:
+    DecrementerInterrupt()
+    {
+    }
+    virtual void invoke(ThreadContext * tc, const StaticInstPtr &inst =
+                        StaticInst::nullStaticInstPtr)
+    {
+      Msr msr = tc->readIntReg(MISCREG_MSR);
+      // Refer Power ISA Manual v3.0B Book-III, section 6.5.11
+      tc->setIntReg(INTREG_SRR0 , tc->instAddr());
+      uint64_t srr1 = msr & 0xffffffff78fc0fff;
+      tc->setIntReg(INTREG_SRR1 , srr1);
+      msr = msr & 0xffffffffffff76cd;
+      tc->setIntReg(INTREG_MSR , msr);
+      tc->pcState(0x900);
+    }
+};
+
 } // namespace PowerISA
 
 #endif // __ARCH_POWER_FAULTS_HH__
index f8995986373d1ef36edbb104f86eb6d571514eeb..40f5c3fcef73f4e798f39ad8244ab2aa53efbeca 100644 (file)
@@ -31,6 +31,8 @@
 #ifndef __ARCH_POWER_INTERRUPT_HH__
 #define __ARCH_POWER_INTERRUPT_HH__
 
+#include "arch/power/faults.hh"
+#include "arch/power/registers.hh"
 #include "base/logging.hh"
 #include "params/PowerInterrupts.hh"
 #include "sim/sim_object.hh"
@@ -44,6 +46,7 @@ class Interrupts : public SimObject
 {
   private:
     BaseCPU * cpu;
+    bool si = false;
 
   public:
     typedef PowerInterruptsParams Params;
@@ -82,22 +85,33 @@ class Interrupts : public SimObject
     }
 
     bool
-    checkInterrupts(ThreadContext *tc) const
+    checkInterrupts(ThreadContext *tc)
     {
-        panic("Interrupts::checkInterrupts not implemented.\n");
+        //panic("Interrupts::checkInterrupts not implemented.\n");
+        if ( tc->readIntReg(INTREG_DEC) == 0) {
+           si = true;
+           return true;
+        }
+        else {
+           tc->setIntReg(INTREG_DEC , tc->readIntReg(INTREG_DEC)-1);
+           return false;
+        }
     }
 
     Fault
     getInterrupt(ThreadContext *tc)
     {
         assert(checkInterrupts(tc));
-        panic("Interrupts::getInterrupt not implemented.\n");
+        if (si)
+        return std::make_shared<DecrementerInterrupt>();
+        else return NoFault;
     }
 
     void
     updateIntrInfo(ThreadContext *tc)
     {
-        panic("Interrupts::updateIntrInfo not implemented.\n");
+        tc->setIntReg(INTREG_DEC , 0xffffffffffffffff);
+        si = false;
     }
 };
 
index c1a3bee3e4cda855b8d449df6aaa793a9c44b222..46ff26f486c5ea5ca6353a4dad8d2dbf7ceb70c5 100644 (file)
@@ -71,5 +71,11 @@ PowerSystem::initState()
     //Sixty Four, little endian,Hypervisor bits are enabled.
     // IR and DR bits are disabled.
     Msr msr = 0x9000000000000001;
+    tc->setIntReg(INTREG_DEC , 0xffffffffffffffff);
+    // This PVR is specific to power9
+    tc->setIntReg(INTREG_PVR , 0x004e1100);
     tc->setIntReg(INTREG_MSR , msr);
+    //ArgumentReg0 is initialized with 0xc00000 because in linux/system.cc
+    //dtb is loaded at 0xc00000
+    tc->setIntReg(ArgumentReg0, 0x1800000);
 }