implement ipi stufff for SPARC
authorAli Saidi <saidi@eecs.umich.edu>
Fri, 9 Mar 2007 21:56:39 +0000 (16:56 -0500)
committerAli Saidi <saidi@eecs.umich.edu>
Fri, 9 Mar 2007 21:56:39 +0000 (16:56 -0500)
src/arch/alpha/utility.hh:
src/arch/mips/utility.hh:
src/arch/sparc/utility.hh:
src/arch/x86/utility.hh:
    add hook for system to startup the cpu or not... in the case of FS sparc, only the first cpu would get spunup.. the rest sit in an idle state until they get an ipi
src/arch/sparc/isa/decoder.isa:
    handle writable bits of strandstatus register in miscregfile
src/arch/sparc/miscregfile.hh:
    some constants for the strand status register
src/arch/sparc/ua2005.cc:
    properly implement the strand status register
src/dev/sparc/iob.cc:
    implement ipi generation properly
src/sim/system.cc:
    call into the ISA to start the CPU (or not)

--HG--
extra : convert_revision : 0003b2032337d8a031a9fc044da726dbb2a9e36f

src/arch/alpha/utility.hh
src/arch/mips/utility.hh
src/arch/sparc/isa/decoder.isa
src/arch/sparc/miscregfile.hh
src/arch/sparc/ua2005.cc
src/arch/sparc/utility.hh
src/arch/x86/utility.hh
src/dev/sparc/iob.cc
src/sim/system.cc

index c8a50e8a2ad5e1bc11433fe64fdf7eb9ad637516..b7844c7ebc0f3dcd97063b1e8a412f9ba924efa9 100644 (file)
@@ -123,6 +123,9 @@ namespace AlphaISA
 
     // Alpha IPR register accessors
     inline bool PcPAL(Addr addr) { return addr & 0x3; }
+    inline void startupCPU(ThreadContext *tc, int cpuId) {
+        tc->activate(0);
+    }
 #if FULL_SYSTEM
 
     ////////////////////////////////////////////////////////////////////////
index 56689ba4d42bc821d966b7df12d13fd3b0e2099e..b5c1e31e19d02f50ea123bdcbd046f5cc2c4080e 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2003-2005 The Regents of The University of Michigan
+ * Copyright (c) 2007 MIPS Technologies, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,6 +28,7 @@
  *
  * Authors: Nathan Binkert
  *          Steve Reinhardt
+ *          Korey Sewell
  */
 
 #ifndef __ARCH_MIPS_UTILITY_HH__
@@ -98,6 +100,11 @@ namespace MipsISA {
         return ExtMachInst(inst);
 #endif
     }
+
+    inline void startupCPU(ThreadContext *tc, int cpuId)
+    {
+        tc->activate(0);
+    }
 };
 
 
index 2e85e1274e45024e6ce37fbd7701e1616a30e605..70afe19b688b461acdf7bf21b5a0e4ef4acc6a6c 100644 (file)
@@ -620,10 +620,6 @@ decode OP default Unknown::unknown()
                 }});
                 0x19: Priv::wrstick_cmpr({{StickCmpr = Rs1 ^ Rs2_or_imm13;}});
                 0x1A: Priv::wrstrand_sts_reg({{
-                    if(Pstate<2:> && !Hpstate<2:>)
-                        StrandStsReg = StrandStsReg<63:1> |
-                                (Rs1 ^ Rs2_or_imm13)<0:>;
-                    else
                         StrandStsReg = Rs1 ^ Rs2_or_imm13;
                 }});
                 //0x1A is supposed to be reserved, but it writes the strand
index 6063c21c8ecfee54ee2cc02712f333fc0b157852..867f959e196948485aa5c6e2a6a89ca66ed89740 100644 (file)
@@ -163,6 +163,23 @@ namespace SparcISA
         const static int ie = 0x2;
     };
 
