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)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sun, 24 Jan 2021 03:52:31 +0000 (03:52 +0000)
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 e20ef8eb538e2c27222c39d1632b37acad6b9d64..9667639f290a6fc5eaa9bf57e7fbfd9c1a50e40e 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)
     {
     }
@@ -53,35 +54,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 29e665cae82dca256a1d13cea1f531edcedc7f89..ead82dd7006f7e8b45688006ed8c82f52c5d9daa 100644 (file)
@@ -30,6 +30,8 @@
 #define __ARCH_POWER_INTERRUPT_HH__
 
 #include "arch/generic/interrupts.hh"
+#include "arch/power/faults.hh"
+#include "arch/power/registers.hh"
 #include "base/logging.hh"
 #include "params/PowerInterrupts.hh"
 
@@ -40,6 +42,10 @@ namespace PowerISA {
 
 class Interrupts : public BaseInterrupts
 {
+  private:
+    BaseCPU * cpu;
+    bool si = false;
+
   public:
     typedef PowerInterruptsParams Params;
 
@@ -70,22 +76,33 @@ class Interrupts : public BaseInterrupts
     }
 
     bool
-    checkInterrupts() 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()
     {
-        assert(checkInterrupts());
-        panic("Interrupts::getInterrupt not implemented.\n");
+        assert(checkInterrupts(tc));
+        if (si)
+        return std::make_shared<DecrementerInterrupt>();
+        else return NoFault;
     }
 
     void
     updateIntrInfo()
     {
-        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);
 }