blob: 5a7a1c57aa17fe3b2d2c39886f9b1d7301f158b5 [file] [log] [blame]
Giacomo Travaglini5a23c6e2021-01-25 13:27:30 +00001/*
2 * Copyright (c) 2012-2013, 2021 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) 2001-2005 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#ifndef __MEM_FLASH_MEM_HH__
42#define __MEM_FLASH_MEM_HH__
43
44#include "mem/abstract_mem.hh"
45#include "params/CfiMemory.hh"
46
Daniel R. Carvalho974a47d2021-05-09 12:32:07 -030047namespace gem5
48{
49
Daniel R. Carvalho79bab1d2021-06-13 12:05:03 -030050namespace memory
51{
52
Giacomo Travaglini5a23c6e2021-01-25 13:27:30 +000053/**
54 * CfiMemory: This is modelling a flash memory adhering to the
55 * Common Flash Interface (CFI):
56 *
57 * JEDEC JESD68.01
58 * JEDEC JEP137B
59 * Intel Application Note 646
60 *
61 * This is as of now a pure functional model of a flash controller:
62 * no timing/power information has been encoded in it and it is therefore
63 * not representive of a real device. Some voltage/timing values have
64 * nevertheless been encoded in the CFI table.
65 * This is just a requirement from the CFI specification: guest software
66 * might query those entries, but they are not reflected in gem5 statistics.
67 *
68 * The model is meant to be used to allow execution of flash drivers
69 * (e.g. UEFI firmware storing EFI variables in non volatile memory)
70 */
71class CfiMemory : public AbstractMemory
72{
73 private:
74 enum class CfiCommand
75 {
76 NO_CMD = 0,
77 LOCK_BLOCK = 0x1,
78 ERASE_BLOCK_SETUP = 0x20,
79 WORD_PROGRAM = 0x40,
80 CLEAR_STATUS_REG = 0x50,
81 LOCK_BLOCK_SETUP = 0x60,
82 READ_STATUS_REG = 0x70,
83 READ_DEVICE_ID = 0x90,
84 READ_CFI_QUERY = 0x98,
85 BUFFERED_PROGRAM_SETUP = 0xE8,
86 BUFFERED_PROGRAM_CONFIRM = 0xD0,
87 BLOCK_ERASE_CONFIRM = 0xD0,
88 UNLOCK_BLOCK = 0xD0,
Quentin Forcioli32fd8cf2021-08-25 17:24:54 +020089 AMD_RESET=0xF0,
Giacomo Travaglini5a23c6e2021-01-25 13:27:30 +000090 READ_ARRAY = 0xFF,
Giacomo Travaglini5a23c6e2021-01-25 13:27:30 +000091 /** This is not a real command, but it is used by the internal
92 * model only to represent the 2nd write cycle state for a buffered
93 * program (when the buffer size is supplied) */
94 BUFFER_SIZE_READ,
95 };
96
97 /** Possible in the status register */
98 static const uint8_t STATUS_ERASE_ERROR = 0x30;
99 static const uint8_t STATUS_LOCK_ERROR = 0x12;
100 static const uint8_t STATUS_READY = 0x80;
101 static const uint8_t STATUS_PROGRAM_LOCK_BIT = 0x10;
102
103 /** Metadata about the erase blocks in flash */
104 struct BlockData : public Serializable
105 {
106 BlockData(const CfiMemory &_parent, ssize_t number, ssize_t size)
107 : Serializable(), locked(number, false), blockSize(size),
108 parent(_parent)
109 {}
110
111 /**
112 * Return true if the block pointed by the block_address
113 * parameter is locked
114 *
115 * @params block_address address of the erase block in flash
116 * memory: first block starts ad address 0x0
117 * @return true if block is locked
118 */
119 bool isLocked(Addr block_address) const;
120
121 /**
122 * Lock the block pointed by the block_address
123 * parameter
124 *
125 * @params block_address address of the erase block in flash
126 * memory: first block starts ad address 0x0
127 */
128 void lock(Addr block_address);
129
130 /**
131 * Unlock the block pointed by the block_address
132 * parameter
133 *
134 * @params block_address address of the erase block in flash
135 * memory: first block starts ad address 0x0
136 */
137 void unlock(Addr block_address);
138
139 /** Erase a single block. The address of the block
140 * is supplied by the packet address.
141 *
142 * @params pkt memory packet targeting the erase block
143 */
144 void erase(PacketPtr pkt);
145
146 /** Number of erase blocks in flash memory */
147 ssize_t number() const { return locked.size(); }
148
149 /** Size in bytes of a single erase block */
150 ssize_t size() const { return blockSize; }
151
152 private: // Serializable
153 void serialize(CheckpointOut &cp) const override;
154
155 void unserialize(CheckpointIn &cp) override;
156
157 private:
158 uint32_t blockIdx(Addr block_address) const;
159
160 // Per block flag. True if the block is locked
161 std::vector<bool> locked;
162
163 // Size of the block in bytes
164 const ssize_t blockSize;
165
166 const CfiMemory &parent;
167 };
168
169 /**
170 * Word Buffer used by the BUFFERED PROGRAM command
171 * to write (program) chunks of words to flash
172 */
173 struct ProgramBuffer : public Serializable
174 {
175 public:
176 // program buffer max size = 32 words
177 static const ssize_t MAX_BUFFER_SIZE = 32 * 4;
178
179 ProgramBuffer(const CfiMemory &_parent)
180 : Serializable(), parent(_parent)
181 {}
182
183 /**
184 * Start buffering
185 * @param buffer_size new size (in bytes) of the program buffer
186 */
187 void setup(ssize_t buffer_size);
188
189 /**
190 * Write data into the buffer. If the buffer is full, the
191 * method will return true, meaning it's time to write
192 * back the buffer into memory
193 *
194 * @params flash_address address in flash (relative to the start)
195 * @params data_ptr pointer to the data
196 * @params size number of bytes to be written to the buffer
197 *
198 * @return true if buffer needs to be written back to flash
199 */
200 bool write(Addr flash_address, void *data_ptr, ssize_t size);
201
202 bool writeback();
203
204 private:
205 void serialize(CheckpointOut &cp) const override;
206
207 void unserialize(CheckpointIn &cp) override;
208
209 private:
210 // program buffer
211 std::vector<uint8_t> buffer;
212
213 // Number of bytes written in the buffer
214 ssize_t bytesWritten = 0;
215
216 // Pointing to the latest written word in the buffer
217 Addr blockPointer = 0;
218
219 const CfiMemory &parent;
220 };
221
222 /**
223 * A deferred packet stores a packet along with its scheduled
224 * transmission time
225 */
226 class DeferredPacket
227 {
228
229 public:
230
231 const Tick tick;
232 const PacketPtr pkt;
233
234 DeferredPacket(PacketPtr _pkt, Tick _tick) : tick(_tick), pkt(_pkt)
235 { }
236 };
237
238 class MemoryPort : public ResponsePort
239 {
240 private:
Daniel R. Carvalho93e57342021-05-08 07:59:47 -0300241 CfiMemory& mem;
Giacomo Travaglini5a23c6e2021-01-25 13:27:30 +0000242
243 public:
244 MemoryPort(const std::string& _name, CfiMemory& _memory);
245
246 protected:
247 Tick recvAtomic(PacketPtr pkt) override;
248 Tick recvAtomicBackdoor(
249 PacketPtr pkt, MemBackdoorPtr &_backdoor) override;
250 void recvFunctional(PacketPtr pkt) override;
251 bool recvTimingReq(PacketPtr pkt) override;
252 void recvRespRetry() override;
253 AddrRangeList getAddrRanges() const override;
254 };
255
256 MemoryPort port;
257
258 /**
259 * Latency from that a request is accepted until the response is
260 * ready to be sent.
261 */
262 const Tick latency;
263
264 /**
265 * Fudge factor added to the latency.
266 */
267 const Tick latency_var;
268
269 /**
270 * Internal (unbounded) storage to mimic the delay caused by the
271 * actual memory access. Note that this is where the packet spends
272 * the memory latency.
273 */
274 std::list<DeferredPacket> packetQueue;
275
276 /**
277 * Bandwidth in ticks per byte. The regulation affects the
278 * acceptance rate of requests and the queueing takes place after
279 * the regulation.
280 */
281 const double bandwidth;
282
283 /**
284 * Track the state of the memory as either idle or busy, no need
285 * for an enum with only two states.
286 */
287 bool isBusy;
288
289 /**
290 * Remember if we have to retry an outstanding request that
291 * arrived while we were busy.
292 */
293 bool retryReq;
294
295 /**
296 * Remember if we failed to send a response and are awaiting a
297 * retry. This is only used as a check.
298 */
299 bool retryResp;
300
301 /**
302 * Release the memory after being busy and send a retry if a
303 * request was rejected in the meanwhile.
304 */
305 void release();
306
307 EventFunctionWrapper releaseEvent;
308
309 /**
310 * Dequeue a packet from our internal packet queue and move it to
311 * the port where it will be sent as soon as possible.
312 */
313 void dequeue();
314
315 EventFunctionWrapper dequeueEvent;
316
317 /**
318 * Detemine the latency.
319 *
320 * @return the latency seen by the current packet
321 */
322 Tick getLatency() const;
323
324 /**
325 * Upstream caches need this packet until true is returned, so
326 * hold it for deletion until a subsequent call
327 */
328 std::unique_ptr<Packet> pendingDelete;
329
330 const uint8_t numberOfChips;
331
332 const uint16_t vendorID;
333 const uint16_t deviceID;
334 const uint16_t bankWidth;
335
336 /** Previous command (issued in the previous write cycle) */
337 CfiCommand readState;
338 CfiCommand writeState;
339
340 uint8_t statusRegister;
341
342 BlockData blocks;
343
344 ProgramBuffer programBuffer;
345
Quentin Forcioli32fd8cf2021-08-25 17:24:54 +0200346 uint8_t cfiQueryTable[61];
Giacomo Travaglini5a23c6e2021-01-25 13:27:30 +0000347
348 public:
349 CfiMemory(const CfiMemoryParams &p);
350
351 DrainState drain() override;
352
353 Port &getPort(const std::string &if_name,
354 PortID idx=InvalidPortID) override;
355 void init() override;
356
357 void serialize(CheckpointOut &cp) const override;
358 void unserialize(CheckpointIn &cp) override;
359
360 protected:
361 Tick recvAtomic(PacketPtr pkt);
362 Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &_backdoor);
363 void recvFunctional(PacketPtr pkt);
364 bool recvTimingReq(PacketPtr pkt);
365 void recvRespRetry();
366
367 /** Make a read/write access to the CFI Memory */
368 void cfiAccess(PacketPtr pkt);
369
370 /** Write request to the CFI Memory */
371 void write(PacketPtr pkt);
372
373 /** Read request to the CFI Memory */
374 void read(PacketPtr pkt);
375
376 /**
377 * Helper function to read the device identifier after the
378 * read state machine is put in the CfiCommand::READ_DEVICE_ID
379 * mode.
380 *
381 * @param flash_address: The flash address LSBits encode the
382 * the information the software is trying
383 * to read
384 */
385 uint64_t readDeviceID(Addr flash_address) const;
386
387 /**
388 * Service a new command issued to the flash device
389 *
390 * @param command: new command issued to the flash device
391 */
392 void handleCommand(CfiCommand command);
393
394 /** Return the selected entry in the CFI table
395 *
396 * @param addr: offset in the CFI table
397 */
398 uint64_t cfiQuery(Addr addr);
399};
400
Daniel R. Carvalho79bab1d2021-06-13 12:05:03 -0300401} // namespace memory
Daniel R. Carvalho974a47d2021-05-09 12:32:07 -0300402} // namespace gem5
403
Giacomo Travaglini5a23c6e2021-01-25 13:27:30 +0000404#endif