physical.cc (2632:1bb2f91485ea) physical.cc (2639:78773954274f)
1/*
2 * Copyright (c) 2001-2005 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
29#include <sys/types.h>
30#include <sys/mman.h>
31#include <errno.h>
32#include <fcntl.h>
33#include <unistd.h>
34#include <zlib.h>
35
36#include <iostream>
37#include <string>
38
39
40#include "base/misc.hh"
41#include "config/full_system.hh"
42#include "mem/packet_impl.hh"
43#include "mem/physical.hh"
44#include "sim/host.hh"
45#include "sim/builder.hh"
46#include "sim/eventq.hh"
47#include "arch/isa_traits.hh"
48
49
50using namespace std;
51using namespace TheISA;
52
53PhysicalMemory::MemResponseEvent::MemResponseEvent(Packet *pkt, MemoryPort* _m)
54 : Event(&mainEventQueue, CPU_Tick_Pri), pkt(pkt), memoryPort(_m)
55{
56
57 this->setFlags(AutoDelete);
58}
59
60void
61PhysicalMemory::MemResponseEvent::process()
62{
63 memoryPort->sendTiming(pkt);
64}
65
66const char *
67PhysicalMemory::MemResponseEvent::description()
68{
69 return "Physical Memory Timing Access respnse event";
70}
71
72PhysicalMemory::PhysicalMemory(const string &n, Tick latency)
73 : MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency)
74{
75 // Hardcoded to 128 MB for now.
76 pmem_size = 1 << 27;
77
78 if (pmem_size % TheISA::PageBytes != 0)
79 panic("Memory Size not divisible by page size\n");
80
81 int map_flags = MAP_ANON | MAP_PRIVATE;
82 pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE,
83 map_flags, -1, 0);
84
85 if (pmem_addr == (void *)MAP_FAILED) {
86 perror("mmap");
87 fatal("Could not mmap!\n");
88 }
89
90 page_ptr = 0;
91}
92
93void
94PhysicalMemory::init()
95{
96 if (!port)
97 panic("PhysicalMemory not connected to anything!");
98 port->sendStatusChange(Port::RangeChange);
99}
100
101PhysicalMemory::~PhysicalMemory()
102{
103 if (pmem_addr)
104 munmap(pmem_addr, pmem_size);
105 //Remove memPorts?
106}
107
108Addr
109PhysicalMemory::new_page()
110{
111 Addr return_addr = page_ptr << LogVMPageSize;
112 return_addr += base_addr;
113
114 ++page_ptr;
115 return return_addr;
116}
117
118int
119PhysicalMemory::deviceBlockSize()
120{
121 //Can accept anysize request
122 return 0;
123}
124
125bool
126PhysicalMemory::doTimingAccess (Packet *pkt, MemoryPort* memoryPort)
127{
128 doFunctionalAccess(pkt);
129
1/*
2 * Copyright (c) 2001-2005 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
29#include <sys/types.h>
30#include <sys/mman.h>
31#include <errno.h>
32#include <fcntl.h>
33#include <unistd.h>
34#include <zlib.h>
35
36#include <iostream>
37#include <string>
38
39
40#include "base/misc.hh"
41#include "config/full_system.hh"
42#include "mem/packet_impl.hh"
43#include "mem/physical.hh"
44#include "sim/host.hh"
45#include "sim/builder.hh"
46#include "sim/eventq.hh"
47#include "arch/isa_traits.hh"
48
49
50using namespace std;
51using namespace TheISA;
52
53PhysicalMemory::MemResponseEvent::MemResponseEvent(Packet *pkt, MemoryPort* _m)
54 : Event(&mainEventQueue, CPU_Tick_Pri), pkt(pkt), memoryPort(_m)
55{
56
57 this->setFlags(AutoDelete);
58}
59
60void
61PhysicalMemory::MemResponseEvent::process()
62{
63 memoryPort->sendTiming(pkt);
64}
65
66const char *
67PhysicalMemory::MemResponseEvent::description()
68{
69 return "Physical Memory Timing Access respnse event";
70}
71
72PhysicalMemory::PhysicalMemory(const string &n, Tick latency)
73 : MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency)
74{
75 // Hardcoded to 128 MB for now.
76 pmem_size = 1 << 27;
77
78 if (pmem_size % TheISA::PageBytes != 0)
79 panic("Memory Size not divisible by page size\n");
80
81 int map_flags = MAP_ANON | MAP_PRIVATE;
82 pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE,
83 map_flags, -1, 0);
84
85 if (pmem_addr == (void *)MAP_FAILED) {
86 perror("mmap");
87 fatal("Could not mmap!\n");
88 }
89
90 page_ptr = 0;
91}
92
93void
94PhysicalMemory::init()
95{
96 if (!port)
97 panic("PhysicalMemory not connected to anything!");
98 port->sendStatusChange(Port::RangeChange);
99}
100
101PhysicalMemory::~PhysicalMemory()
102{
103 if (pmem_addr)
104 munmap(pmem_addr, pmem_size);
105 //Remove memPorts?
106}
107
108Addr
109PhysicalMemory::new_page()
110{
111 Addr return_addr = page_ptr << LogVMPageSize;
112 return_addr += base_addr;
113
114 ++page_ptr;
115 return return_addr;
116}
117
118int
119PhysicalMemory::deviceBlockSize()
120{
121 //Can accept anysize request
122 return 0;
123}
124
125bool
126PhysicalMemory::doTimingAccess (Packet *pkt, MemoryPort* memoryPort)
127{
128 doFunctionalAccess(pkt);
129
130 // turn packet around to go back to requester
130 pkt->dest = pkt->src;
131 MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort);
132 response->schedule(curTick + lat);
133
134 return true;
135}
136
137Tick
138PhysicalMemory::doAtomicAccess(Packet *pkt)
139{
140 doFunctionalAccess(pkt);
141 pkt->time = curTick + lat;
142 return curTick + lat;
143}
144
145void
146PhysicalMemory::doFunctionalAccess(Packet *pkt)
147{
148 assert(pkt->addr + pkt->size < pmem_size);
149
150 switch (pkt->cmd) {
151 case Read:
152 memcpy(pkt->getPtr<uint8_t>(), pmem_addr + pkt->addr - base_addr,
153 pkt->size);
154 break;
155 case Write:
156 memcpy(pmem_addr + pkt->addr - base_addr, pkt->getPtr<uint8_t>(),
157 pkt->size);
158 // temporary hack: will need to add real LL/SC implementation
159 // for cacheless systems later.
160 if (pkt->req->getFlags() & LOCKED) {
161 pkt->req->setScResult(1);
162 }
163 break;
164 default:
165 panic("unimplemented");
166 }
167
168 pkt->result = Success;
169}
170
171Port *
172PhysicalMemory::getPort(const std::string &if_name)
173{
174 if (if_name == "") {
175 if (port != NULL)
176 panic("PhysicalMemory::getPort: additional port requested to memory!");
177 port = new MemoryPort(this);
178 return port;
179 } else if (if_name == "functional") {
180 /* special port for functional writes at startup. */
181 return new MemoryPort(this);
182 } else {
183 panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
184 }
185}
186
187void
188PhysicalMemory::recvStatusChange(Port::Status status)
189{
190}
191
192PhysicalMemory::MemoryPort::MemoryPort(PhysicalMemory *_memory)
193 : memory(_memory)
194{ }
195
196void
197PhysicalMemory::MemoryPort::recvStatusChange(Port::Status status)
198{
199 memory->recvStatusChange(status);
200}
201
202void
203PhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp,
204 AddrRangeList &snoop)
205{
206 memory->getAddressRanges(resp, snoop);
207}
208
209void
210PhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
211{
212 snoop.clear();
213 resp.clear();
214 resp.push_back(RangeSize(base_addr, pmem_size));
215}
216
217int
218PhysicalMemory::MemoryPort::deviceBlockSize()
219{
220 return memory->deviceBlockSize();
221}
222
223bool
224PhysicalMemory::MemoryPort::recvTiming(Packet *pkt)
225{
226 return memory->doTimingAccess(pkt, this);
227}
228
229Tick
230PhysicalMemory::MemoryPort::recvAtomic(Packet *pkt)
231{
232 return memory->doAtomicAccess(pkt);
233}
234
235void
236PhysicalMemory::MemoryPort::recvFunctional(Packet *pkt)
237{
238 memory->doFunctionalAccess(pkt);
239}
240
241
242
243void
244PhysicalMemory::serialize(ostream &os)
245{
246 gzFile compressedMem;
247 string filename = name() + ".physmem";
248
249 SERIALIZE_SCALAR(pmem_size);
250 SERIALIZE_SCALAR(filename);
251
252 // write memory file
253 string thefile = Checkpoint::dir() + "/" + filename.c_str();
254 int fd = creat(thefile.c_str(), 0664);
255 if (fd < 0) {
256 perror("creat");
257 fatal("Can't open physical memory checkpoint file '%s'\n", filename);
258 }
259
260 compressedMem = gzdopen(fd, "wb");
261 if (compressedMem == NULL)
262 fatal("Insufficient memory to allocate compression state for %s\n",
263 filename);
264
265 if (gzwrite(compressedMem, pmem_addr, pmem_size) != pmem_size) {
266 fatal("Write failed on physical memory checkpoint file '%s'\n",
267 filename);
268 }
269
270 if (gzclose(compressedMem))
271 fatal("Close failed on physical memory checkpoint file '%s'\n",
272 filename);
273}
274
275void
276PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
277{
278 gzFile compressedMem;
279 long *tempPage;
280 long *pmem_current;
281 uint64_t curSize;
282 uint32_t bytesRead;
283 const int chunkSize = 16384;
284
285
286 // unmap file that was mmaped in the constructor
287 munmap(pmem_addr, pmem_size);
288
289 string filename;
290
291 UNSERIALIZE_SCALAR(pmem_size);
292 UNSERIALIZE_SCALAR(filename);
293
294 filename = cp->cptDir + "/" + filename;
295
296 // mmap memoryfile
297 int fd = open(filename.c_str(), O_RDONLY);
298 if (fd < 0) {
299 perror("open");
300 fatal("Can't open physical memory checkpoint file '%s'", filename);
301 }
302
303 compressedMem = gzdopen(fd, "rb");
304 if (compressedMem == NULL)
305 fatal("Insufficient memory to allocate compression state for %s\n",
306 filename);
307
308
309 pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE,
310 MAP_ANON | MAP_PRIVATE, -1, 0);
311
312 if (pmem_addr == (void *)MAP_FAILED) {
313 perror("mmap");
314 fatal("Could not mmap physical memory!\n");
315 }
316
317 curSize = 0;
318 tempPage = (long*)malloc(chunkSize);
319 if (tempPage == NULL)
320 fatal("Unable to malloc memory to read file %s\n", filename);
321
322 /* Only copy bytes that are non-zero, so we don't give the VM system hell */
323 while (curSize < pmem_size) {
324 bytesRead = gzread(compressedMem, tempPage, chunkSize);
325 if (bytesRead != chunkSize && bytesRead != pmem_size - curSize)
326 fatal("Read failed on physical memory checkpoint file '%s'"
327 " got %d bytes, expected %d or %d bytes\n",
328 filename, bytesRead, chunkSize, pmem_size-curSize);
329
330 assert(bytesRead % sizeof(long) == 0);
331
332 for (int x = 0; x < bytesRead/sizeof(long); x++)
333 {
334 if (*(tempPage+x) != 0) {
335 pmem_current = (long*)(pmem_addr + curSize + x * sizeof(long));
336 *pmem_current = *(tempPage+x);
337 }
338 }
339 curSize += bytesRead;
340 }
341
342 free(tempPage);
343
344 if (gzclose(compressedMem))
345 fatal("Close failed on physical memory checkpoint file '%s'\n",
346 filename);
347
348}
349
350
351BEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
352
353 Param<string> file;
354 Param<Range<Addr> > range;
355 Param<Tick> latency;
356
357END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
358
359BEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
360
361 INIT_PARAM_DFLT(file, "memory mapped file", ""),
362 INIT_PARAM(range, "Device Address Range"),
363 INIT_PARAM(latency, "Memory access latency")
364
365END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
366
367CREATE_SIM_OBJECT(PhysicalMemory)
368{
369
370 return new PhysicalMemory(getInstanceName(), latency);
371}
372
373REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)
131 pkt->dest = pkt->src;
132 MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort);
133 response->schedule(curTick + lat);
134
135 return true;
136}
137
138Tick
139PhysicalMemory::doAtomicAccess(Packet *pkt)
140{
141 doFunctionalAccess(pkt);
142 pkt->time = curTick + lat;
143 return curTick + lat;
144}
145
146void
147PhysicalMemory::doFunctionalAccess(Packet *pkt)
148{
149 assert(pkt->addr + pkt->size < pmem_size);
150
151 switch (pkt->cmd) {
152 case Read:
153 memcpy(pkt->getPtr<uint8_t>(), pmem_addr + pkt->addr - base_addr,
154 pkt->size);
155 break;
156 case Write:
157 memcpy(pmem_addr + pkt->addr - base_addr, pkt->getPtr<uint8_t>(),
158 pkt->size);
159 // temporary hack: will need to add real LL/SC implementation
160 // for cacheless systems later.
161 if (pkt->req->getFlags() & LOCKED) {
162 pkt->req->setScResult(1);
163 }
164 break;
165 default:
166 panic("unimplemented");
167 }
168
169 pkt->result = Success;
170}
171
172Port *
173PhysicalMemory::getPort(const std::string &if_name)
174{
175 if (if_name == "") {
176 if (port != NULL)
177 panic("PhysicalMemory::getPort: additional port requested to memory!");
178 port = new MemoryPort(this);
179 return port;
180 } else if (if_name == "functional") {
181 /* special port for functional writes at startup. */
182 return new MemoryPort(this);
183 } else {
184 panic("PhysicalMemory::getPort: unknown port %s requested", if_name);
185 }
186}
187
188void
189PhysicalMemory::recvStatusChange(Port::Status status)
190{
191}
192
193PhysicalMemory::MemoryPort::MemoryPort(PhysicalMemory *_memory)
194 : memory(_memory)
195{ }
196
197void
198PhysicalMemory::MemoryPort::recvStatusChange(Port::Status status)
199{
200 memory->recvStatusChange(status);
201}
202
203void
204PhysicalMemory::MemoryPort::getDeviceAddressRanges(AddrRangeList &resp,
205 AddrRangeList &snoop)
206{
207 memory->getAddressRanges(resp, snoop);
208}
209
210void
211PhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
212{
213 snoop.clear();
214 resp.clear();
215 resp.push_back(RangeSize(base_addr, pmem_size));
216}
217
218int
219PhysicalMemory::MemoryPort::deviceBlockSize()
220{
221 return memory->deviceBlockSize();
222}
223
224bool
225PhysicalMemory::MemoryPort::recvTiming(Packet *pkt)
226{
227 return memory->doTimingAccess(pkt, this);
228}
229
230Tick
231PhysicalMemory::MemoryPort::recvAtomic(Packet *pkt)
232{
233 return memory->doAtomicAccess(pkt);
234}
235
236void
237PhysicalMemory::MemoryPort::recvFunctional(Packet *pkt)
238{
239 memory->doFunctionalAccess(pkt);
240}
241
242
243
244void
245PhysicalMemory::serialize(ostream &os)
246{
247 gzFile compressedMem;
248 string filename = name() + ".physmem";
249
250 SERIALIZE_SCALAR(pmem_size);
251 SERIALIZE_SCALAR(filename);
252
253 // write memory file
254 string thefile = Checkpoint::dir() + "/" + filename.c_str();
255 int fd = creat(thefile.c_str(), 0664);
256 if (fd < 0) {
257 perror("creat");
258 fatal("Can't open physical memory checkpoint file '%s'\n", filename);
259 }
260
261 compressedMem = gzdopen(fd, "wb");
262 if (compressedMem == NULL)
263 fatal("Insufficient memory to allocate compression state for %s\n",
264 filename);
265
266 if (gzwrite(compressedMem, pmem_addr, pmem_size) != pmem_size) {
267 fatal("Write failed on physical memory checkpoint file '%s'\n",
268 filename);
269 }
270
271 if (gzclose(compressedMem))
272 fatal("Close failed on physical memory checkpoint file '%s'\n",
273 filename);
274}
275
276void
277PhysicalMemory::unserialize(Checkpoint *cp, const string &section)
278{
279 gzFile compressedMem;
280 long *tempPage;
281 long *pmem_current;
282 uint64_t curSize;
283 uint32_t bytesRead;
284 const int chunkSize = 16384;
285
286
287 // unmap file that was mmaped in the constructor
288 munmap(pmem_addr, pmem_size);
289
290 string filename;
291
292 UNSERIALIZE_SCALAR(pmem_size);
293 UNSERIALIZE_SCALAR(filename);
294
295 filename = cp->cptDir + "/" + filename;
296
297 // mmap memoryfile
298 int fd = open(filename.c_str(), O_RDONLY);
299 if (fd < 0) {
300 perror("open");
301 fatal("Can't open physical memory checkpoint file '%s'", filename);
302 }
303
304 compressedMem = gzdopen(fd, "rb");
305 if (compressedMem == NULL)
306 fatal("Insufficient memory to allocate compression state for %s\n",
307 filename);
308
309
310 pmem_addr = (uint8_t *)mmap(NULL, pmem_size, PROT_READ | PROT_WRITE,
311 MAP_ANON | MAP_PRIVATE, -1, 0);
312
313 if (pmem_addr == (void *)MAP_FAILED) {
314 perror("mmap");
315 fatal("Could not mmap physical memory!\n");
316 }
317
318 curSize = 0;
319 tempPage = (long*)malloc(chunkSize);
320 if (tempPage == NULL)
321 fatal("Unable to malloc memory to read file %s\n", filename);
322
323 /* Only copy bytes that are non-zero, so we don't give the VM system hell */
324 while (curSize < pmem_size) {
325 bytesRead = gzread(compressedMem, tempPage, chunkSize);
326 if (bytesRead != chunkSize && bytesRead != pmem_size - curSize)
327 fatal("Read failed on physical memory checkpoint file '%s'"
328 " got %d bytes, expected %d or %d bytes\n",
329 filename, bytesRead, chunkSize, pmem_size-curSize);
330
331 assert(bytesRead % sizeof(long) == 0);
332
333 for (int x = 0; x < bytesRead/sizeof(long); x++)
334 {
335 if (*(tempPage+x) != 0) {
336 pmem_current = (long*)(pmem_addr + curSize + x * sizeof(long));
337 *pmem_current = *(tempPage+x);
338 }
339 }
340 curSize += bytesRead;
341 }
342
343 free(tempPage);
344
345 if (gzclose(compressedMem))
346 fatal("Close failed on physical memory checkpoint file '%s'\n",
347 filename);
348
349}
350
351
352BEGIN_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
353
354 Param<string> file;
355 Param<Range<Addr> > range;
356 Param<Tick> latency;
357
358END_DECLARE_SIM_OBJECT_PARAMS(PhysicalMemory)
359
360BEGIN_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
361
362 INIT_PARAM_DFLT(file, "memory mapped file", ""),
363 INIT_PARAM(range, "Device Address Range"),
364 INIT_PARAM(latency, "Memory access latency")
365
366END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
367
368CREATE_SIM_OBJECT(PhysicalMemory)
369{
370
371 return new PhysicalMemory(getInstanceName(), latency);
372}
373
374REGISTER_SIM_OBJECT("PhysicalMemory", PhysicalMemory)