thread_context_impl.hh revision 8232
1/*
2 * Copyright (c) 2010 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2004-2006 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Kevin Lim
41 *          Korey Sewell
42 */
43
44#include "arch/registers.hh"
45#include "config/the_isa.hh"
46#include "cpu/o3/thread_context.hh"
47#include "cpu/quiesce_event.hh"
48#include "debug/O3CPU.hh"
49
50#if FULL_SYSTEM
51template <class Impl>
52VirtualPort *
53O3ThreadContext<Impl>::getVirtPort()
54{
55    return thread->getVirtPort();
56}
57
58template <class Impl>
59void
60O3ThreadContext<Impl>::dumpFuncProfile()
61{
62    thread->dumpFuncProfile();
63}
64#endif
65
66template <class Impl>
67void
68O3ThreadContext<Impl>::takeOverFrom(ThreadContext *old_context)
69{
70    // some things should already be set up
71#if FULL_SYSTEM
72    assert(getSystemPtr() == old_context->getSystemPtr());
73#else
74    assert(getProcessPtr() == old_context->getProcessPtr());
75#endif
76
77    // copy over functional state
78    setStatus(old_context->status());
79    copyArchRegs(old_context);
80    setContextId(old_context->contextId());
81    setThreadId(old_context->threadId());
82
83#if !FULL_SYSTEM
84    thread->funcExeInst = old_context->readFuncExeInst();
85#else
86    EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
87    if (other_quiesce) {
88        // Point the quiesce event's TC at this TC so that it wakes up
89        // the proper CPU.
90        other_quiesce->tc = this;
91    }
92    if (thread->quiesceEvent) {
93        thread->quiesceEvent->tc = this;
94    }
95
96    // Transfer kernel stats from one CPU to the other.
97    thread->kernelStats = old_context->getKernelStats();
98//    storeCondFailures = 0;
99    cpu->lockFlag = false;
100#endif
101
102    old_context->setStatus(ThreadContext::Halted);
103
104    thread->inSyscall = false;
105    thread->trapPending = false;
106}
107
108template <class Impl>
109void
110O3ThreadContext<Impl>::activate(int delay)
111{
112    DPRINTF(O3CPU, "Calling activate on Thread Context %d\n",
113            threadId());
114
115    if (thread->status() == ThreadContext::Active)
116        return;
117
118#if FULL_SYSTEM
119    thread->lastActivate = curTick();
120#endif
121
122    thread->setStatus(ThreadContext::Active);
123
124    // status() == Suspended
125    cpu->activateContext(thread->threadId(), delay);
126}
127
128template <class Impl>
129void
130O3ThreadContext<Impl>::suspend(int delay)
131{
132    DPRINTF(O3CPU, "Calling suspend on Thread Context %d\n",
133            threadId());
134
135    if (thread->status() == ThreadContext::Suspended)
136        return;
137
138#if FULL_SYSTEM
139    thread->lastActivate = curTick();
140    thread->lastSuspend = curTick();
141#endif
142/*
143#if FULL_SYSTEM
144    // Don't change the status from active if there are pending interrupts
145    if (cpu->checkInterrupts()) {
146        assert(status() == ThreadContext::Active);
147        return;
148    }
149#endif
150*/
151    thread->setStatus(ThreadContext::Suspended);
152    cpu->suspendContext(thread->threadId());
153}
154
155template <class Impl>
156void
157O3ThreadContext<Impl>::halt(int delay)
158{
159    DPRINTF(O3CPU, "Calling halt on Thread Context %d\n",
160            threadId());
161
162    if (thread->status() == ThreadContext::Halted)
163        return;
164
165    thread->setStatus(ThreadContext::Halted);
166    cpu->haltContext(thread->threadId());
167}
168
169template <class Impl>
170void
171O3ThreadContext<Impl>::regStats(const std::string &name)
172{
173#if FULL_SYSTEM
174    thread->kernelStats = new TheISA::Kernel::Statistics(cpu->system);
175    thread->kernelStats->regStats(name + ".kern");
176#endif
177}
178
179template <class Impl>
180void
181O3ThreadContext<Impl>::serialize(std::ostream &os)
182{
183#if FULL_SYSTEM
184    if (thread->kernelStats)
185        thread->kernelStats->serialize(os);
186#endif
187
188}
189
190template <class Impl>
191void
192O3ThreadContext<Impl>::unserialize(Checkpoint *cp, const std::string &section)
193{
194#if FULL_SYSTEM
195    if (thread->kernelStats)
196        thread->kernelStats->unserialize(cp, section);
197#endif
198
199}
200
201#if FULL_SYSTEM
202template <class Impl>
203Tick
204O3ThreadContext<Impl>::readLastActivate()
205{
206    return thread->lastActivate;
207}
208
209template <class Impl>
210Tick
211O3ThreadContext<Impl>::readLastSuspend()
212{
213    return thread->lastSuspend;
214}
215
216template <class Impl>
217void
218O3ThreadContext<Impl>::profileClear()
219{
220    thread->profileClear();
221}
222
223template <class Impl>
224void
225O3ThreadContext<Impl>::profileSample()
226{
227    thread->profileSample();
228}
229#endif
230
231template <class Impl>
232void
233O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc)
234{
235    // Prevent squashing
236    thread->inSyscall = true;
237    TheISA::copyRegs(tc, this);
238    thread->inSyscall = false;
239
240#if !FULL_SYSTEM
241    this->thread->funcExeInst = tc->readFuncExeInst();
242#endif
243}
244
245template <class Impl>
246void
247O3ThreadContext<Impl>::clearArchRegs()
248{
249    cpu->isa[thread->threadId()].clear();
250}
251
252template <class Impl>
253uint64_t
254O3ThreadContext<Impl>::readIntReg(int reg_idx)
255{
256    reg_idx = cpu->isa[thread->threadId()].flattenIntIndex(reg_idx);
257    return cpu->readArchIntReg(reg_idx, thread->threadId());
258}
259
260template <class Impl>
261TheISA::FloatReg
262O3ThreadContext<Impl>::readFloatReg(int reg_idx)
263{
264    reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx);
265    return cpu->readArchFloatReg(reg_idx, thread->threadId());
266}
267
268template <class Impl>
269TheISA::FloatRegBits
270O3ThreadContext<Impl>::readFloatRegBits(int reg_idx)
271{
272    reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx);
273    return cpu->readArchFloatRegInt(reg_idx, thread->threadId());
274}
275
276template <class Impl>
277void
278O3ThreadContext<Impl>::setIntReg(int reg_idx, uint64_t val)
279{
280    reg_idx = cpu->isa[thread->threadId()].flattenIntIndex(reg_idx);
281    cpu->setArchIntReg(reg_idx, val, thread->threadId());
282
283    // Squash if we're not already in a state update mode.
284    if (!thread->trapPending && !thread->inSyscall) {
285        cpu->squashFromTC(thread->threadId());
286    }
287}
288
289template <class Impl>
290void
291O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val)
292{
293    reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx);
294    cpu->setArchFloatReg(reg_idx, val, thread->threadId());
295
296    if (!thread->trapPending && !thread->inSyscall) {
297        cpu->squashFromTC(thread->threadId());
298    }
299}
300
301template <class Impl>
302void
303O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
304{
305    reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx);
306    cpu->setArchFloatRegInt(reg_idx, val, thread->threadId());
307
308    // Squash if we're not already in a state update mode.
309    if (!thread->trapPending && !thread->inSyscall) {
310        cpu->squashFromTC(thread->threadId());
311    }
312}
313
314template <class Impl>
315void
316O3ThreadContext<Impl>::pcState(const TheISA::PCState &val)
317{
318    cpu->pcState(val, thread->threadId());
319
320    // Squash if we're not already in a state update mode.
321    if (!thread->trapPending && !thread->inSyscall) {
322        cpu->squashFromTC(thread->threadId());
323    }
324}
325
326template <class Impl>
327int
328O3ThreadContext<Impl>::flattenIntIndex(int reg)
329{
330    return cpu->isa[thread->threadId()].flattenIntIndex(reg);
331}
332
333template <class Impl>
334int
335O3ThreadContext<Impl>::flattenFloatIndex(int reg)
336{
337    return cpu->isa[thread->threadId()].flattenFloatIndex(reg);
338}
339
340template <class Impl>
341void
342O3ThreadContext<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val)
343{
344    cpu->setMiscRegNoEffect(misc_reg, val, thread->threadId());
345
346    // Squash if we're not already in a state update mode.
347    if (!thread->trapPending && !thread->inSyscall) {
348        cpu->squashFromTC(thread->threadId());
349    }
350}
351
352template <class Impl>
353void
354O3ThreadContext<Impl>::setMiscReg(int misc_reg,
355                                                const MiscReg &val)
356{
357    cpu->setMiscReg(misc_reg, val, thread->threadId());
358
359    // Squash if we're not already in a state update mode.
360    if (!thread->trapPending && !thread->inSyscall) {
361        cpu->squashFromTC(thread->threadId());
362    }
363}
364
365