TEMU  4.0
The Terma Emulator
Memory.h
Go to the documentation of this file.
1 //===-- temu-c/Memory.h - Memory Helpers ------------------------*- C++ -*-===//
2 //
3 // TEMU: The Terma Emulator
4 // (c) Terma 2015-2016
5 // Authors: Mattias Holm <maho (at) terma.com>
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef TEMU_SUPPORT_MEMORY
10 #define TEMU_SUPPORT_MEMORY
11 
12 #include "temu-c/Support/Attributes.h"
13 #include "temu-c/Support/Objsys.h"
14 #include <stdint.h>
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 typedef enum temu_MemoryKind {
21  teMK_RAM = 0, //!< Model is a RAM
22  teMK_ROM = 1, //!< Model is a ROM
23  teMK_MMIO = 2, //!< Alias for `teMK_IO`
24  teMK_IO = 2, //!< Model is a normal IO device
25  teMK_MemSpace = 4, //!< Model is a memory space
26  teMK_Last = 4, //!< DO NOT USE
27 } temu_MemoryKind;
28 
29 //! Memory attribute enumeration
30 
31 //! The emulator provides 5 standard attributes, and 3 user defined
32 //! ones. The attributes are set in the memory space (not the memory
33 //! models), so it is possible to set a watch point on memory mapped
34 //! devices. When an attribute is set on a page, that page will get a
35 //! shadow attribute page (same size as the page), enabling attributes
36 //! to be set on a per byte level.
37 //!
38 //! Attributes are only checked on the address being accessed, the
39 //! transaction size is not taken into account.
40 typedef enum temu_MemoryAttr {
41  teMA_Break = 1, //!< Breakpoint set
42  teMA_WatchRead = 1 << 1, //!< Read watchpoint set
43  teMA_WatchWrite = 1 << 2, //!< Write watchpoint set
44  teMA_Upset = 1 << 3, //!< Single event upset
45  teMA_Faulty = 1 << 4, //!< Multiple event upset / uncorrectable
46  teMA_User1 = 1 << 5, //!< User definable
47  teMA_User2 = 1 << 6, //!< User definable
48  teMA_User3 = 1 << 7, //!< User definable
49 } temu_MemoryAttr;
50 typedef uint8_t temu_MemoryAttrs;
51 typedef struct temu_MemAccessIface temu_MemAccessIface;
52 
53 typedef enum temu_MemoryStat {
58 } temu_MemoryStat;
59 
60 // Private interface, this is not stable yet
61 typedef struct temu_MemorySpaceIface {
62  //! Map device (using the default MemAccessIface interface)
63  int (*mapDevice)(void *Obj, uint64_t Addr, uint64_t Len, temu_Object_ *Device,
64  uint32_t Flags);
65  //! Set attribute bit
66  void (*setAttr)(void *Obj, uint64_t Addr, uint64_t Len, temu_MemoryAttr Attr);
67  //! Clear attribute bit
68  void (*clearAttr)(void *Obj, uint64_t Addr, uint64_t Len,
69  temu_MemoryAttr Attr);
70  //! Get attributes for address
71  temu_MemoryAttrs (*getAttrs)(void *Obj, uint64_t Addr);
72 
73  //! Map device with named interface
74  int (*mapDeviceWithNamedIface)(void *Obj, uint64_t Addr, uint64_t Len,
75  temu_Object_ *Device, const char *IfaceName,
76  uint32_t Flags);
77 
78  //! Unmap devices in range
79  int (*unmapRange)(void *Obj, uint64_t Addr, uint64_t Len);
80 
81  //! Map device with interface pointer
82  int (*mapDeviceWithIface)(void *Obj, uint64_t Addr, uint64_t Len,
83  temu_Object_ *Device, temu_MemAccessIface *Iface,
84  uint32_t Flags);
85 
86  uint64_t (*getStat)(void *Obj, temu_MemoryStat Stat);
87 } temu_MemorySpaceIface;
88 
89 TEMU_IFACE_REFERENCE_TYPE(temu_MemorySpace);
90 #define TEMU_MEMORY_SPACE_IFACE_TYPE "temu::MemorySpaceIface"
91 
92 // Private interface, do not use directly
93 #define TEMU_PDC_PSEUDO_UNKNOWN_INSTR 0
94 #define TEMU_PDC_PSEUDO_EOP 1
95 #define TEMU_PDC_PSEUDO_TRAMPOLINE 2
96 #define TEMU_PDC_PSEUDO_POST_DS_0 3
97 #define TEMU_PDC_PSEUDO_POST_DS_1 4
98 #define TEMU_PDC_PSEUDO_ATTRIB_CHECK 5
99 #define TEMU_PDC_PSEUDO_PROFILE 6
100 #define TEMU_PDC_PSEUDO_PRE_TRAMPOLINE 7
101 #define TEMU_PDC_PSEUDO_IDLE 8
102 #define TEMU_PDC_PSEUDO_SKIP 9
103 #define TEMU_PDC_PSEUDO_CALL 10
104 #define TEMU_PDC_PSEUDO_CALL_AND_SKIP 11
105 #define TEMU_PDC_PSEUDO_MULTIPAGE 12
106 #define TEMU_PDC_PSEUDO_OP_COUNT 13
107 
108 typedef struct {
109  uint32_t Instruction;
110  uint32_t Operands;
111 } temu_IRInstruction;
112 
113 typedef struct {
114  temu_IRInstruction Inst;
115  uint64_t ExtParam;
116 } temu_ExtIRInstruction;
117 
118 typedef struct {
119  void *(*getPDC)(void *Obj, uint64_t Addr);
120  void (*allocPDC)(void *Obj, uint64_t Addr);
121  void (*disposePDC)(void *Obj, uint64_t Addr);
122  void (*writePDC)(void *Obj, uint64_t Addr, void *Inst);
123  void (*clearPDC)(void *Obj, uint64_t Addr);
124  void (*setPseudoOpHandler)(void *Obj, unsigned Opcode, uintptr_t Handler);
125  void (*installTrampoline)(void *Obj, uint64_t Addr,
126  void (*TrampHandler)(void *));
127  void (*installProfile)(void *Obj, uint64_t Addr);
128  void (*removeProfile)(void *Obj, uint64_t Addr);
129 
130  void (*installIdle)(void *Obj, uint64_t Addr);
131  void (*removeIdle)(void *Obj, uint64_t Addr);
132 
133  void (*setBT)(void *Obj, uint64_t Addr, void *BTP);
134 
135  temu_ExtIRInstruction *(*allocPDCChain)(void *Obj, uint64_t Addr);
136  void (*releasePDCChain)(void *Obj, uint64_t Addr);
137 
138  uint64_t (*irToPA)(void *obj, uint64_t addr);
139 
140 
141 } temu_PDCIface;
142 TEMU_IFACE_REFERENCE_TYPE(temu_PDC);
143 #define TEMU_PDC_IFACE_TYPE "PDCIface"
144 
145 /*!
146  * Read block of data via memory block transfer interfaces
147  * \param mem Pointer to memory space object
148  * \param buff The buffer to which the memory should be stored
149  * \param addr The address of the memory block to be read
150  * \param size The size to be read
151  * \param swap setting this to 0 indicates reading a byte array, 1 a
152  * uint16 array, 2 a uint32 array and 3 a uint64 array
153  *
154  * \result Negative on failures. Other values indicate success. The
155  * convention is to return the number of bytes read which should be
156  * == size.
157  */
159  uint32_t size, int swap);
160 
161 /*!
162  * Write block of data via memory block transfer interfaces
163  * \param mem Pointer to memory space object
164  * \param buff The buffer to which the memory should be stored
165  * \param addr The address, at which the write should be done
166  * \param size The size to be read
167  * \param swap Negative on failures. Other values indicate success.
168  *
169  * \result Negative on failure. Other values indicate success. The
170  * convention is to return the number of bytes written, which should
171  * be == size.
172  */
174  uint32_t size, int swap);
175 
176 
177 /*!
178  * Read block of data via large memory transactions.
179  * \param obj Memory space object
180  * \param addr Physical address inside memory space
181  * \param buff Data buffer
182  * \param unitSize Log size of transaction unit size (0 = u8, 1 = u16, 2 = u32, 3 = u64)
183  * \param size Number of units to transfer
184  * \param flags Memory transaction flags (e.g. TEMU_MT_LITTLE_ENDIAN)
185  * \result Negative on failures. Other values indicate success.
186  */
187 
189  unsigned unitSize, uint32_t size,
190  unsigned flags);
191 
192 /*!
193  * Write block of data via large memory transactions.
194  * \param obj Memory space object
195  * \param addr Physical address inside memory space
196  * \param buff Data buffer
197  * \param unitSize Log size of transaction unit size (0 = u8, 1 = u16, 2 = u32, 3 = u64)
198  * \param size Number of units to transfer
199  * \param flags Memory transaction flags (e.g. TEMU_MT_LITTLE_ENDIAN)
200  * \result Negative on failures. Other values indicate success.
201  */
203  const uint8_t *buff, unsigned unitSize,
204  uint32_t size, unsigned flags);
205 
206 /*!
207  * temu_memoryMap Maps an object into a memory space. The object must have an
208  * interface named MemAccessIface, of the type defined as
209  * TEMU_MEM_ACCESS_IFACE_TYPE
210  * \param Obj is the memory space object
211  * \param Addr the physical address
212  * \param Len the length in bytes
213  * \param MemObj is the object that is mapped into the memory space
214  * it needs to be of a class that follows the rules above
215  * \param Flags are flags that are copied into the
216  * memory transaction object's flag field when a transaction
217  * reaches an object
218  * \result Zero on success
219  */
221  void *MemObj, uint32_t Flags);
222 
223 /*!
224  * temu_memoryMapNamedIface Maps an object into a memory space using the named
225  * memory access interface. The interface named by IfaceName must be of the type
226  * TEMU_MEM_ACCESS_IFACE_TYPE
227  * \param Obj is the memory space object
228  * \param Addr the physical address \param Len the length in bytes
229  * \param MemObj is the object that is mapped into the memory space it needs to
230  * be of a class that follows the rules above
231  * \param IfaceName Name of the memory access interface
232  * \param Flags are flags that are copied into the memory transaction object's
233  * flag field when a transaction reaches an object
234  * \result Zero on success
235  */
237  void *MemObj, const char *IfaceName,
238  uint32_t Flags);
239 
241  void *MemObj, const char *IfaceName,
242  unsigned Idx, uint32_t Flags);
243 
244 /*!
245  * Sets an attribute on the given memory range
246  * \param Obj Memory space object
247  * \param Addr Physical address of start
248  * \param Len Length of memory range
249  * \param Attr Attribute to set
250  */
253 
254 /*!
255  * Clears an attribute on the given memory range
256  * \param Obj Memory space object
257  * \param Addr Physical address of start
258  * \param Len Length of memory range
259  * \param Attr Attribute to clear
260  */
263 
264 /*!
265  * Get memory attributes for address
266  * \param Obj Memory space
267  * \param Addr Physical addres
268  * \result Memory attributes for the address
269  */
270 TEMU_API temu_MemoryAttrs temu_memoryGetAttrs(void *Obj, uint64_t Addr);
271 
272 /*!
273  * Issue a big endian memory read transaction (without initiator)
274  * \param Obj Memory space
275  * \param Addr Physical address
276  * \param Word 16 bit word that is read
277  * \result 0 on success, other values imply failure and will not
278  * update the word.
279  */
281 /*!
282  * Issue a little endian memory read transaction (without initiator)
283  * \param Obj Memory space
284  * \param Addr Physical address
285  * \param Word 16 bit word that is read
286  * \result 0 on success, other values imply failure and will not
287  * update the word.
288  */
290 
291 /*!
292  * Issue a big endian memory read transaction (without initiator)
293  * \param Obj Memory space
294  * \param Addr Physical address
295  * \param Word 32 bit word that is read
296  * \result 0 on success, other values imply failure and will not
297  * update the word.
298  */
300 /*!
301  * Issue a little endian memory read transaction (without initiator)
302  * \param Obj Memory space
303  * \param Addr Physical address
304  * \param Word 32 bit word that is read
305  * \result 0 on success, other values imply failure and will not
306  * update the word.
307  */
309 
310 /*!
311  * Issue a big endian memory write transaction (without initiator)
312  * \param Obj Memory space
313  * \param Addr Physical address
314  * \param Word 32 bit word to write
315  * \result 0 on success
316  */
318 
319 /*!
320  * Issue a little endian memory write transaction (without initiator)
321  * \param Obj Memory space
322  * \param Addr Physical address
323  * \param Word 32 bit word to write
324  * \result 0 on success
325  */
327 
328 /*!
329  * Normalise a value for writes where only 32 bit transactions are
330  * supported by the device model, but the target is allowed to write
331  * non-32 bit quantity. The function mixes the old register value with
332  * the new one based on the size and offset parameter. The problem
333  * exists because the memory access interface has a value entry, which
334  * always ends up in the lower bits, so if we write to the higher bits
335  * in in a 32 bit register, then by just forwarding the the value as
336  * is to the write handler, will result in a write of the lower bits and
337  * a clear of the upper bits (for a store unsigned).
338  *
339  * Thus a normalisation is needed where we mix the written word with the old
340  * bits. So for transaction size of 16, and an offset of 16, the resulting
341  * word is (old & 0x0000ffff) | (new << 16)
342  *
343  * \param OldVal Old regiseter value.
344  * \param NewVal Content in memory transaction (new value).
345  * \param Sz Size in log number of bytes
346  * \param Off Offset in bytes within the 32 bit word of the transaction.
347  */
348 TEMU_API uint32_t temu_normaliseWrite32(uint32_t OldVal, uint32_t NewVal,
349  int Sz, int Off);
350 
351 /*!
352  * Normalise a value for reads where only 32 bit transactions are
353  * supported by the device model, but the target is allowed to read
354  * non-32 bit quantities.
355  *
356  * Given a 32 bit register value, the function extracts the bits from it
357  * that was actually requested.
358  *
359  * \param Value Register value
360  * \param Sz Size in log number of bytes (0, 1, or 2)
361  * \param Off Offset in bytes within the 32 bit word of the transaction (0-3)
362  */
363 TEMU_API uint32_t temu_normaliseRead32(uint32_t Value, int Sz, int Off);
364 
365 /*!
366  * Normalise a value for reads where only 16 bit transactions are
367  * supported by the device model, but the target is allowed to read
368  * non-16 bit quantities.
369  *
370  * Given a 32 bit register value, the function extracts the bits from it
371  * that was actually requested.
372  *
373  * \param Value Register value
374  * \param Sz Size in log number of bytes (0 or 1)
375  * \param Off Offset in bytes within the 32 bit word of the transaction (0 or 2)
376  */
377 TEMU_API uint16_t temu_normaliseRead16(uint16_t Value, int Sz, int Off);
378 
379 /*!
380  * Normalise a value for writes where only 16 bit transactions are
381  * supported by the device model, but the target is allowed to write
382  * non-16 bit quantity. The function mixes the old register value with
383  * the new one based on the size and offset parameter. The problem
384  * exists because the memory access interface has a value entry, which
385  * always ends up in the lower bits, so if we write to the higher bits
386  * in in a 16 bit register, then by just forwarding the the value as
387  * is to the write handler, will result in a write of the lower bits and
388  * a clear of the upper bits (for a store unsigned).
389  *
390  * Thus a normalisation is neded where we mix the written word with the old
391  * bits. So for transaction size of 8, and an offset of8, the resulting
392  * word is (old & 0x00ff) | (new << 8)
393  *
394  * \param OldVal Old regiseter value.
395  * \param NewVal Content in memory transaction (new value).
396  * \param Sz Size in log number of bytes
397  * \param Off Offset in bytes within the 16 bit word of the transaction.
398  */
399 
400 TEMU_API uint16_t temu_normaliseWrite16(uint16_t OldVal, uint16_t NewVal,
401  int Sz, int Off);
402 
403 /*!
404  * Install trampoline function in PDC cache
405  * \param Obj Memory space
406  * \param Addr Physical address
407  * \param Tramp Trampoline function, takes CPU pointer as first argument.
408  * \result 0 on success
409  */
411  void (*Tramp)(void *));
412 TEMU_API uint64_t temu_irToPhys(void *obj, uintptr_t ir);
413 
414 #ifdef __cplusplus
415 }
416 #endif
417 
418 #endif /* ! TEMU_SUPPORT_MEMORY */
temu_MemoryAttr
temu_MemoryAttr
Memory attribute enumeration.
Definition: Memory.h:40
temu_PDCIface::setPseudoOpHandler
void(* setPseudoOpHandler)(void *Obj, unsigned Opcode, uintptr_t Handler)
Definition: Memory.h:124
temu_memoryClearAttr
TEMU_API void temu_memoryClearAttr(void *Obj, uint64_t Addr, uint64_t Len, temu_MemoryAttr Attr)
temu_PDCIface::clearPDC
void(* clearPDC)(void *Obj, uint64_t Addr)
Definition: Memory.h:123
temu_MemAccessIface
struct temu_MemAccessIface temu_MemAccessIface
Definition: Memory.h:51
temu_PDCIface::writePDC
void(* writePDC)(void *Obj, uint64_t Addr, void *Inst)
Definition: Memory.h:122
temu_memoryRead
TEMU_API int temu_memoryRead(void *mem, uint8_t *buff, uint64_t addr, uint32_t size, int swap)
temu_PDCIface::installProfile
void(* installProfile)(void *Obj, uint64_t Addr)
Definition: Memory.h:127
temu_memoryReadData
TEMU_API int temu_memoryReadData(void *obj, uint64_t addr, uint8_t *buff, unsigned unitSize, uint32_t size, unsigned flags)
temu_PDCIface::setBT
void(* setBT)(void *Obj, uint64_t Addr, void *BTP)
Definition: Memory.h:133
temu_memorySetAttr
TEMU_API void temu_memorySetAttr(void *Obj, uint64_t Addr, uint64_t Len, temu_MemoryAttr Attr)
temu_memoryReadPhys32Little
TEMU_API int temu_memoryReadPhys32Little(void *Obj, uint64_t Addr, uint32_t *Word)
temu_PDCIface::disposePDC
void(* disposePDC)(void *Obj, uint64_t Addr)
Definition: Memory.h:121
teMA_User2
@ teMA_User2
User definable.
Definition: Memory.h:47
temu_memoryWriteData
TEMU_API int temu_memoryWriteData(void *obj, uint64_t addr, const uint8_t *buff, unsigned unitSize, uint32_t size, unsigned flags)
temu_ExtIRInstruction::ExtParam
uint64_t ExtParam
Definition: Memory.h:115
temu_ExtIRInstruction::Inst
temu_IRInstruction Inst
Definition: Memory.h:114
teMA_Upset
@ teMA_Upset
Single event upset.
Definition: Memory.h:44
temu_MemorySpaceIface::clearAttr
void(* clearAttr)(void *Obj, uint64_t Addr, uint64_t Len, temu_MemoryAttr Attr)
Clear attribute bit.
Definition: Memory.h:68
temu_memoryMapNamedIface
TEMU_API int temu_memoryMapNamedIface(void *Obj, uint64_t Addr, uint64_t Len, void *MemObj, const char *IfaceName, uint32_t Flags)
temu_memoryInstallTrampoline
TEMU_API int temu_memoryInstallTrampoline(void *Obj, uint64_t Addr, void(*Tramp)(void *))
teMS_CodeWrites
@ teMS_CodeWrites
Definition: Memory.h:57
temu_PDCIface::allocPDC
void(* allocPDC)(void *Obj, uint64_t Addr)
Definition: Memory.h:120
temu_MemorySpaceIface::unmapRange
int(* unmapRange)(void *Obj, uint64_t Addr, uint64_t Len)
Unmap devices in range.
Definition: Memory.h:79
temu_MemoryStat
temu_MemoryStat
Definition: Memory.h:53
teMK_IO
@ teMK_IO
Model is a normal IO device.
Definition: Memory.h:24
teMA_User3
@ teMA_User3
User definable.
Definition: Memory.h:48
teMK_Last
@ teMK_Last
DO NOT USE.
Definition: Memory.h:26
teMS_IOReads
@ teMS_IOReads
Definition: Memory.h:54
teMA_Faulty
@ teMA_Faulty
Multiple event upset / uncorrectable.
Definition: Memory.h:45
temu_memoryWritePhys32
TEMU_API int temu_memoryWritePhys32(void *Obj, uint64_t Addr, uint32_t Word)
temu_MemorySpaceIface::setAttr
void(* setAttr)(void *Obj, uint64_t Addr, uint64_t Len, temu_MemoryAttr Attr)
Set attribute bit.
Definition: Memory.h:66
temu_PDCIface::installTrampoline
void(* installTrampoline)(void *Obj, uint64_t Addr, void(*TrampHandler)(void *))
Definition: Memory.h:125
temu_PDCIface::removeProfile
void(* removeProfile)(void *Obj, uint64_t Addr)
Definition: Memory.h:128
teMS_SelfModifyingCodeWrites
@ teMS_SelfModifyingCodeWrites
Definition: Memory.h:56
temu_MemoryAttrs
uint8_t temu_MemoryAttrs
Definition: Memory.h:50
temu_memoryMap
TEMU_API int temu_memoryMap(void *Obj, uint64_t Addr, uint64_t Len, void *MemObj, uint32_t Flags)
teMK_MemSpace
@ teMK_MemSpace
Model is a memory space.
Definition: Memory.h:25
teMA_WatchRead
@ teMA_WatchRead
Read watchpoint set.
Definition: Memory.h:42
temu_MemorySpaceIface::mapDeviceWithNamedIface
int(* mapDeviceWithNamedIface)(void *Obj, uint64_t Addr, uint64_t Len, temu_Object_ *Device, const char *IfaceName, uint32_t Flags)
Map device with named interface.
Definition: Memory.h:74
temu_memoryWritePhys32Little
TEMU_API int temu_memoryWritePhys32Little(void *Obj, uint64_t Addr, uint32_t Word)
teMA_User1
@ teMA_User1
User definable.
Definition: Memory.h:46
teMK_ROM
@ teMK_ROM
Model is a ROM.
Definition: Memory.h:22
teMK_MMIO
@ teMK_MMIO
Alias for teMK_IO
Definition: Memory.h:23
temu_PDCIface::installIdle
void(* installIdle)(void *Obj, uint64_t Addr)
Definition: Memory.h:130
teMK_RAM
@ teMK_RAM
Model is a RAM.
Definition: Memory.h:21
temu_IRInstruction::Instruction
uint32_t Instruction
Definition: Memory.h:109
teMS_IOWrites
@ teMS_IOWrites
Definition: Memory.h:55
temu_memoryReadPhys32
TEMU_API int temu_memoryReadPhys32(void *Obj, uint64_t Addr, uint32_t *Word)
temu_memoryMapNamedIface2
TEMU_API int temu_memoryMapNamedIface2(void *Obj, uint64_t Addr, uint64_t Len, void *MemObj, const char *IfaceName, unsigned Idx, uint32_t Flags)
teMA_WatchWrite
@ teMA_WatchWrite
Write watchpoint set.
Definition: Memory.h:43
temu_MemoryKind
temu_MemoryKind
Definition: Memory.h:20
temu_memoryReadPhys16
TEMU_API int temu_memoryReadPhys16(void *Obj, uint64_t Addr, uint16_t *Word)
temu_memoryWrite
TEMU_API int temu_memoryWrite(void *mem, uint64_t addr, uint8_t *buff, uint32_t size, int swap)
temu_MemorySpaceIface::mapDeviceWithIface
int(* mapDeviceWithIface)(void *Obj, uint64_t Addr, uint64_t Len, temu_Object_ *Device, temu_MemAccessIface *Iface, uint32_t Flags)
Map device with interface pointer.
Definition: Memory.h:82
temu_MemorySpaceIface::mapDevice
int(* mapDevice)(void *Obj, uint64_t Addr, uint64_t Len, temu_Object_ *Device, uint32_t Flags)
Map device (using the default MemAccessIface interface)
Definition: Memory.h:63
teMA_Break
@ teMA_Break
Breakpoint set.
Definition: Memory.h:41
temu_MemorySpaceIface
Definition: Memory.h:61
temu_PDCIface::getPDC
void *(* getPDC)(void *Obj, uint64_t Addr)
Definition: Memory.h:119
temu_IRInstruction::Operands
uint32_t Operands
Definition: Memory.h:110
temu_PDCIface::removeIdle
void(* removeIdle)(void *Obj, uint64_t Addr)
Definition: Memory.h:131
temu_memoryReadPhys16Little
TEMU_API int temu_memoryReadPhys16Little(void *Obj, uint64_t Addr, uint16_t *Word)
temu_PDCIface::releasePDCChain
void(* releasePDCChain)(void *Obj, uint64_t Addr)
Definition: Memory.h:136