gem5  v21.2.0.0
cpu.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011,2013,2017-2018, 2020 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) 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 
41 #include "cpu/checker/cpu.hh"
42 
43 #include <list>
44 #include <string>
45 
46 #include "arch/generic/tlb.hh"
47 #include "cpu/base.hh"
48 #include "cpu/simple_thread.hh"
49 #include "cpu/static_inst.hh"
50 #include "cpu/thread_context.hh"
51 #include "cpu/utils.hh"
52 #include "params/CheckerCPU.hh"
53 #include "sim/full_system.hh"
54 
55 namespace gem5
56 {
57 
58 void
60 {
63 }
64 
65 CheckerCPU::CheckerCPU(const Params &p)
66  : BaseCPU(p, true),
67  zeroReg(params().isa[0]->regClasses().at(IntRegClass).zeroReg()),
68  systemPtr(NULL), icachePort(NULL), dcachePort(NULL),
69  tc(NULL), thread(NULL),
70  unverifiedReq(nullptr),
71  unverifiedMemData(nullptr)
72 {
73  curStaticInst = NULL;
74  curMacroStaticInst = NULL;
75 
76  numInst = 0;
77  startNumInst = 0;
78  numLoad = 0;
79  startNumLoad = 0;
80  youngestSN = 0;
81 
82  changedPC = willChangePC = false;
83 
84  exitOnError = p.exitOnError;
85  warnOnlyOnLoadError = p.warnOnlyOnLoadError;
86  mmu = p.mmu;
87  workload = p.workload;
88 
89  updateOnError = true;
90 }
91 
93 {
94 }
95 
96 void
98 {
99  const Params &p = params();
100 
101  systemPtr = system;
102 
103  if (FullSystem) {
104  thread = new SimpleThread(this, 0, systemPtr, mmu, p.isa[0],
105  p.decoder[0]);
106  } else {
107  thread = new SimpleThread(this, 0, systemPtr,
108  workload.size() ? workload[0] : NULL,
109  mmu, p.isa[0], p.decoder[0]);
110  }
111 
112  tc = thread->getTC();
113  threadContexts.push_back(tc);
114  // Thread should never be null after this
115  assert(thread != NULL);
116 }
117 
118 void
120 {
121  icachePort = icache_port;
122 }
123 
124 void
126 {
127  dcachePort = dcache_port;
128 }
129 
130 void
131 CheckerCPU::serialize(std::ostream &os) const
132 {
133 }
134 
135 void
137 {
138 }
139 
142  Request::Flags flags,
143  const std::vector<bool>& byte_enable,
144  int& frag_size, int& size_left) const
145 {
146  frag_size = std::min(
147  cacheLineSize() - addrBlockOffset(frag_addr, cacheLineSize()),
148  (Addr) size_left);
149  size_left -= frag_size;
150 
151  RequestPtr mem_req;
152 
153  // Set up byte-enable mask for the current fragment
154  auto it_start = byte_enable.cbegin() + (size - (frag_size +
155  size_left));
156  auto it_end = byte_enable.cbegin() + (size - size_left);
157  if (isAnyActiveElement(it_start, it_end)) {
158  mem_req = std::make_shared<Request>(frag_addr, frag_size,
159  flags, requestorId, thread->pcState().instAddr(),
160  tc->contextId());
161  mem_req->setByteEnable(std::vector<bool>(it_start, it_end));
162  }
163 
164  return mem_req;
165 }
166 
167 Fault
168 CheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size,
169  Request::Flags flags,
170  const std::vector<bool>& byte_enable)
171 {
172  assert(byte_enable.size() == size);
173 
174  Fault fault = NoFault;
175  bool checked_flags = false;
176  bool flags_match = true;
177  Addr pAddr = 0x0;
178 
179  Addr frag_addr = addr;
180  int frag_size = 0;
181  int size_left = size;
182  bool predicate;
183 
184  // Need to account for multiple accesses like the Atomic and TimingSimple
185  while (1) {
186  RequestPtr mem_req = genMemFragmentRequest(frag_addr, size, flags,
187  byte_enable, frag_size,
188  size_left);
189 
190  predicate = (mem_req != nullptr);
191 
192  // translate to physical address
193  if (predicate) {
194  fault = mmu->translateFunctional(mem_req, tc, BaseMMU::Read);
195  }
196 
197  if (predicate && !checked_flags && fault == NoFault && unverifiedReq) {
198  flags_match = checkFlags(unverifiedReq, mem_req->getVaddr(),
199  mem_req->getPaddr(), mem_req->getFlags());
200  pAddr = mem_req->getPaddr();
201  checked_flags = true;
202  }
203 
204  // Now do the access
205  if (predicate && fault == NoFault &&
206  !mem_req->getFlags().isSet(Request::NO_ACCESS)) {
207  PacketPtr pkt = Packet::createRead(mem_req);
208 
209  pkt->dataStatic(data);
210 
211  if (!(mem_req->isUncacheable() || mem_req->isLocalAccess())) {
212  // Access memory to see if we have the same data
214  } else {
215  // Assume the data is correct if it's an uncached access
216  memcpy(data, unverifiedMemData, frag_size);
217  }
218 
219  delete pkt;
220  }
221 
222  if (fault != NoFault) {
223  if (mem_req->isPrefetch()) {
224  fault = NoFault;
225  }
226  break;
227  }
228 
229  //If we don't need to access a second cache line, stop now.
230  if (size_left == 0)
231  {
232  break;
233  }
234 
235  // Setup for accessing next cache line
236  frag_addr += frag_size;
237  data += frag_size;
238  unverifiedMemData += frag_size;
239  }
240 
241  if (!flags_match) {
242  warn("%lli: Flags do not match CPU:%#x %#x %#x Checker:%#x %#x %#x\n",
243  curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(),
244  unverifiedReq->getFlags(), frag_addr, pAddr, flags);
245  handleError();
246  }
247 
248  return fault;
249 }
250 
251 Fault
252 CheckerCPU::writeMem(uint8_t *data, unsigned size,
253  Addr addr, Request::Flags flags, uint64_t *res,
254  const std::vector<bool>& byte_enable)
255 {
256  assert(byte_enable.size() == size);
257 
258  Fault fault = NoFault;
259  bool checked_flags = false;
260  bool flags_match = true;
261  Addr pAddr = 0x0;
262  static uint8_t zero_data[64] = {};
263 
264  Addr frag_addr = addr;
265  int frag_size = 0;
266  int size_left = size;
267  bool predicate;
268 
269  // Need to account for a multiple access like Atomic and Timing CPUs
270  while (1) {
271  RequestPtr mem_req = genMemFragmentRequest(frag_addr, size, flags,
272  byte_enable, frag_size,
273  size_left);
274 
275  predicate = (mem_req != nullptr);
276 
277  if (predicate) {
278  fault = mmu->translateFunctional(mem_req, tc, BaseMMU::Write);
279  }
280 
281  if (predicate && !checked_flags && fault == NoFault && unverifiedReq) {
282  flags_match = checkFlags(unverifiedReq, mem_req->getVaddr(),
283  mem_req->getPaddr(), mem_req->getFlags());
284  pAddr = mem_req->getPaddr();
285  checked_flags = true;
286  }
287 
288  /*
289  * We don't actually check memory for the store because there
290  * is no guarantee it has left the lsq yet, and therefore we
291  * can't verify the memory on stores without lsq snooping
292  * enabled. This is left as future work for the Checker: LSQ snooping
293  * and memory validation after stores have committed.
294  */
295  bool was_prefetch = mem_req->isPrefetch();
296 
297  //If we don't need to access a second cache line, stop now.
298  if (fault != NoFault || size_left == 0)
299  {
300  if (fault != NoFault && was_prefetch) {
301  fault = NoFault;
302  }
303  break;
304  }
305 
306  frag_addr += frag_size;
307  }
308 
309  if (!flags_match) {
310  warn("%lli: Flags do not match CPU:%#x %#x Checker:%#x %#x %#x\n",
311  curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(),
312  unverifiedReq->getFlags(), frag_addr, pAddr, flags);
313  handleError();
314  }
315 
316  // Assume the result was the same as the one passed in. This checker
317  // doesn't check if the SC should succeed or fail, it just checks the
318  // value.
319  if (unverifiedReq && res && unverifiedReq->extraDataValid())
320  *res = unverifiedReq->getExtraData();
321 
322  // Entire purpose here is to make sure we are getting the
323  // same data to send to the mem system as the CPU did.
324  // Cannot check this is actually what went to memory because
325  // there stores can be in ld/st queue or coherent operations
326  // overwriting values.
327  bool extraData = false;
328  if (unverifiedReq) {
329  extraData = unverifiedReq->extraDataValid() ?
330  unverifiedReq->getExtraData() : true;
331  }
332 
333  // If the request is to ZERO a cache block, there is no data to check
334  // against, but it's all zero. We need something to compare to, so use a
335  // const set of zeros.
336  if (flags & Request::STORE_NO_DATA) {
337  assert(!data);
338  assert(sizeof(zero_data) <= size);
339  data = zero_data;
340  }
341 
343  memcmp(data, unverifiedMemData, size) && extraData) {
344  warn("%lli: Store value does not match value sent to memory! "
345  "data: %#x inst_data: %#x", curTick(), data,
347  handleError();
348  }
349 
350  return fault;
351 }
352 
356 bool
357 CheckerCPU::checkFlags(const RequestPtr &unverified_req, Addr vAddr,
358  Addr pAddr, int flags)
359 {
360  Addr unverifiedVAddr = unverified_req->getVaddr();
361  Addr unverifiedPAddr = unverified_req->getPaddr();
362  int unverifiedFlags = unverified_req->getFlags();
363 
364  if (unverifiedVAddr != vAddr ||
365  unverifiedPAddr != pAddr ||
366  unverifiedFlags != flags) {
367  return false;
368  }
369 
370  return true;
371 }
372 
373 void
375 {
376  warn("%lli: Checker PC:%s",
377  curTick(), thread->pcState());
378  panic("Checker found an error!");
379 }
380 
381 } // namespace gem5
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::CheckerCPU::CheckerCPU
CheckerCPU(const Params &p)
Definition: cpu.cc:65
gem5::PCStateBase::instAddr
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
Definition: pcstate.hh:107
gem5::BaseMMU::Read
@ Read
Definition: mmu.hh:56
utils.hh
gem5::NoFault
constexpr decltype(nullptr) NoFault
Definition: types.hh:260
gem5::CheckerCPU::numInst
Counter numInst
Definition: cpu.hh:144
warn
#define warn(...)
Definition: logging.hh:246
gem5::CheckerCPU::serialize
void serialize(CheckpointOut &cp) const override
Definition: cpu.cc:131
data
const char data[]
Definition: circlebuf.test.cc:48
gem5::CheckerCPU::~CheckerCPU
virtual ~CheckerCPU()
Definition: cpu.cc:92
gem5::BaseMMU::Write
@ Write
Definition: mmu.hh:56
gem5::CheckpointIn
Definition: serialize.hh:68
gem5::CheckerCPU::unverifiedReq
RequestPtr unverifiedReq
Definition: cpu.hh:511
gem5::CheckerCPU::genMemFragmentRequest
RequestPtr genMemFragmentRequest(Addr frag_addr, int size, Request::Flags flags, const std::vector< bool > &byte_enable, int &frag_size, int &size_left) const
Helper function used to generate the request for a single fragment of a memory access.
Definition: cpu.cc:141
tlb.hh
gem5::CheckerCPU::workload
std::vector< Process * > workload
Definition: cpu.hh:125
gem5::ThreadContext::contextId
virtual ContextID contextId() const =0
gem5::CheckerCPU::thread
SimpleThread * thread
Definition: cpu.hh:152
gem5::X86ISA::system
Bitfield< 15 > system
Definition: misc.hh:1003
gem5::addrBlockOffset
Addr addrBlockOffset(Addr addr, Addr block_size)
Calculates the offset of a given address wrt aligned fixed-size blocks.
Definition: utils.hh:53
std::vector< bool >
gem5::CheckerCPU::willChangePC
bool willChangePC
Definition: cpu.hh:515
gem5::SimpleThread
The SimpleThread object provides a combination of the ThreadState object and the ThreadContext interf...
Definition: simple_thread.hh:93
gem5::CheckerCPU::writeMem
Fault writeMem(uint8_t *data, unsigned size, Addr addr, Request::Flags flags, uint64_t *res, const std::vector< bool > &byte_enable) override
Definition: cpu.cc:252
gem5::CheckerCPU::youngestSN
InstSeqNum youngestSN
Definition: cpu.hh:521
gem5::RequestPort
A RequestPort is a specialisation of a Port, which implements the default protocol for the three diff...
Definition: port.hh:77
gem5::BaseMMU::translateFunctional
virtual Fault translateFunctional(const RequestPtr &req, ThreadContext *tc, Mode mode)
Definition: mmu.cc:118
gem5::ArmISA::at
Bitfield< 35, 32 > at
Definition: misc_types.hh:155
gem5::CheckerCPU::dumpAndExit
void dumpAndExit()
Definition: cpu.cc:374
gem5::Packet::dataStatic
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
Definition: packet.hh:1134
gem5::CheckerCPU::tc
ThreadContext * tc
Definition: cpu.hh:132
gem5::Flags< FlagsType >
gem5::RequestPort::sendFunctional
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.hh:485
gem5::System
Definition: system.hh:75
gem5::ThreadContext::getIsaPtr
virtual BaseISA * getIsaPtr()=0
gem5::Fault
std::shared_ptr< FaultBase > Fault
Definition: types.hh:255
gem5::CheckerCPU::dcachePort
RequestPort * dcachePort
Definition: cpu.hh:130
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:283
gem5::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
cpu.hh
gem5::RequestPtr
std::shared_ptr< Request > RequestPtr
Definition: request.hh:92
gem5::Request::NO_ACCESS
@ NO_ACCESS
The request should not cause a memory access.
Definition: request.hh:146
gem5::isAnyActiveElement
bool isAnyActiveElement(const std::vector< bool >::const_iterator &it_start, const std::vector< bool >::const_iterator &it_end)
Test if there is any active element in an enablement range.
Definition: utils.hh:89
gem5::BaseISA::setThreadContext
virtual void setThreadContext(ThreadContext *_tc)
Definition: isa.hh:72
gem5::CheckerCPU::icachePort
RequestPort * icachePort
Definition: cpu.hh:129
gem5::System::getRequestorId
RequestorID getRequestorId(const SimObject *requestor, std::string subrequestor={})
Request an id used to create a request object in the system.
Definition: system.cc:533
gem5::CheckerCPU::systemPtr
System * systemPtr
Definition: cpu.hh:127
static_inst.hh
gem5::CheckerCPU::numLoad
Counter numLoad
Definition: cpu.hh:161
gem5::CheckerCPU::startNumInst
Counter startNumInst
Definition: cpu.hh:145
gem5::CheckerCPU::requestorId
RequestorID requestorId
id attached to all issued requests
Definition: cpu.hh:88
gem5::SimpleThread::pcState
const PCStateBase & pcState() const override
Definition: simple_thread.hh:422
gem5::CheckerCPU::changedPC
bool changedPC
Definition: cpu.hh:514
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::CheckerCPU::mmu
BaseMMU * mmu
Definition: cpu.hh:134
gem5::CheckerCPU::readMem
Fault readMem(Addr addr, uint8_t *data, unsigned size, Request::Flags flags, const std::vector< bool > &byte_enable) override
Definition: cpu.cc:168
gem5::CheckerCPU::exitOnError
bool exitOnError
Definition: cpu.hh:517
full_system.hh
gem5::CheckerCPU::checkFlags
bool checkFlags(const RequestPtr &unverified_req, Addr vAddr, Addr pAddr, int flags)
Checks if the flags set by the Checker and Checkee match.
Definition: cpu.cc:357
gem5::FullSystem
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition: root.cc:220
gem5::SimpleThread::getTC
ThreadContext * getTC()
Returns the pointer to this SimpleThread's ThreadContext.
Definition: simple_thread.hh:169
gem5::Request::STORE_NO_DATA
static const FlagsType STORE_NO_DATA
Definition: request.hh:246
gem5::IntRegClass
@ IntRegClass
Integer register.
Definition: reg_class.hh:58
gem5::CheckerCPU::init
void init() override
Definition: cpu.cc:59
gem5::CheckerCPU::unserialize
void unserialize(CheckpointIn &cp) override
Definition: cpu.cc:136
gem5::CheckerCPU::handleError
void handleError()
Definition: cpu.hh:496
simple_thread.hh
gem5::CheckerCPU::curStaticInst
StaticInstPtr curStaticInst
Definition: cpu.hh:140
gem5::CheckerCPU::setDcachePort
void setDcachePort(RequestPort *dcache_port)
Definition: cpu.cc:125
base.hh
gem5::X86ISA::os
Bitfield< 17 > os
Definition: misc.hh:809
gem5::CheckerCPU::warnOnlyOnLoadError
bool warnOnlyOnLoadError
Definition: cpu.hh:519
gem5::CheckerCPU::startNumLoad
Counter startNumLoad
Definition: cpu.hh:162
gem5::CheckerCPU::setIcachePort
void setIcachePort(RequestPort *icache_port)
Definition: cpu.cc:119
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: tlb.cc:60
gem5::Packet::createRead
static PacketPtr createRead(const RequestPtr &req)
Constructor-like methods that return Packets based on Request objects.
Definition: packet.hh:1007
gem5::CheckerCPU::curMacroStaticInst
StaticInstPtr curMacroStaticInst
Definition: cpu.hh:141
gem5::CheckerCPU::updateOnError
bool updateOnError
Definition: cpu.hh:518
thread_context.hh
gem5::CheckerCPU::unverifiedMemData
uint8_t * unverifiedMemData
Definition: cpu.hh:512
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
gem5::X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:84
gem5::CheckerCPU::setSystem
void setSystem(System *system)
Definition: cpu.cc:97

Generated on Tue Dec 21 2021 11:34:19 for gem5 by doxygen 1.8.17