qemu-2.5.0-eos.patch 53.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
diff --git a/configure b/configure
index b9552fd..9aeaae3 100755
--- a/configure
+++ b/configure
@@ -3612,7 +3612,7 @@ fi
 # check if memfd is supported
 memfd=no
 cat > $TMPC << EOF
-#include <sys/memfd.h>
+#include <sys/mman.h>
 
 int main(void)
 {
14
diff --git a/cpu-exec.c b/cpu-exec.c
15
index c88d0ff..4395bb3 100644
16
17
--- a/cpu-exec.c
+++ b/cpu-exec.c
18
19
20
21
22
23
24
25
@@ -31,6 +31,7 @@
 #include "hw/i386/apic.h"
 #endif
 #include "sysemu/replay.h"
+#include "hw/boards.h"
 
 /* -icount align implementation. */
 
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@@ -332,6 +333,16 @@ static void cpu_handle_debug_exception(CPUState *cpu)
     cc->debug_excp_handler(cpu);
 }
 
+static void (*tb_exec_cb)(void *opaque, CPUState *cpu, TranslationBlock *tb);
+static void * tb_exec_opaque;
+
+void cpu_set_tb_exec_cb(void (*cb)(void *opaque, CPUState *cpu, TranslationBlock *tb),
+                        void *opaque)
+{
+    tb_exec_cb = cb;
+    tb_exec_opaque = opaque;
+}
+
 /* main execution loop */
 
 int cpu_exec(CPUState *cpu)
43
@@ -500,8 +511,28 @@ int cpu_exec(CPUState *cpu)
44
45
46
47
48
49
50
51
52
                     tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
                 }
                 if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
+#if defined(TARGET_ARM)
+                    /* rather than logging just PC, also log the disassembled code */
+                    if (!singlestep) {
+                        /* separate translation blocks by newlines */
+                        qemu_log("\n");
+                    }
53
54
55
56
57
58
59
60
+                    /* some instructions are printed more than once, not sure why */
+                    static int prev_pc = -1;
+                    if (tb->pc != prev_pc) {
+                        prev_pc = tb->pc;
+                        if (CPU_NEXT(first_cpu)) {
+                            qemu_log("[CPU%d] ", current_cpu->cpu_index);
+                        }
+                        log_target_disas(cpu, tb->pc, tb->size, 0);
61
+                    }
62
63
64
+#else
                     qemu_log("Trace %p [" TARGET_FMT_lx "] %s\n",
                              tb->tc_ptr, tb->pc, lookup_symbol(tb->pc));
65
66
+#endif
+                }
67
68
+                if (tb_exec_cb) {
+                    tb_exec_cb(tb_exec_opaque, cpu, tb);
69
70
71
                 }
                 /* see if we can patch the calling TB. When the TB
                    spans two pages, we cannot safely do a direct
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
diff --git a/disas/arm.c b/disas/arm.c
index 7a7354b..95f82cc 100644
--- a/disas/arm.c
+++ b/disas/arm.c
@@ -2826,9 +2826,9 @@ print_insn_arm_internal (bfd_vma pc, struct disassemble_info *info, long given)
 		      if ((given & 0x02000000) != 0)
 			{
 			  int rotate = (given & 0xf00) >> 7;
-			  int immed = (given & 0xff);
-			  immed = (((immed << (32 - rotate))
-				    | (immed >> rotate)) & 0xffffffff);
+			  int64_t immed64 = (given & 0xff);
+			  int immed = (((immed64 << (32 - rotate))
+				      | (immed64 >> rotate)) & 0xffffffff);
 			  func (stream, "#%d\t; 0x%x", immed, immed);
 			}
 		      else
@@ -3868,7 +3868,7 @@ int
 print_insn_arm (bfd_vma pc, struct disassemble_info *info)
 {
   unsigned char b[4];
-  long		given;
+  unsigned long given;
   int           status;
   int           is_thumb = false;
   int           is_data = false;
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
diff --git a/exec.c b/exec.c
index 0bf0a6e..5eb69de 100644
--- a/exec.c
+++ b/exec.c
@@ -2564,7 +2564,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
             } else {
                 addr1 += memory_region_get_ram_addr(mr);
                 /* RAM case */
-                ptr = qemu_get_ram_ptr(addr1);
+                ptr = qemu_ram_ptr_length(addr1, &l);
                 memcpy(ptr, buf, l);
                 invalidate_and_set_dirty(mr, addr1, l);
             }
@@ -2603,7 +2603,7 @@ MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
                 }
             } else {
                 /* RAM case */
-                ptr = qemu_get_ram_ptr(mr->ram_addr + addr1);
+                ptr = qemu_ram_ptr_length(mr->ram_addr + addr1, &l);
                 memcpy(buf, ptr, l);
             }
         }
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
diff --git a/gdbstub.c b/gdbstub.c
index 9c29aa0..a95ec8d 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -431,6 +431,7 @@ static inline int tohex(int v)
         return v - 10 + 'a';
 }
 
