cpu.cc revision 8793:5f25086326ac
1/*
2 * Copyright (c) 2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Kevin Lim
29 */
30
31#include <list>
32#include <string>
33
34#include "arch/kernel_stats.hh"
35#include "arch/vtophys.hh"
36#include "cpu/checker/cpu.hh"
37#include "cpu/base.hh"
38#include "cpu/simple_thread.hh"
39#include "cpu/static_inst.hh"
40#include "cpu/thread_context.hh"
41
42using namespace std;
43//The CheckerCPU does alpha only
44using namespace AlphaISA;
45
46void
47CheckerCPU::init()
48{
49}
50
51CheckerCPU::CheckerCPU(Params *p)
52    : BaseCPU(p), thread(NULL), tc(NULL)
53{
54    memReq = NULL;
55
56    numInst = 0;
57    startNumInst = 0;
58    numLoad = 0;
59    startNumLoad = 0;
60    youngestSN = 0;
61
62    changedPC = willChangePC = changedNextPC = false;
63
64    exitOnError = p->exitOnError;
65    warnOnlyOnLoadError = p->warnOnlyOnLoadError;
66    itb = p->itb;
67    dtb = p->dtb;
68    systemPtr = NULL;
69    process = p->process;
70    thread = new SimpleThread(this, /* thread_num */ 0, process);
71
72    tc = thread->getTC();
73    threadContexts.push_back(tc);
74
75    result.integer = 0;
76}
77
78CheckerCPU::~CheckerCPU()
79{
80}
81
82void
83CheckerCPU::setSystem(System *system)
84{
85    systemPtr = system;
86
87    thread = new SimpleThread(this, 0, systemPtr, itb, dtb, false);
88
89    tc = thread->getTC();
90    threadContexts.push_back(tc);
91    delete thread->kernelStats;
92    thread->kernelStats = NULL;
93}
94
95void
96CheckerCPU::setIcachePort(Port *icache_port)
97{
98    icachePort = icache_port;
99}
100
101void
102CheckerCPU::setDcachePort(Port *dcache_port)
103{
104    dcachePort = dcache_port;
105}
106
107void
108CheckerCPU::serialize(ostream &os)
109{
110/*
111    BaseCPU::serialize(os);
112    SERIALIZE_SCALAR(inst);
113    nameOut(os, csprintf("%s.xc", name()));
114    thread->serialize(os);
115    cacheCompletionEvent.serialize(os);
116*/
117}
118
119void
120CheckerCPU::unserialize(Checkpoint *cp, const string &section)
121{
122/*
123    BaseCPU::unserialize(cp, section);
124    UNSERIALIZE_SCALAR(inst);
125    thread->unserialize(cp, csprintf("%s.xc", section));
126*/
127}
128
129template <class T>
130Fault
131CheckerCPU::read(Addr addr, T &data, unsigned flags)
132{
133    // need to fill in CPU & thread IDs here
134    memReq = new Request();
135
136    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
137
138    // translate to physical address
139    dtb->translateAtomic(memReq, tc, false);
140
141    PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
142
143    pkt->dataStatic(&data);
144
145    if (!(memReq->isUncacheable())) {
146        // Access memory to see if we have the same data
147        dcachePort->sendFunctional(pkt);
148    } else {
149        // Assume the data is correct if it's an uncached access
150        memcpy(&data, &unverifiedResult.integer, sizeof(T));
151    }
152
153    delete pkt;
154
155    return NoFault;
156}
157
158#ifndef DOXYGEN_SHOULD_SKIP_THIS
159
160template
161Fault
162CheckerCPU::read(Addr addr, uint64_t &data, unsigned flags);
163
164template
165Fault
166CheckerCPU::read(Addr addr, uint32_t &data, unsigned flags);
167
168template
169Fault
170CheckerCPU::read(Addr addr, uint16_t &data, unsigned flags);
171
172template
173Fault
174CheckerCPU::read(Addr addr, uint8_t &data, unsigned flags);
175
176#endif //DOXYGEN_SHOULD_SKIP_THIS
177
178template<>
179Fault
180CheckerCPU::read(Addr addr, double &data, unsigned flags)
181{
182    return read(addr, *(uint64_t*)&data, flags);
183}
184
185template<>
186Fault
187CheckerCPU::read(Addr addr, float &data, unsigned flags)
188{
189    return read(addr, *(uint32_t*)&data, flags);
190}
191
192template<>
193Fault
194CheckerCPU::read(Addr addr, int32_t &data, unsigned flags)
195{
196    return read(addr, (uint32_t&)data, flags);
197}
198
199template <class T>
200Fault
201CheckerCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
202{
203    // need to fill in CPU & thread IDs here
204    memReq = new Request();
205
206    memReq->setVirt(0, addr, sizeof(T), flags, thread->readPC());
207
208    // translate to physical address
209    dtb->translateAtomic(memReq, tc, true);
210
211    // Can compare the write data and result only if it's cacheable,
212    // not a store conditional, or is a store conditional that
213    // succeeded.
214    // @todo: Verify that actual memory matches up with these values.
215    // Right now it only verifies that the instruction data is the
216    // same as what was in the request that got sent to memory; there
217    // is no verification that it is the same as what is in memory.
218    // This is because the LSQ would have to be snooped in the CPU to
219    // verify this data.
220    if (unverifiedReq &&
221        !(unverifiedReq->isUncacheable()) &&
222        (!(unverifiedReq->isLLSC()) ||
223         ((unverifiedReq->isLLSC()) &&
224          unverifiedReq->getExtraData() == 1))) {
225        T inst_data;
226/*
227        // This code would work if the LSQ allowed for snooping.
228        PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast);
229        pkt.dataStatic(&inst_data);
230
231        dcachePort->sendFunctional(pkt);
232
233        delete pkt;
234*/
235        memcpy(&inst_data, unverifiedMemData, sizeof(T));
236
237        if (data != inst_data) {
238            warn("%lli: Store value does not match value in memory! "
239                 "Instruction: %#x, memory: %#x",
240                 curTick(), inst_data, data);
241            handleError();
242        }
243    }
244
245    // Assume the result was the same as the one passed in.  This checker
246    // doesn't check if the SC should succeed or fail, it just checks the
247    // value.
248    if (res && unverifiedReq->scResultValid())
249        *res = unverifiedReq->getExtraData();
250
251    return NoFault;
252}
253
254
255#ifndef DOXYGEN_SHOULD_SKIP_THIS
256template
257Fault
258CheckerCPU::write(uint64_t data, Addr addr, unsigned flags, uint64_t *res);
259
260template
261Fault
262CheckerCPU::write(uint32_t data, Addr addr, unsigned flags, uint64_t *res);
263
264template
265Fault
266CheckerCPU::write(uint16_t data, Addr addr, unsigned flags, uint64_t *res);
267
268template
269Fault
270CheckerCPU::write(uint8_t data, Addr addr, unsigned flags, uint64_t *res);
271
272#endif //DOXYGEN_SHOULD_SKIP_THIS
273
274template<>
275Fault
276CheckerCPU::write(double data, Addr addr, unsigned flags, uint64_t *res)
277{
278    return write(*(uint64_t*)&data, addr, flags, res);
279}
280
281template<>
282Fault
283CheckerCPU::write(float data, Addr addr, unsigned flags, uint64_t *res)
284{
285    return write(*(uint32_t*)&data, addr, flags, res);
286}
287
288template<>
289Fault
290CheckerCPU::write(int32_t data, Addr addr, unsigned flags, uint64_t *res)
291{
292    return write((uint32_t)data, addr, flags, res);
293}
294
295
296Addr
297CheckerCPU::dbg_vtophys(Addr addr)
298{
299    return vtophys(tc, addr);
300}
301
302bool
303CheckerCPU::checkFlags(Request *req)
304{
305    // Remove any dynamic flags that don't have to do with the request itself.
306    unsigned flags = unverifiedReq->getFlags();
307    unsigned mask = LOCKED | PHYSICAL | VPTE | ALTMODE | UNCACHEABLE | PREFETCH;
308    flags = flags & (mask);
309    if (flags == req->getFlags()) {
310        return false;
311    } else {
312        return true;
313    }
314}
315
316void
317CheckerCPU::dumpAndExit()
318{
319    warn("%lli: Checker PC:%#x, next PC:%#x",
320         curTick(), thread->readPC(), thread->readNextPC());
321    panic("Checker found an error!");
322}
323