mem: Delete authors lists from mem files.
[gem5.git] / src / mem / mem_checker_monitor.cc
1 /*
2 * Copyright (c) 2012-2014 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 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include "mem/mem_checker_monitor.hh"
39
40 #include <memory>
41
42 #include "base/logging.hh"
43 #include "base/output.hh"
44 #include "base/trace.hh"
45 #include "debug/MemCheckerMonitor.hh"
46
47 MemCheckerMonitor::MemCheckerMonitor(Params* params)
48 : SimObject(params),
49 masterPort(name() + "-master", *this),
50 slavePort(name() + "-slave", *this),
51 warnOnly(params->warn_only),
52 memchecker(params->memchecker)
53 {}
54
55 MemCheckerMonitor::~MemCheckerMonitor()
56 {}
57
58 MemCheckerMonitor*
59 MemCheckerMonitorParams::create()
60 {
61 return new MemCheckerMonitor(this);
62 }
63
64 void
65 MemCheckerMonitor::init()
66 {
67 // make sure both sides of the monitor are connected
68 if (!slavePort.isConnected() || !masterPort.isConnected())
69 fatal("Communication monitor is not connected on both sides.\n");
70 }
71
72 Port &
73 MemCheckerMonitor::getPort(const std::string &if_name, PortID idx)
74 {
75 if (if_name == "master" || if_name == "mem_side") {
76 return masterPort;
77 } else if (if_name == "slave" || if_name == "cpu_side") {
78 return slavePort;
79 } else {
80 return SimObject::getPort(if_name, idx);
81 }
82 }
83
84 void
85 MemCheckerMonitor::recvFunctional(PacketPtr pkt)
86 {
87 Addr addr = pkt->getAddr();
88 unsigned size = pkt->getSize();
89
90 // Conservatively reset this address-range. Alternatively we could try to
91 // update the values seen by the memchecker, however, there may be other
92 // reads/writes to these location from other devices we do not see.
93 memchecker->reset(addr, size);
94
95 masterPort.sendFunctional(pkt);
96
97 DPRINTF(MemCheckerMonitor,
98 "Forwarded functional access: addr = %#llx, size = %d\n",
99 addr, size);
100 }
101
102 void
103 MemCheckerMonitor::recvFunctionalSnoop(PacketPtr pkt)
104 {
105 Addr addr = pkt->getAddr();
106 unsigned size = pkt->getSize();
107
108 // See above.
109 memchecker->reset(addr, size);
110
111 slavePort.sendFunctionalSnoop(pkt);
112
113 DPRINTF(MemCheckerMonitor,
114 "Received functional snoop: addr = %#llx, size = %d\n",
115 addr, size);
116 }
117
118 Tick
119 MemCheckerMonitor::recvAtomic(PacketPtr pkt)
120 {
121 panic("Atomic not supported");
122 }
123
124 Tick
125 MemCheckerMonitor::recvAtomicSnoop(PacketPtr pkt)
126 {
127 panic("Atomic not supported");
128 }
129
130 bool
131 MemCheckerMonitor::recvTimingReq(PacketPtr pkt)
132 {
133 // should always see a request
134 assert(pkt->isRequest());
135
136 // Store relevant fields of packet, because packet may be modified
137 // or even deleted when sendTiming() is called.
138 //
139 // For reads we are only interested in real reads, and not prefetches, as
140 // it is not guaranteed that the prefetch returns any useful data.
141 bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
142 bool is_write = pkt->isWrite();
143 unsigned size = pkt->getSize();
144 Addr addr = pkt->getAddr();
145 bool expects_response = pkt->needsResponse() && !pkt->cacheResponding();
146 std::unique_ptr<uint8_t[]> pkt_data;
147 MemCheckerMonitorSenderState* state = NULL;
148
149 if (expects_response && is_write) {
150 // On receipt of a request, only need to allocate pkt_data if this is a
151 // write. For reads, we have no data yet, so it doesn't make sense to
152 // allocate.
153 pkt_data.reset(new uint8_t[size]);
154 pkt->writeData(pkt_data.get());
155 }
156
157 // If a cache miss is served by a cache, a monitor near the memory
158 // would see a request which needs a response, but this response
159 // would not come back from the memory. Therefore
160 // we additionally have to check the inhibit flag.
161 if (expects_response && (is_read || is_write)) {
162 state = new MemCheckerMonitorSenderState(0);
163 pkt->pushSenderState(state);
164 }
165
166 // Attempt to send the packet
167 bool successful = masterPort.sendTimingReq(pkt);
168
169 // If not successful, restore the sender state
170 if (!successful && expects_response && (is_read || is_write)) {
171 delete pkt->popSenderState();
172 }
173
174 if (successful && expects_response) {
175 if (is_read) {
176 MemChecker::Serial serial = memchecker->startRead(curTick(),
177 addr,
178 size);
179
180 // At the time where we push the sender-state, we do not yet know
181 // the serial the MemChecker class will assign to this request. We
182 // cannot call startRead at the time we push the sender-state, as
183 // the masterPort may not be successful in executing sendTimingReq,
184 // and in case of a failure, we must not modify the state of the
185 // MemChecker.
186 //
187 // Once we know that sendTimingReq was successful, we can set the
188 // serial of the newly constructed sender-state. This is legal, as
189 // we know that nobody else will touch nor is responsible for
190 // deletion of our sender-state.
191 state->serial = serial;
192
193 DPRINTF(MemCheckerMonitor,
194 "Forwarded read request: serial = %d, addr = %#llx, "
195 "size = %d\n",
196 serial, addr, size);
197 } else if (is_write) {
198 MemChecker::Serial serial = memchecker->startWrite(curTick(),
199 addr,
200 size,
201 pkt_data.get());
202
203 state->serial = serial;
204
205 DPRINTF(MemCheckerMonitor,
206 "Forwarded write request: serial = %d, addr = %#llx, "
207 "size = %d\n",
208 serial, addr, size);
209 } else {
210 DPRINTF(MemCheckerMonitor,
211 "Forwarded non read/write request: addr = %#llx\n", addr);
212 }
213 } else if (successful) {
214 DPRINTF(MemCheckerMonitor,
215 "Forwarded request marked for cache response: addr = %#llx\n",
216 addr);
217 }
218
219 return successful;
220 }
221
222 bool
223 MemCheckerMonitor::recvTimingResp(PacketPtr pkt)
224 {
225 // should always see responses
226 assert(pkt->isResponse());
227
228 // Store relevant fields of packet, because packet may be modified
229 // or even deleted when sendTiming() is called.
230 bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
231 bool is_write = pkt->isWrite();
232 bool is_failed_LLSC = pkt->isLLSC() && pkt->req->getExtraData() == 0;
233 unsigned size = pkt->getSize();
234 Addr addr = pkt->getAddr();
235 std::unique_ptr<uint8_t[]> pkt_data;
236 MemCheckerMonitorSenderState* received_state = NULL;
237
238 if (is_read) {
239 // On receipt of a response, only need to allocate pkt_data if this is
240 // a read. For writes, we have already given the MemChecker the data on
241 // the request, so it doesn't make sense to allocate on write.
242 pkt_data.reset(new uint8_t[size]);
243 pkt->writeData(pkt_data.get());
244 }
245
246 if (is_read || is_write) {
247 received_state =
248 dynamic_cast<MemCheckerMonitorSenderState*>(pkt->senderState);
249
250 // Restore initial sender state
251 panic_if(received_state == NULL,
252 "Monitor got a response without monitor sender state\n");
253
254 // Restore the state
255 pkt->senderState = received_state->predecessor;
256 }
257
258 // Attempt to send the packet
259 bool successful = slavePort.sendTimingResp(pkt);
260
261 // If packet successfully send, complete transaction in MemChecker
262 // instance, and delete sender state, otherwise restore state.
263 if (successful) {
264 if (is_read) {
265 DPRINTF(MemCheckerMonitor,
266 "Received read response: serial = %d, addr = %#llx, "
267 "size = %d\n",
268 received_state->serial, addr, size);
269
270 bool result = memchecker->completeRead(received_state->serial,
271 curTick(),
272 addr,
273 size,
274 pkt_data.get());
275
276 if (!result) {
277 warn("%s: read of %#llx @ cycle %d failed:\n%s\n",
278 name(),
279 addr, curTick(),
280 memchecker->getErrorMessage().c_str());
281
282 panic_if(!warnOnly, "MemChecker violation!");
283 }
284
285 delete received_state;
286 } else if (is_write) {
287 DPRINTF(MemCheckerMonitor,
288 "Received write response: serial = %d, addr = %#llx, "
289 "size = %d\n",
290 received_state->serial, addr, size);
291
292 if (is_failed_LLSC) {
293 // The write was not successful, let MemChecker know.
294 memchecker->abortWrite(received_state->serial,
295 addr,
296 size);
297 } else {
298 memchecker->completeWrite(received_state->serial,
299 curTick(),
300 addr,
301 size);
302 }
303
304 delete received_state;
305 } else {
306 DPRINTF(MemCheckerMonitor,
307 "Received non read/write response: addr = %#llx\n", addr);
308 }
309 } else if (is_read || is_write) {
310 // Don't delete anything and let the packet look like we
311 // did not touch it
312 pkt->senderState = received_state;
313 }
314
315 return successful;
316 }
317
318 void
319 MemCheckerMonitor::recvTimingSnoopReq(PacketPtr pkt)
320 {
321 slavePort.sendTimingSnoopReq(pkt);
322 }
323
324 bool
325 MemCheckerMonitor::recvTimingSnoopResp(PacketPtr pkt)
326 {
327 return masterPort.sendTimingSnoopResp(pkt);
328 }
329
330 bool
331 MemCheckerMonitor::isSnooping() const
332 {
333 // check if the connected master port is snooping
334 return slavePort.isSnooping();
335 }
336
337 AddrRangeList
338 MemCheckerMonitor::getAddrRanges() const
339 {
340 // get the address ranges of the connected slave port
341 return masterPort.getAddrRanges();
342 }
343
344 void
345 MemCheckerMonitor::recvReqRetry()
346 {
347 slavePort.sendRetryReq();
348 }
349
350 void
351 MemCheckerMonitor::recvRespRetry()
352 {
353 masterPort.sendRetryResp();
354 }
355
356 void
357 MemCheckerMonitor::recvRangeChange()
358 {
359 slavePort.sendRangeChange();
360 }