+/* writes 2*len+1 bytes in buf */
 static void memtohex(char *buf, const uint8_t *mem, int len)
 {
     int i, c;
@@ -787,8 +788,8 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
     const char *p;
     uint32_t thread;
     int ch, reg_size, type, res;
-    char buf[MAX_PACKET_LENGTH];
     uint8_t mem_buf[MAX_PACKET_LENGTH];
+    char buf[sizeof(mem_buf) + 1 /* trailing NUL */];
     uint8_t *registers;
     target_ulong addr, len;
 
a1ex's avatar
a1ex committed
142
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
alex@thinkpad's avatar
alex@thinkpad committed
143
index 2195b60..e3e2c14 100644
a1ex's avatar
a1ex committed
144
145
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
alex@thinkpad's avatar
alex@thinkpad committed
146
147
@@ -6,6 +6,7 @@ obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o
 obj-$(CONFIG_ACPI) += virt-acpi-build.o
a1ex's avatar
a1ex committed
148
 obj-y += netduino2.o
alex@thinkpad's avatar
alex@thinkpad committed
149
 obj-y += sysbus-fdt.o
150
+include ../hw/eos/Makefile.objs
a1ex's avatar
a1ex committed
151
152
153
 
 obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
 obj-$(CONFIG_DIGIC) += digic.o
154
155
156
157
158
159
160
161
162
163
164
165
166
diff --git a/hw/arm/digic.c b/hw/arm/digic.c
index 90f8190..8e934be 100644
--- a/hw/arm/digic.c
+++ b/hw/arm/digic.c
@@ -36,7 +36,7 @@ static void digic_init(Object *obj)
     object_property_add_child(obj, "cpu", OBJECT(&s->cpu), NULL);
 
     for (i = 0; i < DIGIC4_NB_TIMERS; i++) {
-#define DIGIC_TIMER_NAME_MLEN    11
+#define DIGIC_TIMER_NAME_MLEN    20
         char name[DIGIC_TIMER_NAME_MLEN];
 
         object_initialize(&s->timer[i], sizeof(s->timer[i]), TYPE_DIGIC_TIMER);
167
168
169
170
171
172
173
174
175
176
177
178
179
diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index 45239e8..825d6e6 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -97,7 +97,7 @@
 #define FIMD_WINCON_BUFSTATUS       ((1 << 21) | (1 << 31))
 #define FIMD_WINCON_BUF0_STAT       ((0 << 21) | (0 << 31))
 #define FIMD_WINCON_BUF1_STAT       ((1 << 21) | (0 << 31))
-#define FIMD_WINCON_BUF2_STAT       ((0 << 21) | (1 << 31))
+#define FIMD_WINCON_BUF2_STAT       ((0 << 21) | (1U << 31))
 #define FIMD_WINCON_BUFSELECT       ((1 << 20) | (1 << 30))
 #define FIMD_WINCON_BUF0_SEL        ((0 << 20) | (0 << 30))
 #define FIMD_WINCON_BUF1_SEL        ((1 << 20) | (0 << 30))
180
181
182
183
184
185
186
187
188
189
190
191
192
193
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 788b361..6aaeced 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -245,7 +245,8 @@ static void ide_dev_instance_init(Object *obj)
 
 static int ide_hd_initfn(IDEDevice *dev)
 {
-    return ide_dev_initfn(dev, IDE_HD);
+    /* fixme: forcing IDE type to IDE_CFATA (was ID_HD) */
+    return ide_dev_initfn(dev, IDE_CFATA);
 }
 
 static int ide_cd_initfn(IDEDevice *dev)
194
195
196
197
198
199
200
201
202
203
204
205
206
207
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 1a9935c..2561560 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -1479,6 +1479,9 @@ static void sd_blk_write(SDState *sd, uint64_t addr, uint32_t len)
 {
     uint64_t end = addr + len;
 
+    DPRINTF("sd_blk_write: addr = 0x%08llx, len = %d\n",
+            (unsigned long long) addr, len);
+
     if ((addr & 511) || len < 512)
         if (!sd->blk || blk_read(sd->blk, addr >> 9, sd->buf, 1) < 0) {
             fprintf(stderr, "sd_blk_write: read error on host side\n");
208
209
210
211
212
213
214
215
216
217
218
219
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index d900b0d..1ad5332 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -405,4 +405,7 @@ extern int singlestep;
 extern CPUState *tcg_current_cpu;
 extern bool exit_request;
 
+void cpu_set_tb_exec_cb(void (*cb)(void *opaque, CPUState *cpu, TranslationBlock *tb),
+                        void *opaque);
+
 #endif
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 0f07159..40c3940 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -1356,6 +1356,19 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
                          int is_write, hwaddr access_len);
 
 
+/* memory_set_access_logging_cb: allow logging guest memory accesses
+ * using callbacks.
+ * 
+ * Currently implemented only for ARM 32-bit (LDR/STR).
+ * 
+ * @mem_log_cb: callback to be called when memory access takes place
+ * @opaque: argument passed to mem_log_cb
+ * @access_mode: bit field (PROT_READ, PROT_WRITE); fixme - better constants? define new ones?
+ */
+void memory_set_access_logging_cb(
+    void (*mem_log_cb)(void * opaque, hwaddr addr, uint64_t value, unsigned size, int is_write),
+    void * opaque, int access_mode);
+
 #endif
 
 #endif
244
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
245
index 0010c44..d85cc6b 100644
246
247
--- a/include/hw/elf_ops.h
+++ b/include/hw/elf_ops.h
248
@@ -140,8 +140,11 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
249
250
251
252
253
         /* We are only interested in function symbols.
            Throw everything else away.  */
         if (syms[i].st_shndx == SHN_UNDEF ||
-                syms[i].st_shndx >= SHN_LORESERVE ||
-                ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
254
255
256
+           (!(syms[i].st_shndx == SHN_ABS &&         /* allow ABS symbols (ML stubs) */
+              ELF_ST_TYPE(syms[i].st_info) == STT_NOTYPE &&
+              syms[i].st_size == 0) &&
257
258
259
260
261
+              (syms[i].st_shndx >= SHN_LORESERVE ||
+               ELF_ST_TYPE(syms[i].st_info) != STT_FUNC))) {
             nsyms--;
             if (i < nsyms) {
                 syms[i] = syms[nsyms];
262
263
264
@@ -157,9 +160,13 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
     syms = g_realloc(syms, nsyms * sizeof(*syms));
 
265
     qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ));
266
267
-    for (i = 0; i < nsyms - 1; i++) {
+    for (i = 0; i < nsyms; i++) {
268
269
         if (syms[i].st_size == 0) {
-            syms[i].st_size = syms[i + 1].st_value - syms[i].st_value;
270
+            if (syms[i].st_shndx == SHN_ABS) {
271
+                syms[i].st_size = 4;
272
273
+            } else if (i + 1 < nsyms) {
+                syms[i].st_size = syms[i + 1].st_value - syms[i].st_value;
274
275
276
277
+            }
         }
     }
 
278
diff --git a/include/qemu/log.h b/include/qemu/log.h
279
index 362cbc4..7859c5f 100644
280
281
--- a/include/qemu/log.h
+++ b/include/qemu/log.h
282
283
284
285
286
287
288
289
290
@@ -12,7 +12,7 @@
 
 /* Private global variables, don't use */
 extern FILE *qemu_logfile;
-extern int qemu_loglevel;
+extern uint64_t qemu_loglevel;
 
 /* 
  * The new API:
291
@@ -42,9 +42,50 @@ static inline bool qemu_log_enabled(void)
292
293
294
 #define CPU_LOG_MMU        (1 << 12)
 #define CPU_LOG_TB_NOCHAIN (1 << 13)
 
295
296
297
+/* various EOS options */
+/* some of them are just defined for future use */
+#define EOS_LOG_IO         (1LL << 21)
298
299
300
301
302
303
304
305
+#define EOS_LOG_IO_LOG     (1LL << 22)
+#define EOS_LOG_UART       (1LL << 23)
+#define EOS_LOG_MPU        (1LL << 24)
+#define EOS_LOG_SDCF       (1LL << 25)
+#define EOS_LOG_SFLASH     (1LL << 26)
+#define EOS_LOG_PFLASH     (1LL << 27)
+#define EOS_LOG_DMA        (1LL << 28)
+#define EOS_LOG_EDMAC      (1LL << 29)
306
+
307
308
309
+#define EOS_LOG_VERBOSE    (1LL << 32)
+#define EOS_LOG_AUTOEXEC   (1LL << 33)
+
310
+/* guest memory tracing (logging) */
311
312
313
314
+#define EOS_LOG_RAM_R      (1LL << 40)      /* memory logging backends */
+#define EOS_LOG_RAM_W      (1LL << 41)      /* used by other analysis tools, but not printed directly */
+#define EOS_LOG_ROM_R      (1LL << 42)      /* these backends have additional overhead on generated code */
+#define EOS_LOG_ROM_W      (1LL << 43)      /* so they are only enabled when actually used */
315
316
317
318
319
+#define EOS_LOG_RAM        (EOS_LOG_RAM_R | EOS_LOG_RAM_W)
+#define EOS_LOG_ROM        (EOS_LOG_ROM_R | EOS_LOG_ROM_W)
+#define EOS_LOG_MEM_R      (EOS_LOG_RAM_R | EOS_LOG_ROM_R)
+#define EOS_LOG_MEM_W      (EOS_LOG_RAM_W | EOS_LOG_ROM_W)
+#define EOS_LOG_MEM        (EOS_LOG_RAM   | EOS_LOG_ROM)
320
321
322
323
324
+#define EOS_PR(mem_flag)  ((mem_flag) << 4) /* memory logging printed in logs (duplicate the above flags) */
+                                            /* this will take 4 bits: 40-43 => 44-47 */
+#define EOS_LOG_RAM_DBG    (1LL << 48)      /* self-test */
+#define EOS_LOG_TASKS      (1LL << 49)      /* task switches */
+#define EOS_LOG_DEBUGMSG   (1LL << 50)      /* DebugMsg calls */
325
326
+
+/* analysis tools */
327
328
329
330
331
332
333
+#define EOS_LOG_CALLSTACK  (1LL << 51)      /* backend: provide call stack to other tools */
+#define EOS_LOG_CALLS      (1LL << 52)      /* log all calls and returns to console */
+#define EOS_LOG_IDC        (1LL << 53)      /* export unique calls to IDA */
+#define EOS_LOG_RAM_MEMCHK (1LL << 54)      /* like valgrind memcheck */
+#define EOS_LOG_RAM_TSKMEM (1LL << 55)      /* check task memory ownership assumptions */
+#define EOS_LOG_RAM_SEMCHK (1LL << 56)      /* check semaphore usage (like helgrind) */
+#define EOS_LOG_ROMCPY     (1LL << 57)      /* find memory blocks copied from ROM to RAM */
334
+#define EOS_LOG_NO_TAIL_CALLS (1LL << 58)   /* don't attempt to identify tail calls */
335
336
337
+
 /* Returns true if a bit is set in the current loglevel mask
  */
338
339
340
341
342
-static inline bool qemu_loglevel_mask(int mask)
+static inline bool qemu_loglevel_mask(uint64_t mask)
 {
     return (qemu_loglevel & mask) != 0;
 }
343
@@ -67,7 +108,7 @@ qemu_log_vprintf(const char *fmt, va_list va)
344
345
346
347
348
349
350
351
 
 /* log only if a bit is set on the current loglevel mask
  */
-void GCC_FMT_ATTR(2, 3) qemu_log_mask(int mask, const char *fmt, ...);
+void GCC_FMT_ATTR(2, 3) qemu_log_mask(uint64_t mask, const char *fmt, ...);
 
 
 /* Special cases: */
352
@@ -95,7 +136,7 @@ static inline void log_cpu_state(CPUState *cpu, int flags)
353
354
355
356
357
358
359
360
  *
  * Logs the output of cpu_dump_state() if loglevel includes @mask.
  */
-static inline void log_cpu_state_mask(int mask, CPUState *cpu, int flags)
+static inline void log_cpu_state_mask(uint64_t mask, CPUState *cpu, int flags)
 {
     if (qemu_loglevel & mask) {
         log_cpu_state(cpu, flags);
361
@@ -152,7 +193,7 @@ static inline void qemu_log_set_file(FILE *f)
362
363
364
365
366
367
368
369
 
 /* define log items */
 typedef struct QEMULogItem {
-    int mask;
+    uint64_t mask;
     const char *name;
     const char *help;
 } QEMULogItem;
370
@@ -163,9 +204,9 @@ extern const QEMULogItem qemu_log_items[];
371
372
373
374
375
376
377
378
379
380
381
  * changing the log level; it should only be accessed via
  * the qemu_set_log() wrapper.
  */
-void do_qemu_set_log(int log_flags, bool use_own_buffers);
+void do_qemu_set_log(uint64_t log_flags, bool use_own_buffers);
 
-static inline void qemu_set_log(int log_flags)
+static inline void qemu_set_log(uint64_t log_flags)
 {
 #ifdef CONFIG_USER_ONLY
     do_qemu_set_log(log_flags, true);
382
@@ -175,7 +216,7 @@ static inline void qemu_set_log(int log_flags)
383
384
385
386
387
388
389
390
 }
 
 void qemu_set_log_filename(const char *filename);
-int qemu_str_to_log_mask(const char *str);
+uint64_t qemu_str_to_log_mask(const char *str);
 
 /* Print a usage message listing all the valid logging categories
  * to the specified FILE*.
a1ex's avatar
a1ex committed
391
diff --git a/memory.c b/memory.c
alex@thinkpad's avatar
alex@thinkpad committed
392
index e193658..9de7251 100644
a1ex's avatar
a1ex committed
393
394
--- a/memory.c
+++ b/memory.c
alex@thinkpad's avatar
alex@thinkpad committed
395
@@ -1761,7 +1761,7 @@ static void memory_region_update_container_subregions(MemoryRegion *subregion)
a1ex's avatar
a1ex committed
396
397
398
399
400
401
402
403
                          int128_make64(other->addr))) {
             continue;
         }
-#if 0
+#if 1
         printf("warning: subregion collision %llx/%llx (%s) "
                "vs %llx/%llx (%s)\n",
                (unsigned long long)offset,
alex@thinkpad's avatar
alex@thinkpad committed
404
@@ -1798,6 +1798,9 @@ void memory_region_add_subregion(MemoryRegion *mr,
a1ex's avatar
a1ex committed
405
406
407
408
409
410
411
412
413
                                  hwaddr offset,
                                  MemoryRegion *subregion)
 {
+    fprintf(stderr, "%08X - %08X: %s\n",
+                     (int)offset, (int)offset + (int)subregion->size.lo - 1,
+                     subregion->name);
     subregion->may_overlap = false;
     subregion->priority = 0;
     memory_region_add_subregion_common(mr, offset, subregion);
414
diff --git a/qemu-log.c b/qemu-log.c
415
index 7cb01a8..7b57b2e 100644
416
417
--- a/qemu-log.c
+++ b/qemu-log.c
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
@@ -22,7 +22,7 @@
 
 static char *logfilename;
 FILE *qemu_logfile;
-int qemu_loglevel;
+uint64_t qemu_loglevel;
 static int log_append = 0;
 
 void qemu_log(const char *fmt, ...)
@@ -36,7 +36,7 @@ void qemu_log(const char *fmt, ...)
     va_end(ap);
 }
 
-void qemu_log_mask(int mask, const char *fmt, ...)
+void qemu_log_mask(uint64_t mask, const char *fmt, ...)
 {
     va_list ap;
 
@@ -48,7 +48,7 @@ void qemu_log_mask(int mask, const char *fmt, ...)
 }
 
 /* enable or disable low levels log */
-void do_qemu_set_log(int log_flags, bool use_own_buffers)
+void do_qemu_set_log(uint64_t log_flags, bool use_own_buffers)
 {
     qemu_loglevel = log_flags;
     if (qemu_loglevel && !qemu_logfile) {
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
@@ -99,7 +99,7 @@ const QEMULogItem qemu_log_items[] = {
       "show micro ops for each compiled TB" },
     { CPU_LOG_TB_OP_OPT, "op_opt",
       "show micro ops (x86 only: before eflags optimization) and\n"
-      "after liveness analysis" },
+      "           after liveness analysis" },
     { CPU_LOG_INT, "int",
       "show interrupts/exceptions in short format" },
     { CPU_LOG_EXEC, "exec",
@@ -116,10 +116,67 @@ const QEMULogItem qemu_log_items[] = {
       "log unimplemented functionality" },
     { LOG_GUEST_ERROR, "guest_errors",
       "log when the guest OS does something invalid (eg accessing a\n"
-      "non-existent register)" },
+      "           non-existent register)" },
460
461
     { CPU_LOG_TB_NOCHAIN, "nochain",
       "do not chain compiled TBs so that \"exec\" and \"cpu\" show\n"
462
463
-      "complete traces" },
+      "           complete traces; implies -singlestep" },
464
+      
465
466
467
468
469
470
471
+    { EOS_LOG_IO | CPU_LOG_TB_NOCHAIN, "io",
+      "EOS: log low-level I/O activity (implies nochain,singlestep)" },
+    { EOS_LOG_IO, "io_quick",
+      "EOS: log low-level I/O activity (without nochain,singlestep; PC not exact)" },
+    { EOS_LOG_IO_LOG | EOS_LOG_IO | CPU_LOG_TB_NOCHAIN, "io_log",
+      "EOS: for every I/O read, export a mmio_log entry to use in dm-spy-extra.c\n"
+      "                (dm-spy-experiments branch) to see the values from physical hardware." },
472
473
+    { EOS_LOG_MPU, "mpu",
+      "EOS: log low-level MPU activity" },
474
475
+    { EOS_LOG_SFLASH, "sflash",
+      "EOS: log low-level serial flash activity" },
476
477
+    { EOS_LOG_SDCF, "sdcf",
+      "EOS: log low-level SD/CF activity" },
478
479
+    { EOS_LOG_UART, "uart",
+      "EOS: log low-level UART activity" },
480
+
481
+    { EOS_PR(EOS_LOG_RAM) | EOS_LOG_RAM, "ram",
482
+      "EOS: log all RAM reads and writes" },
483
+    { EOS_PR(EOS_LOG_ROM) | EOS_LOG_ROM, "rom",
484
+      "EOS: log all ROM reads and writes" },
485
+    { EOS_PR(EOS_LOG_RAM_R) | EOS_LOG_RAM_R, "ramr",
486
+      "EOS: log all RAM reads" },
487
+    { EOS_PR(EOS_LOG_ROM_R) | EOS_LOG_ROM_R, "romr",
488
+      "EOS: log all ROM reads" },
489
+    { EOS_PR(EOS_LOG_RAM_W) | EOS_LOG_RAM_W, "ramw",
490
+      "EOS: log all RAM writes" },
491
+    { EOS_PR(EOS_LOG_ROM_W) | EOS_LOG_ROM_W, "romw",
492
+      "EOS: log all ROM writes" },
493
494
+    { EOS_LOG_RAM_DBG | EOS_LOG_RAM, "ram_dbg",
+      "EOS: self-test for the RAM logging routines" },
495
+
496
497
+    { EOS_LOG_CALLSTACK | CPU_LOG_TB_NOCHAIN, "callstack",
+      "EOS: reconstruct call stack (implies nochain,singlestep)" },
498
499
+    { EOS_LOG_CALLS | EOS_LOG_CALLSTACK | CPU_LOG_TB_NOCHAIN | EOS_LOG_RAM_R, "calls",
+      "EOS: log function calls (implies callstack,nochain,singlestep; monitors RAM reads)" },
500
501
+    { EOS_LOG_NO_TAIL_CALLS, "notail",
+      "EOS: don't identify tail calls (for troubleshooting)" },
502
503
+    { EOS_LOG_IDC | EOS_LOG_CALLSTACK | CPU_LOG_TB_NOCHAIN, "idc",
+      "EOS: export called functions to IDA (implies callstack,nochain,singlestep)" },
504
+    { EOS_LOG_TASKS, "tasks",
505
506
507
+      "EOS: log task switches (.current_task_addr must be defined)" },
+    { EOS_LOG_DEBUGMSG, "debugmsg",
+      "EOS: log DebugMsg calls (QEMU_EOS_DEBUGMSG must be defined)" },
508
509
+    { EOS_LOG_ROMCPY | EOS_LOG_ROM_R | EOS_LOG_RAM_W, "romcpy",
+      "EOS: find memory blocks copied from ROM to RAM" },
510
511
512
+
+    { EOS_LOG_RAM_MEMCHK | EOS_LOG_RAM, "memchk",
+      "EOS: check memory usage (malloc/free, uninitialized values)" },
513
+
514
515
516
+    { EOS_LOG_AUTOEXEC, "autoexec",
+      "EOS: start verbose logging when autoexec.bin is loaded (quiet logging for bootloader)" },
+
517
518
519
520
+    { EOS_LOG_VERBOSE, "v", "" },
+    { EOS_LOG_VERBOSE, "verbose",
+      "EOS: very detailed debug messages" },
+
521
522
523
     { 0, NULL, NULL },
 };
 
524
@@ -132,10 +189,10 @@ static int cmp1(const char *s1, int n, const char *s2)
525
526
527
528
529
530
531
532
533
534
535
536
 }
 
 /* takes a comma separated list of log masks. Return 0 if error. */
-int qemu_str_to_log_mask(const char *str)
+uint64_t qemu_str_to_log_mask(const char *str)
 {
     const QEMULogItem *item;
-    int mask;
+    uint64_t mask;
     const char *p, *p1;
 
     p = str;
537
538
539
540
541
542
543
544
545
546
547
548
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index 25fb1ce..c180f78 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -141,6 +141,7 @@ typedef struct ARMCPU {
     uint32_t mvfr1;
     uint32_t mvfr2;
     uint32_t ctr;
+    uint32_t tcmtr;
     uint32_t reset_sctlr;
     uint32_t id_pfr0;
     uint32_t id_pfr1;
a1ex's avatar
a1ex committed
549
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
550
index 30739fc..e332483 100644
a1ex's avatar
a1ex committed
551
552
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
553
@@ -501,6 +501,7 @@ static void arm_cpu_initfn(Object *obj)
alex@thinkpad's avatar
alex@thinkpad committed
554
555
556
557
558
 static Property arm_cpu_reset_cbar_property =
             DEFINE_PROP_UINT64("reset-cbar", ARMCPU, reset_cbar, 0);
 
+/* fixme: how to change this property from machine code? */
 static Property arm_cpu_reset_hivecs_property =
559
             DEFINE_PROP_BOOL("reset-hivecs", ARMCPU, reset_hivecs, false);
alex@thinkpad's avatar
alex@thinkpad committed
560
 
561
562
563
564
565
566
567
568
569
570
571
@@ -513,8 +514,9 @@ static Property arm_cpu_has_el3_property =
 static Property arm_cpu_has_mpu_property =
             DEFINE_PROP_BOOL("has-mpu", ARMCPU, has_mpu, true);
 
+/* fixme: how to change this property from machine code? */
 static Property arm_cpu_pmsav7_dregion_property =
-            DEFINE_PROP_UINT32("pmsav7-dregion", ARMCPU, pmsav7_dregion, 16);
+            DEFINE_PROP_UINT32("pmsav7-dregion", ARMCPU, pmsav7_dregion, 8);
 
 static void arm_cpu_post_init(Object *obj)
 {
572
@@ -711,6 +713,103 @@ static void arm926_initfn(Object *obj)
a1ex's avatar
a1ex committed
573
574
575
     cpu->reset_sctlr = 0x00090078;
 }
 
576
+static void arm946_eos_initfn(Object *obj)
a1ex's avatar
a1ex committed
577
+{
578
+    /* https://chdk.setepontos.com/index.php?topic=2139.msg19836#msg19836 */
a1ex's avatar
a1ex committed
579
580
581
+    ARMCPU *cpu = ARM_CPU(obj);
+    set_feature(&cpu->env, ARM_FEATURE_V5);
+    set_feature(&cpu->env, ARM_FEATURE_MPU);
582
583
584
+    cpu->midr        = 0x41059461;
+    cpu->ctr         = 0x0F112112;                /* DIGIC 5: 0x0F192192 */
+    cpu->tcmtr       = 0x000C00C0;
585
+    cpu->reset_sctlr = 0x00000078 | (1 << 13);    /* fixme: how to change the HIVECS property? */
586
+    set_feature(&cpu->env, ARM_FEATURE_946EOS);
a1ex's avatar
a1ex committed
587
+}
588
+
589
590
591
592
593
594
595
596
597
+static void arm946_eos5_initfn(Object *obj)
+{
+    /* mostly identical to DIGIC 2..4, with minor differences */
+    arm946_eos_initfn(obj);
+
+    ARMCPU *cpu = ARM_CPU(obj);
+    cpu->ctr = 0x0F192192;
+}
+
alex@thinkpad's avatar
alex@thinkpad committed
598
599
+static void cortex_r5_initfn(Object *obj);
+
600
+static void cortex_r4_eos_initfn(Object *obj)
601
+{
602
+    /* Cortex R4: https://chdk.setepontos.com/index.php?topic=11316.msg124273#msg124273 */
alex@thinkpad's avatar
alex@thinkpad committed
603
+    cortex_r5_initfn(obj);
604
605
+
+    /* https://www.magiclantern.fm/forum/index.php?topic=17714.0 */
606
+    ARMCPU *cpu = ARM_CPU(obj);
607
608
+    cpu->midr        = 0x411FC143;
+    cpu->ctr         = 0x8003C003;
609
+    cpu->tcmtr       = 0x00010001;
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
+    cpu->id_mmfr3    = 0x00000011;
+    cpu->id_isar0    = 0x01101111;
+    cpu->id_isar2    = 0x21232131;
+    cpu->clidr       = 0x09000003;
+    cpu->ccsidr[0]   = 0xF00FE019;
+    cpu->ccsidr[1]   = 0xF00FE019;
+    cpu->dbgdidr     = 0x77040013;  /* https://www.magiclantern.fm/forum/index.php?topic=17360.msg202322#msg202322 */
+    cpu->reset_sctlr = 0x08E50878 | (1 << 13);    /* fixme: how to change the HIVECS property? */
+    //        1=MPU,        2=align,      4=DCacheL1,  8=SBO        => 8
+    //       10=SBO,       20=SBO,       40=SBO,      80=SBZ        => 7
+    //      100=SBZ,      200=SBZ,      400=SBZ,     800=Z(SBO)     => 8
+    //     1000=ICacheL1,2000=HIVECS,  4000=RR,     8000=SBZ        => 2 (1 << 13)
+    //    10000=SBO,    20000=BR,     40000=SBO,   80000=DZ         => 5
+    //   100000=SBZ,   200000=FI/SBO,400000=SBO,  800000=SBO        => E
+    //  1000000=VE,   2000000=EE,   4000000=SBZ, 8000000=NMFIQ      => 8
+    // 10000000=TRE, 20000000=AFE, 40000000=TE, 80000000=IE         => 0
+    // bic                0x20000   (disable background region)
+    // orr                    0x1   (enable MPU)
+    // bic              0x1002000   (disable HIVECS, VE?!)
+    // orr                   1004   (enable L1 DCache & ICache)
+    // ->reset_sctlr = 0x08E5187D;  /* as printed by CHDK cpuinfo running from bootloader */
+    cpu->reset_auxcr = 0x00000020;  /* ACTLR */
632
+    unset_feature(&cpu->env, ARM_FEATURE_V7MP);
633
634
635
636
637
638
639
640
+}
+
+static void cortex_a9_initfn(Object *obj);
+
+static void cortex_a9_eos_initfn(Object *obj)
+{
+    /* Cortex A9: http://chdk.setepontos.com/index.php?topic=13014.msg131110#msg131110 */
+    cortex_a9_initfn(obj);
641
642
+
+    /* https://www.magiclantern.fm/forum/index.php?topic=19737.msg200737#msg200737 */
643
+    ARMCPU *cpu = ARM_CPU(obj);
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
+    cpu->midr        = 0x414FC091;
+    cpu->ctr         = 0x83338003;
+    cpu->id_pfr0     = 0x00001231;
+    cpu->id_pfr1     = 0x00000011;
+    cpu->id_dfr0     = 0x00010444;
+    cpu->id_mmfr3    = 0x00102111;
+    cpu->id_isar4    = 0x00011142;
+    cpu->clidr       = 0x09200003;
+    cpu->ccsidr[0]   = 0x700FE019;
+    cpu->ccsidr[1]   = 0x200FE019;
+    cpu->reset_sctlr = 0x08C50078;  /* best guess */
+    //        1=MMU,        2=align,      4=DCache,    8=SBO        => 8
+    //       10=SBO,       20=SBO,       40=SBO,      80=SBZ        => 7
+    //      100=SBZ,      200=SBZ,      400=SWP,     800=Z(BP)      => 0 
+    //     1000=ICache,  2000=HIVECS,  4000=RR,     8000=SBZ        => 0
+    //    10000=SBO,    20000=SBZ,    40000=SBO,   80000=SBZ        => 5
+    //   100000=SBZ,   200000=SBZ,   400000=SBO,  800000=SBO        => C
+    //  1000000=SBZ,  2000000=EE,   4000000=SBZ, 8000000=NMFIQ      => 8
+    // 10000000=TRE, 20000000=AFE, 40000000=TE, 80000000=SBZ        => 0
+    // bic              0x1003005   (disable MMU, DCache, ICache, HIVECS, ???)
+    // orr             0x40000800   (enable branch predictor and Thumb exceptions)
+    // orr                   1005   (enable MMU, DCache, ICache)
+    // ->reset_sctlr = 0x48C5187D;  /* as printed by CHDK cpuinfo running from bootloader */
+    cpu->reset_auxcr = 0x00000045;  /* ACTLR */
+    //cpu->actlr2    = 0x00000201;
+    //cpu->cpacr     = 0xC0000000;
+    //cpu->dbgdidr   = TODO;
671
+}
a1ex's avatar
a1ex committed
672
673
674
675
+
 static void arm946_initfn(Object *obj)
 {
     ARMCPU *cpu = ARM_CPU(obj);
676
@@ -914,9 +1013,20 @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
677
678
679
680
 
 static const ARMCPRegInfo cortexr5_cp_reginfo[] = {
     /* Dummy the TCM region regs for the moment */
-    { .name = "ATCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 0,
681
+    /* fixme: resetvalue hardcoded for DIGIC 6 */
682
+    { .name = "ATCM",       .cp = 15, .opc1 = 0, .crn = 9,  .crm = 1, .opc2 = 1,
683
+      .access = PL1_RW,     .fieldoffset = offsetof(CPUARMState, cp15.c15_atcm), .resetvalue = 0x00000015 },
684
+    { .name = "BTCM",       .cp = 15, .opc1 = 0, .crn = 9,  .crm = 1, .opc2 = 0,
685
+      .access = PL1_RW,     .fieldoffset = offsetof(CPUARMState, cp15.c15_btcm), .resetvalue = 0x8000001D },
686
687
688
689
690
+    { .name = "INV_DCACHE", .cp = 15, .opc1 = 0, .crn = 15, .crm = 5, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST },
+    { .name = "BUILDOPTS",  .cp = 15, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = CP_ANY,
       .access = PL1_RW, .type = ARM_CP_CONST },
-    { .name = "BTCM", .cp = 15, .opc1 = 0, .crn = 9, .crm = 1, .opc2 = 1,
691
692
693
694
+    { .name = "BUILDOPTS1", .cp = 15, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 0,
+      .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue = 0x00010000 },
+    { .name = "BUILDOPTS2", .cp = 15, .opc1 = 0, .crn = 15, .crm = 2, .opc2 = 1,
+      .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue = 0x00CFC010 },
695
696
697
698
+    { .name = "ACTLR2",     .cp = 15, .opc1 = 0, .crn = 15, .crm = 0, .opc2 = 0,
       .access = PL1_RW, .type = ARM_CP_CONST },
     REGINFO_SENTINEL
 };
699
@@ -1329,6 +1439,8 @@ static const ARMCPUInfo arm_cpus[] = {
a1ex's avatar
a1ex committed
700
701
702
 #if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
     { .name = "arm926",      .initfn = arm926_initfn },
     { .name = "arm946",      .initfn = arm946_initfn },
703
+    { .name = "arm946-eos",  .initfn = arm946_eos_initfn },
704
+    { .name = "arm946-eos5", .initfn = arm946_eos5_initfn },
a1ex's avatar
a1ex committed
705
706
     { .name = "arm1026",     .initfn = arm1026_initfn },
     /* What QEMU calls "arm1136-r2" is actually the 1136 r0p2, i.e. an
707
      * older core than plain "arm1136". In particular this does not
708
@@ -1342,9 +1454,11 @@ static const ARMCPUInfo arm_cpus[] = {
709
710
711
712
713
714
715
716
717
718
719
                              .class_init = arm_v7m_class_init },
     { .name = "cortex-m4",   .initfn = cortex_m4_initfn,
                              .class_init = arm_v7m_class_init },
+    { .name = "cortex-r4-eos",.initfn = cortex_r4_eos_initfn },
     { .name = "cortex-r5",   .initfn = cortex_r5_initfn },
     { .name = "cortex-a8",   .initfn = cortex_a8_initfn },
     { .name = "cortex-a9",   .initfn = cortex_a9_initfn },
+    { .name = "cortex-a9-eos",.initfn = cortex_a9_eos_initfn },
     { .name = "cortex-a15",  .initfn = cortex_a15_initfn },
     { .name = "ti925t",      .initfn = ti925t_initfn },
     { .name = "sa1100",      .initfn = sa1100_initfn },
720
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
721
index 815fef8..74ce4a9 100644
722
723
724
725
726
727
728
729
730
731
732
733
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -389,6 +389,9 @@ typedef struct CPUARMState {
         uint64_t pmccfiltr_el0; /* Performance Monitor Filter Register */
         uint64_t vpidr_el2; /* Virtualization Processor ID Register */
         uint64_t vmpidr_el2; /* Virtualization Multiprocessor ID Register */
+
+        uint32_t c15_atcm;
+        uint32_t c15_btcm;
     } cp15;
 
     struct {
734
735
736
737
738
739
740
741
@@ -912,6 +915,7 @@ enum arm_features {
     ARM_FEATURE_V8_SHA256, /* implements SHA256 part of v8 Crypto Extensions */
     ARM_FEATURE_V8_PMULL, /* implements PMULL part of v8 Crypto Extensions */
     ARM_FEATURE_THUMB_DSP, /* DSP insns supported in the Thumb encodings */
+    ARM_FEATURE_946EOS,    /* EOS-specific (DIGIC 2...5) */
 };
 
 static inline int arm_feature(CPUARMState *env, int feature)
742
diff --git a/target-arm/helper.c b/target-arm/helper.c
743
index afc4163..632ea26 100644
744
745
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
746
747
748
749
750
751
752
753
754
755
756
757
758
759
@@ -549,6 +549,13 @@ static const ARMCPRegInfo not_v6_cp_reginfo[] = {
     REGINFO_SENTINEL
 };
 
+static const ARMCPRegInfo eos_wfi_cp_reginfo[] = {
+    /* similar to not_v6_cp_reginfo, but .crn was changed from 7 to 15 */
+    { .name = "WFI_v5", .cp = 15, .crn = 15, .crm = 8, .opc1 = 0, .opc2 = 2,
+      .access = PL1_W, .type = ARM_CP_WFI },
+    REGINFO_SENTINEL
+};
+
 static const ARMCPRegInfo not_v7_cp_reginfo[] = {
     /* Standard v6 WFI (also used in some pre-v6 cores); not in v7 (which
      * is UNPREDICTABLE; we choose to NOP as most implementations do).
760
@@ -598,6 +605,138 @@ static const ARMCPRegInfo not_v7_cp_reginfo[] = {
761
762
763
     REGINFO_SENTINEL
 };
 
764
765
766
767
768
769
770
+static const ARMCPRegInfo eos_tcm_cp_reginfo[] = {
+    { .name = "ITCM",       .cp = 15, .opc1 = 0, .crn = 9,  .crm = 1, .opc2 = 1,
+      .access = PL1_RW,     .fieldoffset = offsetof(CPUARMState, cp15.c15_atcm), .resetvalue = 0x00000006 },
+    { .name = "DTCM",       .cp = 15, .opc1 = 0, .crn = 9,  .crm = 1, .opc2 = 0,
+      .access = PL1_RW,     .fieldoffset = offsetof(CPUARMState, cp15.c15_btcm), .resetvalue = 0x40000006 },
+    REGINFO_SENTINEL
+};
771
772
773
774
+
+/* ARM946E-S (EOS) cache lockdown emulation */
+/* note: the model is very incomplete, just enough to emulate
+ * the cache hacks from Magic Lantern */
775
776
777
778
779
780
781
782
783
784
785
786
787
+
+struct cache_patch
+{
+    uint32_t addr;
+    uint32_t old;
+    uint32_t new;
+};
+
+static struct cache_patch cache_patches[32];
+
+static int num_cache_patches = 0;
+
+
788
789
790
791
792
793
794
795
796
797
798
799
800
+static uint64_t eos_cache_lockdown_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+    fprintf(stderr, "Lockdown read %x\n", ri->crm);
+    return 0;
+}
+
+static void eos_cache_patch(uint32_t addr, uint32_t value)
+{
+    uint32_t old;
+    cpu_physical_memory_read(addr, &old, sizeof(old));
+    
+    if (value != old)
+    {
801
802
+        fprintf(stderr, "Cache patch: [%08X] <- %X (was %X)\n", addr, value, old);
+        cache_patches[num_cache_patches++] = (struct cache_patch) { .addr = addr, .old = old, .new = value };
803
804
805
806
+        cpu_physical_memory_write(addr, &value, sizeof(value));
+    }
+}
+
807
808
809
810
811
812
813
814
815
816
+static void eos_revert_cache_patches(void)
+{
+    for ( ; num_cache_patches > 0; num_cache_patches--)
+    {
+        struct cache_patch * p = &cache_patches[num_cache_patches - 1];
+        fprintf(stderr, "Reverting cache patch: [%08X] <- %X (was patched to %X)\n", p->addr, p->old, p->new);
+        cpu_physical_memory_write(p->addr, &p->old, sizeof(p->old));
+    }
+}
+
817
818
819
820
821
822
+static void eos_cache_lockdown_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t val)
+{
+    static uint32_t index = 0;
+    static uint32_t itag = 0;
+    static uint32_t dtag = 0;
+
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
+    /* FIXME: not exactly accurate, just a rough approximation */
+    /* no difference is made between data and instruction cache -
+     * first cache flush or lockdown disable event will revert all cache patches */
+    switch (ri->crn)
+    {
+        case 7:
+            /* FlushICache */
+            eos_revert_cache_patches();
+            return;
+
+        case 9:
+            /* DLockDown / ILockDown */
+            if (val == 0) {
+                eos_revert_cache_patches();
+            }
+            CPREG_FIELD32(env, ri) = val;
+            return;
+
+        case 15:
+            /* see the next switch */
+            break;
+
+        default:
+            /* unreachable */
+            assert(0);
+    }
+
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
+    switch (ri->crm)
+    {
+        case 0:             /* cache debug index register */
+            index = val;
+            break;
+        
+        case 1:             /* icache tag */
+            itag = val;
+            break;
+        
+        case 2:             /* dcache tag */
+            dtag = val;
+            break;
+        
+        case 3:             /* icache value */
+            eos_cache_patch((itag & 0xFFFFFFE0) | (index & 0x1C), val);
+            break;
+        
+        case 4:             /* dcache value */
+            eos_cache_patch((dtag & 0xFFFFFFE0) | (index & 0x1C), val);
+            break;
+    }
+}
+
+static const ARMCPRegInfo eos_lockdown_cp_reginfo[] = {
+    { .name = "CacheDbgIdx", .cp = 15, .crn = 15, .crm = 0, .opc1 = 3, .opc2 = 0,
+      .access = PL1_RW, .readfn = eos_cache_lockdown_read, .writefn = eos_cache_lockdown_write },
+    { .name = "IcacheTag",   .cp = 15, .crn = 15, .crm = 1, .opc1 = 3, .opc2 = 0,
+      .access = PL1_RW, .readfn = eos_cache_lockdown_read, .writefn = eos_cache_lockdown_write },
+    { .name = "DcacheTag",   .cp = 15, .crn = 15, .crm = 2, .opc1 = 3, .opc2 = 0,
+      .access = PL1_RW, .readfn = eos_cache_lockdown_read, .writefn = eos_cache_lockdown_write },
+    { .name = "IcacheVal",   .cp = 15, .crn = 15, .crm = 3, .opc1 = 3, .opc2 = 0,
+      .access = PL1_RW, .readfn = eos_cache_lockdown_read, .writefn = eos_cache_lockdown_write },
+    { .name = "DcacheVal",   .cp = 15, .crn = 15, .crm = 4, .opc1 = 3, .opc2 = 0,
+      .access = PL1_RW, .readfn = eos_cache_lockdown_read, .writefn = eos_cache_lockdown_write },
885
886
887
888
889
890
891
892
+    { .name = "DLockDown",   .cp = 15, .crn = 9,  .crm = 0, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_data),
+      .writefn = eos_cache_lockdown_write, .resetvalue = 0, .type = ARM_CP_OVERRIDE },
+    { .name = "ILockDown",   .cp = 15, .crn = 9,  .crm = 0, .opc1 = 0, .opc2 = 1,
+      .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_insn),
+      .writefn = eos_cache_lockdown_write, .resetvalue = 0, .type = ARM_CP_OVERRIDE },
+    { .name = "FlushICache", .cp = 15, .crn = 7, .crm = 5, .opc1 = 0, .opc2 = 0,
+      .access = PL1_RW, .readfn = eos_cache_lockdown_read, .writefn = eos_cache_lockdown_write },
893
894
895
896
897
898
+    REGINFO_SENTINEL
+};
+
 static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
                         uint64_t value)
 {
899
@@ -4410,7 +4549,7 @@ void register_cp_regs_for_features(ARMCPU *cpu)
900
901
902
903
             /* TCMTR and TLBTR exist in v8 but have no 64-bit versions */
             { .name = "TCMTR",
               .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 2,
-              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = 0 },
904
+              .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->tcmtr },
905
906
907
             REGINFO_SENTINEL
         };
         /* TLBTR is specific to VMSA */
908
@@ -4542,6 +4681,13 @@ void register_cp_regs_for_features(ARMCPU *cpu)
909
910
911
912
913
914
915
916
         }
         define_one_arm_cp_reg(cpu, &sctlr);
     }
+
+    /* Features specific to DIGIC 2..5 (EOS) */
+    if (arm_feature(env, ARM_FEATURE_946EOS)) {
+        define_arm_cp_regs(cpu, eos_wfi_cp_reginfo);
+        define_arm_cp_regs(cpu, eos_lockdown_cp_reginfo);
917
+        define_arm_cp_regs(cpu, eos_tcm_cp_reginfo);
918
919
920
921
+    }
 }
 
 ARMCPU *cpu_arm_init(const char *cpu_model)
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
@@ -5422,7 +5568,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
     uint32_t lr;
     uint32_t addr;
 
-    arm_log_exception(cs->exception_index);
+    arm_log_exception(cs->exception_index, env);
 
     lr = 0xfffffff1;
     if (env->v7m.current_sp)
@@ -5719,7 +5865,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
 
     assert(!IS_M(env));
 
-    arm_log_exception(cs->exception_index);
+    arm_log_exception(cs->exception_index, env);
 
     if (arm_is_psci_call(cpu, cs->exception_index)) {
         arm_handle_psci_call(cpu);
940
@@ -5891,11 +6037,21 @@ void arm_cpu_do_interrupt(CPUState *cs)
941
942
943
     /* Switch to the new mode, and to the correct instruction set.  */
     env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
     env->daif |= mask;
944
945
-    /* this is a lie, as the was no c1_sys on V4T/V5, but who cares
-     * and we should just guard the thumb mode on V4 */
946
-    if (arm_feature(env, ARM_FEATURE_V4T)) {
947
948
949
950
951
952
953
954
955
956
957
958
959
+
+    if (arm_feature(env, ARM_FEATURE_V6) ||
+        arm_feature(env, ARM_FEATURE_V7) ||
+        arm_feature(env, ARM_FEATURE_V8)) {
+        /* newer processors execute the interrupts in Thumb mode
+         * if the SCTLR TE bit is enabled */
         env->thumb = (A32_BANKED_CURRENT_REG_GET(env, sctlr) & SCTLR_TE) != 0;
+    } else if (arm_feature(env, ARM_FEATURE_V4T)) {
+        /* there was no c1_sys on V4T/V5,
+         * and we should just guard the thumb mode on V4
+         * note: arm946eos uses the SCTLR TE bit for something else,
+         * so we can't assume this bit being always 0 on older platforms */
+        env->thumb = 0;
960
     }
961
962
963
964
+
     env->regs[14] = env->regs[15] + offset;
     env->regs[15] = addr;
     cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
965
diff --git a/target-arm/helper.h b/target-arm/helper.h
966
index c2a85c7..98aa94b 100644
967
968
--- a/target-arm/helper.h
+++ b/target-arm/helper.h
969
@@ -64,10 +64,15 @@ DEF_HELPER_2(v7m_mrs, i32, env, i32)
970
971
972
973
 
 DEF_HELPER_3(access_check_cp_reg, void, env, ptr, i32)
 DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
+DEF_HELPER_3(print_set_cp_reg, void, env, ptr, i32)
974
+DEF_HELPER_3(print_get_cp_reg, void, env, ptr, i32)
975
976
977
 DEF_HELPER_2(get_cp_reg, i32, env, ptr)
 DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64)
 DEF_HELPER_2(get_cp_reg64, i64, env, ptr)
978
979
980
981
982
983
984
 
+DEF_HELPER_3(log_ldr, void, i32, i32, i32)
+DEF_HELPER_3(log_str, void, i32, i32, i32)
+
 DEF_HELPER_3(msr_i_pstate, void, env, i32, i32)
 DEF_HELPER_1(clear_pstate_ss, void, env)
 DEF_HELPER_1(exception_return, void, env)
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
diff --git a/target-arm/internals.h b/target-arm/internals.h
index 347998c..6265345 100644
--- a/target-arm/internals.h
+++ b/target-arm/internals.h
@@ -72,7 +72,7 @@ static const char * const excnames[] = {
     [EXCP_SEMIHOST] = "Semihosting call",
 };
 
-static inline void arm_log_exception(int idx)
+static inline void arm_log_exception(int idx, CPUARMState *env)
 {
     if (qemu_loglevel_mask(CPU_LOG_INT)) {
         const char *exc = NULL;
@@ -83,7 +83,7 @@ static inline void arm_log_exception(int idx)
         if (!exc) {
             exc = "unknown";
         }
-        qemu_log_mask(CPU_LOG_INT, "Taking exception %d [%s]\n", idx, exc);
+        qemu_log_mask(CPU_LOG_INT, "%08X: Taking exception %d [%s]\n", env->regs[15], idx, exc);
     }
 }
 
1007
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
1008
index 6cd54c8..055aaf7 100644
1009
1010
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
1011
@@ -474,6 +474,199 @@ void HELPER(set_cp_reg)(CPUARMState *env, void *rip, uint32_t value)
1012
1013
1014
     ri->writefn(env, ri, value);
 }
 
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
+/* adapted from CHDK cpuinfo */
+static char linebuf[128];
+
+static const char *regperm_str(unsigned val) {
+    switch(val) {
+        case 0: return "P:-- U:--";
+        case 1: return "P:RW U:--";
+        case 2: return "P:RW U:R-";
+        case 3: return "P:RW U:RW";
+        case 5: return "P:R- U:--";
+        case 6: return "P:R- U:R-";
+        default:
+            return "P:?? U:??";
+    }
+}
+
+static const char *mpu_rattr(unsigned val) {
+    const char *s="";
+    const char *s2="";
+    const char *t;
+    t = (val&4)?"Shared":"Non-shared";
+    if (val&0x20) {
+        switch (val&3) {
+            case 0: s = "Inner Non-cacheable"; break;
+            case 1: s = "Inner Write-back, write-allocate"; break;
+            case 2: s = "Inner Write-through, no write-allocate"; break;
+            case 3: s = "Inner Write-back, no write-allocate"; break;
+        }
+        switch ((val&0x18)>>3) {
+            case 0: s2 = "Outer Non-cacheable"; break;
+            case 1: s2 = "Outer Write-back, write-allocate"; break;
+            case 2: s2 = "Outer Write-through, no write-allocate"; break;
+            case 3: s2 = "Outer Write-back, no write-allocate"; break;
+        }
+        sprintf(linebuf,"%s; %s; %s",s, s2, t);
+    }
+    else {
+        switch (val&0x1B) {
+            case 0: s = "Strongly ordered, shareable"; t=""; break;
+            case 1: s = "Shareable device"; t="Shareable"; break;
+            case 2: s = "Outer and Inner write-through, no write-allocate"; break;
+            case 3: s = "Outer and Inner write-back, no write-allocate"; break;
+            case 8: s = "Outer and Inner Non-cacheable"; break;
+            case 11: s = "Outer and Inner write-back, write-allocate"; break;
+            case 16: s = "Non-shareable Device"; t=""; break;
+            default: s = "(reserved)"; t="";
+        }
+        sprintf(linebuf,"%s; %s",s, t);
+    }
+    return linebuf;
+}
+
1067
1068
1069
1070
1071
1072
1073
1074
1075
+static void print_cpu_mpidr(CPUARMState *env)
+{
+    if (arm_feature(env, ARM_FEATURE_V7MP)) {
+        ARMCPU *cpu = ARM_CPU(arm_env_get_cpu(env));
+        uint64_t mpidr = cpu->mp_affinity;
+        fprintf(stderr, "[CPU%d] ", (int) mpidr & 0xFF);
+    }
+}
+
1076
1077
1078
+void HELPER(print_set_cp_reg)(CPUARMState *env, void *rip, uint32_t value)
+{
+    const ARMCPRegInfo *ri = rip;
1079
1080
1081
1082
1083
1084
+    char desc[256] = "";
+
+    if (strcmp(ri->name, "DSB") == 0)
+    {
+        return;
+    }
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
+    
+    /* CACHEMAINT registers come in very large groups;
+     * just display how many calls there were.
+     * fixme: if there are MRC calls, the display order may be wrong
+     */
+    static int cachemaint_count = 0;
+    static uint32_t cachemaint_pc = 0;
+    if (strcmp(ri->name, "CACHEMAINT") == 0)
+    {
+        cachemaint_pc = env->regs[15];
+        cachemaint_count++;
+        return;
+    }
+    else
+    {
+        if (cachemaint_count)
+        {
1102
+            print_cpu_mpidr(env);
1103
1104
1105
1106
+            fprintf(stderr, "%08X: MCR p%d, ...          : CACHEMAINT x%d (omitted)\n", cachemaint_pc, ri->cp, cachemaint_count);
+            cachemaint_count = 0;
+        }
+    }
1107
+
1108
+    if (strncmp(ri->name, "946_PRBS", 8) == 0 &&
1109
+        (value & 1))
1110
1111
1112
1113
+    {
+        uint64_t base = value & 0xFFFFF000;
+        uint64_t size = 1ull << (((value >> 1) & 0x1F) + 1);
+        uint64_t end = base + size - 1;
1114
+        snprintf(desc, sizeof(desc), "(%08"PRIX64" - %08"PRIX64", 0x%"PRIX64")", base, end, size);
1115
1116
1117
1118
1119
+
+        /* workaround to emulate io_trace */
+        /* fixme - proper solution? */
+        ARMCPU *cpu = arm_env_get_cpu(env);
+        tlb_flush(CPU(cpu), 1);
1120
1121
+    }
+
1122
+    if (strcmp(ri->name+1, "TCM") == 0)
1123
1124
1125
1126
+    {
+        uint64_t base = value & 0xFFFFF000;
+        uint64_t size = 1ull << (((value >> 1) & 0x1F) + 9);
+        uint64_t end = base + size - 1;
1127
+        snprintf(desc, sizeof(desc), "(%08"PRIX64" - %08"PRIX64", 0x%"PRIX64")", base, end, size);
1128
1129
+    }
+
1130
1131
+    if (strcmp(ri->name, "DRSR") == 0 &&
+        (value & 1))
1132
1133
+    {
+        uint64_t size = 1ull << (((value >> 1) & 0x1F) + 1);
1134
+        snprintf(desc, sizeof(desc), "(0x%"PRIX64")", size);
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
+
+        uint32_t rgnr = env->cp15.c6_rgnr;
+        uint32_t base = env->pmsav7.drbar[rgnr];
+        assert(base % size == 0);
+
+        /* subregion disable bits */
+        uint32_t subregion_disable = (value & 0xFF00) >> 8;
+        if (subregion_disable)
+        {
+            /* Region sizes of less than 256 bytes do not support subregions
+             * (Cortex R4 TRM, 7.1.1 Memory regions) */
+            assert(size >= 256);
+
+            uint32_t subregion_size = size / 8;
+            for (int i = 0; i < 8; i++)
+            {
+                fprintf(stderr,
+                    "Subregion %08X - %08X: %s\n",
+                    base + subregion_size * i,
+                    base + subregion_size * (i + 1) - 1,
+                    subregion_disable & (1 << i) ? "disabled" : "enabled"
+                );
+            }
+        }
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
+    }
+
+    if (strcmp(ri->name, "DRACR") == 0)
+    {
+        uint32_t rattr = value & 0x3F;
+        uint32_t accpm = (value >> 8) & 3;
+        uint32_t xn    = (value >> 12) & 1;
+        snprintf(desc, sizeof(desc),
+            "(%s; %s%s)",
+            regperm_str(accpm),
+            mpu_rattr(rattr),
+            xn ? "; Execute never" : ""
+        );
+    }
+
1174
+    print_cpu_mpidr(env);
1175
+    fprintf(stderr, "%08X: MCR p%d,%d,Rd,cr%d,cr%d,%d: %10s <- 0x%-8X %s\n",
1176
1177
+        env->regs[15], ri->cp,
+        ri->opc1, ri->crn, ri->crm, ri->opc2,
1178
+        ri->name, value, desc
1179
1180
+    );
+}
1181
+
1182
1183
1184
1185
+void HELPER(print_get_cp_reg)(CPUARMState *env, void *rip, uint32_t value)
+{
+    const ARMCPRegInfo *ri = rip;
+
1186
+    print_cpu_mpidr(env);
1187
+    fprintf(stderr, "%08X: MRC p%d,%d,Rd,cr%d,cr%d,%d: %10s -> 0x%X\n",
1188
1189
1190
1191
1192
+        env->regs[15], ri->cp,
+        ri->opc1, ri->crn, ri->crm, ri->opc2,
+        ri->name, value
+    );
+}
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
+
+/* fixme: how to pass a pointer here, to call the registered CBR directly? */
+extern void log_ldr_cb(uint32_t addr, uint32_t value, uint32_t opc);
+extern void log_str_cb(uint32_t addr, uint32_t value, uint32_t opc);
+
+void HELPER(log_ldr)(uint32_t addr, uint32_t value, uint32_t opc)
+{
+    log_ldr_cb(addr, value, opc);
+}
+
+void HELPER(log_str)(uint32_t addr, uint32_t value, uint32_t opc)
+{
+    log_str_cb(addr, value, opc);
+}
1207
1208
1209
1210
1211
+
 uint32_t HELPER(get_cp_reg)(CPUARMState *env, void *rip)
 {
     const ARMCPRegInfo *ri = rip;
diff --git a/target-arm/translate.c b/target-arm/translate.c
1212
index 5d22879..a413e2c 100644
1213
1214
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
1215
@@ -37,6 +37,8 @@
1216
1217
1218
 
 #include "trace-tcg.h"
 
1219
+#define LOG_ALL_CP_READS
1220
1221
1222
1223
+#define LOG_ALL_CP_WRITES
 
 #define ENABLE_ARCH_4T    arm_dc_feature(s, ARM_FEATURE_V4T)
 #define ENABLE_ARCH_5     arm_dc_feature(s, ARM_FEATURE_V5)
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
@@ -923,25 +925,101 @@ static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
  */
 #if TARGET_LONG_BITS == 32
 
+/* fixme: should be moved to memory.c and accessed somehow from there? */
+/* fixme: use MemoryRegionOps? The read callback doesn't accept address and value */
+struct mem_log
+{
+    void (*read_cb)(void * opaque, hwaddr addr, uint64_t value, unsigned size, int is_write);
+    void * read_arg;
+    void (*write_cb)(void * opaque, hwaddr addr, uint64_t value, unsigned size, int is_write);
+    void * write_arg;
+} mem_log;
+
+void memory_set_access_logging_cb(
+    void (*mem_log_cb)(void * opaque, hwaddr addr, uint64_t value, unsigned size, int is_write),
+    void * opaque, int access_mode)
+{
+    if (access_mode & PROT_READ) {
+        mem_log.read_cb = mem_log_cb;
+        mem_log.read_arg = opaque;
+    }
+    if (access_mode & PROT_WRITE) {
+        mem_log.write_cb = mem_log_cb;
+        mem_log.write_arg = opaque;
+    }
+}
+
+/* called from helper_log_ldr */
+void log_ldr_cb(uint32_t addr, uint32_t value, uint32_t opc)
+{
+    if (mem_log.read_cb) {
+        unsigned size = 1 << (opc & MO_SIZE);
+        mem_log.read_cb(mem_log.read_arg, addr, value, size, 0);
+    }
+}
+
+/* called from helper_log_str */
+void log_str_cb(uint32_t addr, uint32_t value, uint32_t opc)
+{
+    if (mem_log.write_cb) {
+        unsigned size = 1 << (opc & MO_SIZE);
+        mem_log.write_cb(mem_log.write_arg, addr, value, size, 1);
+    }
+}
+
+static inline void gen_log_ldr(TCGv_i32 addr, TCGv_i32 val, int opc)
+{
+    /* called after the actual LDR, to get the value too */
+    /* only compile the logging code if a CBR was registered */
+    if (mem_log.read_cb) {
+        TCGv_i32 opc_reg = tcg_temp_new_i32();
+        tcg_gen_movi_i32(opc_reg, opc);
+        gen_helper_log_ldr(addr, val, opc_reg);
+        tcg_temp_free_i32(opc_reg);
+    }
+}
+
+static inline void gen_log_str(TCGv_i32 addr, TCGv_i32 val, int opc)
+{
+    /* called before the actual STR */
+    /* only compile the logging code if a CBR was registered */
+    if (mem_log.write_cb) {
+        TCGv_i32 opc_reg = tcg_temp_new_i32();
+        tcg_gen_movi_i32(opc_reg, opc);
+        gen_helper_log_str(addr, val, opc_reg);
+        tcg_temp_free_i32(opc_reg);
+    }
+}
+
 #define DO_GEN_LD(SUFF, OPC)                                             \
 static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
     tcg_gen_qemu_ld_i32(val, addr, index, OPC);                          \
+    gen_log_ldr(addr, val, OPC);                                         \
 }
 
 #define DO_GEN_ST(SUFF, OPC)                                             \
 static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
 {                                                                        \
+    gen_log_str(addr, val, OPC);                                         \
     tcg_gen_qemu_st_i32(val, addr, index, OPC);                          \
 }
 
 static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
 {
+    if (mem_log.read_cb) {
+        /* not implemented */
+        assert(0);
+    }
     tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
 }
 
 static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
 {
+    if (mem_log.write_cb) {
+        /* not implemented */
+        assert(0);
+    }
     tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
 }
 
@@ -7222,6 +7300,27 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
         /* Handle special cases first */
         switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
         case ARM_CP_NOP:
+            #if defined(LOG_ALL_CP_READS) || defined(LOG_ALL_CP_WRITES)
+            if (!is64) {
+                /* log all reads to coprocessor registers (32-bit) */
+                TCGv_ptr tmpptr;
+                TCGv_i32 tmp;
+                tmpptr = tcg_const_ptr(ri);
+                if (isread) {
+                    #ifdef LOG_ALL_CP_READS
+                    tmp = load_cpu_offset(ri->fieldoffset);
+                    gen_helper_print_get_cp_reg(cpu_env, tmpptr, tmp);
+                    #endif
+                } else {
+                    #ifdef LOG_ALL_CP_WRITES
+                    tmp = load_reg(s, rt);
+                    gen_helper_print_set_cp_reg(cpu_env, tmpptr, tmp);
+                    #endif
+                }
+                tcg_temp_free_ptr(tmpptr);
+                tcg_temp_free_i32(tmp);
+            }
+            #endif
             return 0;
         case ARM_CP_WFI:
             if (isread) {
1354
@@ -7276,6 +7375,15 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
1355
                 } else {
1356
                     tmp = load_cpu_offset(ri->fieldoffset);
1357
                 }
1358
+
1359
1360
1361
1362
1363
1364
1365
+                #ifdef LOG_ALL_CP_READS
+                /* log all reads to coprocessor registers (32-bit) */
+                TCGv_ptr tmpptr;
+                tmpptr = tcg_const_ptr(ri);
+                gen_helper_print_get_cp_reg(cpu_env, tmpptr, tmp);
+                tcg_temp_free_ptr(tmpptr);
+                #endif
1366
1367
1368
1369
+
                 if (rt == 15) {
                     /* Destination register of r15 for 32 bit loads sets
                      * the condition codes from the high 4 bits of the value
1370
@@ -7287,6 +7395,19 @@ static int disas_coproc_insn(DisasContext *s, uint32_t insn)
1371
                 }
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
             }
         } else {
+            #ifdef LOG_ALL_CP_WRITES
+            if (!is64) {
+                /* log all writes to coprocessor registers (32-bit) */
+                TCGv_i32 tmp;
+                TCGv_ptr tmpptr;
+                tmp = load_reg(s, rt);
+                tmpptr = tcg_const_ptr(ri);
+                gen_helper_print_set_cp_reg(cpu_env, tmpptr, tmp);
+                tcg_temp_free_ptr(tmpptr);
+                tcg_temp_free_i32(tmp);
+            }
+            #endif
+            
             /* Write */
             if (ri->type & ARM_CP_CONST) {
                 /* If not forbidden by access permissions, treat as WI */
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 53ef971..260331a 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -151,4 +151,8 @@ void arm_free_cc(DisasCompare *cmp);
 void arm_jump_cc(DisasCompare *cmp, TCGLabel *label);
 void arm_gen_test_cc(int cc, TCGLabel *label);
 
+/* fixme: duplicate declaration in op_helper.c */
+void log_ldr_cb(uint32_t addr, uint32_t value, uint32_t opc);
+void log_str_cb(uint32_t addr, uint32_t value, uint32_t opc);
+
 #endif /* TARGET_ARM_TRANSLATE_H */
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
diff --git a/util/memfd.c b/util/memfd.c
index 7c40691..3636f0d 100644
--- a/util/memfd.c
+++ b/util/memfd.c
@@ -34,9 +34,7 @@
 
 #include "qemu/memfd.h"
 
-#ifdef CONFIG_MEMFD
-#include <sys/memfd.h>
-#elif defined CONFIG_LINUX
+#if defined CONFIG_LINUX && !defined CONFIG_MEMFD
 #include <sys/syscall.h>
 #include <asm/unistd.h>
 
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
diff --git a/vl.c b/vl.c
index 4211ff1..93d4df4 100644
--- a/vl.c
+++ b/vl.c
@@ -4102,7 +4102,7 @@ int main(int argc, char **argv, char **envp)
     }
 
     if (log_mask) {
-        int mask;
+        uint64_t mask;
         mask = qemu_str_to_log_mask(log_mask);
         if (!mask) {
             qemu_print_log_usage(stdout);