+    struct STS {
+        const static int st_idle     = 0x00;
+        const static int st_wait     = 0x01;
+        const static int st_halt     = 0x02;
+        const static int st_run      = 0x05;
+        const static int st_spec_run = 0x07;
+        const static int st_spec_rdy = 0x13;
+        const static int st_ready    = 0x19;
+        const static int active      = 0x01;
+        const static int speculative = 0x04;
+        const static int shft_id     = 8;
+        const static int shft_fsm0   = 31;
+        const static int shft_fsm1   = 26;
+        const static int shft_fsm2   = 21;
+        const static int shft_fsm3   = 16;
+    };
+
 
     const int NumMiscArchRegs = MISCREG_NUMMISCREGS;
     const int NumMiscRegs = MISCREG_NUMMISCREGS;
index 6c8a987fea3ab3b6a1cf6fc0e770e848441654da..439f384579540cf3d8c8ba126af8a404959eabfc 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "arch/sparc/kernel_stats.hh"
 #include "arch/sparc/miscregfile.hh"
 #include "base/bitfield.hh"
 #include "base/trace.hh"
 #include "cpu/base.hh"
 #include "cpu/thread_context.hh"
+#include "sim/system.hh"
 
 using namespace SparcISA;
 
@@ -185,10 +187,21 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
 #endif
         break;
       case MISCREG_HTSTATE:
-      case MISCREG_STRAND_STS_REG:
         setRegNoEffect(miscReg, val);
         break;
 
+      case MISCREG_STRAND_STS_REG:
+        if (bits(val,2,2))
+            panic("No support for setting spec_en bit\n");
+        setRegNoEffect(miscReg, bits(val,0,0));
+        if (!bits(val,0,0)) {
+            // Time to go to sleep
+            tc->suspend();
+            if (tc->getKernelStats())
+                tc->getKernelStats()->quiesce();
+            }
+        break;
+
       default:
         panic("Invalid write to FS misc register %s\n", getMiscRegName(miscReg));
     }
@@ -197,6 +210,8 @@ MiscRegFile::setFSReg(int miscReg, const MiscReg &val, ThreadContext *tc)
 MiscReg
 MiscRegFile::readFSReg(int miscReg, ThreadContext * tc)
 {
+    uint64_t temp;
+
     switch (miscReg) {
         /* Privileged registers. */
       case MISCREG_QUEUE_CPU_MONDO_HEAD:
@@ -214,7 +229,6 @@ MiscRegFile::readFSReg(int miscReg, ThreadContext * tc)
       case MISCREG_HPSTATE:
       case MISCREG_HINTP:
       case MISCREG_HTSTATE:
-      case MISCREG_STRAND_STS_REG:
       case MISCREG_HSTICK_CMPR:
         return readRegNoEffect(miscReg) ;
 
@@ -223,6 +237,38 @@ MiscRegFile::readFSReg(int miscReg, ThreadContext * tc)
       case MISCREG_HVER:
         return NWindows | MaxTL << 8 | MaxGL << 16;
 
+      case MISCREG_STRAND_STS_REG:
+        System *sys;
+        int x;
+        sys = tc->getSystemPtr();
+
+        temp = readRegNoEffect(miscReg) & (STS::active | STS::speculative);
+        // Check that the CPU array is fully populated (by calling getNumCPus())
+        assert(sys->getNumCPUs() > tc->readCpuId());
+
+        temp |= tc->readCpuId()  << STS::shft_id;
+
+        for (x = tc->readCpuId() & ~3; x < sys->threadContexts.size(); x++) {
+            switch (sys->threadContexts[x]->status()) {
+              case ThreadContext::Active:
+                temp |= STS::st_run << (STS::shft_fsm0 -
+                        ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
+                break;
+              case ThreadContext::Suspended:
+                // should this be idle?
+                temp |= STS::st_idle << (STS::shft_fsm0 -
+                        ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
+                break;
+              case ThreadContext::Halted:
+                temp |= STS::st_halt << (STS::shft_fsm0 -
+                        ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1)));
+                break;
+              default:
+                panic("What state are we in?!\n");
+            } // switch
+        } // for
+
+        return temp;
       default:
         panic("Invalid read to FS misc register\n");
     }
index 64b91695ecbc9405296ca558635c778bd09553ac..dc9201401cdefea059f5b8bee070f4f6027f7e75 100644 (file)
@@ -112,7 +112,20 @@ namespace SparcISA
     inline void initCPU(ThreadContext *tc, int cpuId)
     {
         static Fault por = new PowerOnReset();
-        por->invoke(tc);
+        if (cpuId == 0)
+            por->invoke(tc);
+
+    }
+
+    inline void startupCPU(ThreadContext *tc, int cpuId)
+    {
+#if FULL_SYSTEM
+        // Other CPUs will get activated by IPIs
+        if (cpuId == 0)
+            tc->activate(0);
+#else
+        tc->activate(0);
+#endif
     }
 
 } // namespace SparcISA
