X86: Implement the sysret instruction in long mode.
[gem5.git] / src / cpu / base.cc
index 1ca0dc14b8f4d9b704302ea2d1878dc8b744a96f..0ef206d901a8766b85a14d030c2433976c6c2994 100644 (file)
@@ -94,21 +94,29 @@ CPUProgressEvent::description() const
 
 #if FULL_SYSTEM
 BaseCPU::BaseCPU(Params *p)
-    : MemObject(p), clock(p->clock), instCnt(0),
+    : MemObject(p), clock(p->clock), instCnt(0), _cpuId(p->cpu_id),
+      interrupts(p->interrupts),
       number_of_threads(p->numThreads), system(p->system),
       phase(p->phase)
 #else
 BaseCPU::BaseCPU(Params *p)
-    : MemObject(p), clock(p->clock),
+    : MemObject(p), clock(p->clock), _cpuId(p->cpu_id),
       number_of_threads(p->numThreads), system(p->system),
       phase(p->phase)
 #endif
 {
 //    currentTick = curTick;
 
+    // if Python did not provide a valid ID, do it here
+    if (_cpuId == -1 ) {
+        _cpuId = cpuList.size();
+    }
+
     // add self to global list of CPUs
     cpuList.push_back(this);
 
+    DPRINTF(SyscallVerbose, "Constructing CPU with id %d\n", _cpuId);
+
     if (number_of_threads > maxThreadsPerCPU)
         maxThreadsPerCPU = number_of_threads;
 
@@ -186,6 +194,8 @@ BaseCPU::BaseCPU(Params *p)
         }
     }
 #if FULL_SYSTEM
+    interrupts->setCPU(this);
+
     profileEvent = NULL;
     if (params()->profile)
         profileEvent = new ProfileEvent(this, params()->profile);
@@ -277,14 +287,19 @@ BaseCPU::registerThreadContexts()
     for (int i = 0; i < threadContexts.size(); ++i) {
         ThreadContext *tc = threadContexts[i];
 
-#if FULL_SYSTEM
-        int id = params()->cpu_id;
-        if (id != -1)
-            id += i;
-
-        tc->setCpuId(system->registerThreadContext(tc, id));
-#else
-        tc->setCpuId(tc->getProcessPtr()->registerThreadContext(tc));
+        /** This is so that contextId and cpuId match where there is a
+         * 1cpu:1context relationship.  Otherwise, the order of registration
+         * could affect the assignment and cpu 1 could have context id 3, for
+         * example.  We may even want to do something like this for SMT so that
+         * cpu 0 has the lowest thread contexts and cpu N has the highest, but
+         * I'll just do this for now
+         */
+        if (number_of_threads == 1)
+            tc->setContextId(system->registerThreadContext(tc, _cpuId));
+        else
+            tc->setContextId(system->registerThreadContext(tc));
+#if !FULL_SYSTEM
+        tc->getProcessPtr()->assignThreadContext(tc->contextId());
 #endif
     }
 }
@@ -315,6 +330,8 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc)
 {
     assert(threadContexts.size() == oldCPU->threadContexts.size());
 
+    _cpuId = oldCPU->cpuId();
+
     for (int i = 0; i < threadContexts.size(); ++i) {
         ThreadContext *newTC = threadContexts[i];
         ThreadContext *oldTC = oldCPU->threadContexts[i];
@@ -323,20 +340,21 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc)
 
         CpuEvent::replaceThreadContext(oldTC, newTC);
 
-        assert(newTC->readCpuId() == oldTC->readCpuId());
-#if FULL_SYSTEM
-        system->replaceThreadContext(newTC, newTC->readCpuId());
-#else
-        assert(newTC->getProcessPtr() == oldTC->getProcessPtr());
-        newTC->getProcessPtr()->replaceThreadContext(newTC, newTC->readCpuId());
-#endif
+        assert(newTC->contextId() == oldTC->contextId());
+        assert(newTC->threadId() == oldTC->threadId());
+        system->replaceThreadContext(newTC, newTC->contextId());
 
-        if (DTRACE(Context))
+        /* This code no longer works since the zero register (e.g.,
+         * r31 on Alpha) doesn't necessarily contain zero at this
+         * point.
+           if (DTRACE(Context))
             ThreadContext::compare(oldTC, newTC);
+        */
     }
 
 #if FULL_SYSTEM
     interrupts = oldCPU->interrupts;
+    interrupts->setCPU(this);
 
     for (int i = 0; i < threadContexts.size(); ++i)
         threadContexts[i]->profileClear();
@@ -378,36 +396,18 @@ BaseCPU::ProfileEvent::process()
     cpu->schedule(this, curTick + interval);
 }
 
-void
-BaseCPU::post_interrupt(int int_num, int index)
-{
-    interrupts.post(int_num, index);
-}
-
-void
-BaseCPU::clear_interrupt(int int_num, int index)
-{
-    interrupts.clear(int_num, index);
-}
-
-void
-BaseCPU::clear_interrupts()
-{
-    interrupts.clear_all();
-}
-
 void
 BaseCPU::serialize(std::ostream &os)
 {
     SERIALIZE_SCALAR(instCnt);
-    interrupts.serialize(os);
+    interrupts->serialize(os);
 }
 
 void
 BaseCPU::unserialize(Checkpoint *cp, const std::string &section)
 {
     UNSERIALIZE_SCALAR(instCnt);
-    interrupts.unserialize(cp, section);
+    interrupts->unserialize(cp, section);
 }
 
 #endif // FULL_SYSTEM