index 1d9d8d3d52c69eac70c5d397282cb94769bda766..1fbe1fffe6ff40403b609569d4ad70f11bc21832 100644 (file)
@@ -126,6 +126,11 @@ namespace X86ISA
     {
         panic("initCPU not implemented!\n");
     }
+
+    inline void startupCPU(ThreadContext *tc, int cpuId)
+    {
+        tc->activate(0);
+    }
 };
 
 #endif // __ARCH_X86_UTILITY_HH__
index 2cff02a995a9894a90b3abd87ff8295d66718f5a..6bd40b631d70a64b0bfee1b9c8b0fc875346cc86 100644 (file)
@@ -38,6 +38,7 @@
 #include <cstring>
 
 #include "arch/sparc/isa_traits.hh"
+#include "arch/sparc/faults.hh"
 #include "base/trace.hh"
 #include "cpu/intr_control.hh"
 #include "dev/sparc/iob.hh"
@@ -45,6 +46,7 @@
 #include "mem/port.hh"
 #include "mem/packet_access.hh"
 #include "sim/builder.hh"
+#include "sim/faults.hh"
 #include "sim/system.hh"
 
 Iob::Iob(Params *p)
@@ -261,13 +263,30 @@ Iob::receiveDeviceInterrupt(DeviceId devid)
 void
 Iob::generateIpi(Type type, int cpu_id, int vector)
 {
-    // Only handle interrupts for the moment... Cpu Idle/reset/resume will be
-    // later
-    if (type != 0)
+    SparcISA::SparcFault<SparcISA::PowerOnReset> *por = new SparcISA::PowerOnReset();
+    if (cpu_id >= sys->getNumCPUs())
         return;
 
-    assert(type == 0);
-    ic->post(cpu_id, SparcISA::IT_INT_VEC, vector);
+    switch (type) {
+      case 0: // interrupt
+        ic->post(cpu_id, SparcISA::IT_INT_VEC, vector);
+        break;
+      case 1: // reset
+        warn("Sending reset to CPU: %d\n", cpu_id);
+        if (vector != por->trapType())
+            panic("Don't know how to set non-POR reset to cpu\n");
+        por->invoke(sys->threadContexts[cpu_id]);
+        sys->threadContexts[cpu_id]->activate();
+        break;
+      case 2: // idle -- this means stop executing and don't wake on interrupts
+        sys->threadContexts[cpu_id]->halt();
+        break;
+      case 3: // resume
+        sys->threadContexts[cpu_id]->activate();
+        break;
+      default:
+        panic("Invalid type to generate ipi\n");
+    }
 }
 
 bool
index 1a87e1754f0020e4d84d70665a6b79ea2f4a9c8a..2d0eaaf5bd93993770c5e64c9a4fcb5e74e5fd06 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "arch/isa_traits.hh"
 #include "arch/remote_gdb.hh"
+#include "arch/utility.hh"
 #include "base/loader/object_file.hh"
 #include "base/loader/symtab.hh"
 #include "base/trace.hh"
@@ -203,7 +204,7 @@ System::startup()
 {
     int i;
     for (i = 0; i < threadContexts.size(); i++)
-        threadContexts[i]->activate(0);
+        TheISA::startupCPU(threadContexts[i], i);
 }
 
 void