1 /*
2 * Copyright (C) 2003-2009 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * Functions for handling the memory of an emulated machine.
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/mman.h>
36
37 #include "cpu.h"
38 #include "machine.h"
39 #include "memory.h"
40 #include "misc.h"
41
42
43 extern int verbose;
44 extern int quiet_mode;
45
46
47 /*
48 * memory_readmax64():
49 *
50 * Read at most 64 bits of data from a buffer. Length is given by
51 * len, and the byte order by cpu->byte_order.
52 *
53 * This function should not be called with cpu == NULL.
54 */
memory_readmax64(struct cpu * cpu,unsigned char * buf,int len)55 uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
56 {
57 int i, byte_order = cpu->byte_order;
58 uint64_t x = 0;
59
60 if (len & MEM_PCI_LITTLE_ENDIAN) {
61 len &= ~MEM_PCI_LITTLE_ENDIAN;
62 byte_order = EMUL_LITTLE_ENDIAN;
63 }
64
65 /* Switch byte order for incoming data, if necessary: */
66 if (byte_order == EMUL_BIG_ENDIAN)
67 for (i=0; i<len; i++) {
68 x <<= 8;
69 x |= buf[i];
70 }
71 else
72 for (i=len-1; i>=0; i--) {
73 x <<= 8;
74 x |= buf[i];
75 }
76
77 return x;
78 }
79
80
81 /*
82 * memory_writemax64():
83 *
84 * Write at most 64 bits of data to a buffer. Length is given by
85 * len, and the byte order by cpu->byte_order.
86 *
87 * This function should not be called with cpu == NULL.
88 */
memory_writemax64(struct cpu * cpu,unsigned char * buf,int len,uint64_t data)89 void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len,
90 uint64_t data)
91 {
92 int i, byte_order = cpu->byte_order;
93
94 if (len & MEM_PCI_LITTLE_ENDIAN) {
95 len &= ~MEM_PCI_LITTLE_ENDIAN;
96 byte_order = EMUL_LITTLE_ENDIAN;
97 }
98
99 if (byte_order == EMUL_LITTLE_ENDIAN)
100 for (i=0; i<len; i++) {
101 buf[i] = data & 255;
102 data >>= 8;
103 }
104 else
105 for (i=0; i<len; i++) {
106 buf[len - 1 - i] = data & 255;
107 data >>= 8;
108 }
109 }
110
111
112 /*
113 * zeroed_alloc():
114 *
115 * Allocates a block of memory using mmap(), and if that fails, try
116 * malloc() + memset(). The returned memory block contains only zeroes.
117 */
zeroed_alloc(size_t s)118 void *zeroed_alloc(size_t s)
119 {
120 void *p = mmap(NULL, s, PROT_READ | PROT_WRITE,
121 MAP_ANON | MAP_PRIVATE, -1, 0);
122
123 if (p == NULL) {
124 #if 1
125 fprintf(stderr, "zeroed_alloc(): mmap() failed. This should"
126 " not usually happen. If you can reproduce this, then"
127 " please contact me with details about your run-time"
128 " environment.\n");
129 exit(1);
130 #else
131 CHECK_ALLOCATION(p = malloc(s));
132 memset(p, 0, s);
133 #endif
134 }
135
136 return p;
137 }
138
139
140 /*
141 * memory_new():
142 *
143 * This function creates a new memory object. An emulated machine needs one
144 * of these.
145 */
memory_new(uint64_t physical_max,int arch)146 struct memory *memory_new(uint64_t physical_max, int arch)
147 {
148 struct memory *mem;
149 int bits_per_pagetable = BITS_PER_PAGETABLE;
150 int bits_per_memblock = BITS_PER_MEMBLOCK;
151 int entries_per_pagetable = 1 << BITS_PER_PAGETABLE;
152 int max_bits = MAX_BITS;
153 size_t s;
154
155 CHECK_ALLOCATION(mem = (struct memory *) malloc(sizeof(struct memory)));
156 memset(mem, 0, sizeof(struct memory));
157
158 /* Check bits_per_pagetable and bits_per_memblock for sanity: */
159 if (bits_per_pagetable + bits_per_memblock != max_bits) {
160 fprintf(stderr, "memory_new(): bits_per_pagetable and "
161 "bits_per_memblock mismatch\n");
162 exit(1);
163 }
164
165 mem->physical_max = physical_max;
166 mem->dev_dyntrans_alignment = 4095;
167
168 s = entries_per_pagetable * sizeof(void *);
169
170 mem->pagetable = (unsigned char *) mmap(NULL, s,
171 PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
172 if (mem->pagetable == NULL) {
173 CHECK_ALLOCATION(mem->pagetable = malloc(s));
174 memset(mem->pagetable, 0, s);
175 }
176
177 mem->mmap_dev_minaddr = 0xffffffffffffffffULL;
178 mem->mmap_dev_maxaddr = 0;
179
180 return mem;
181 }
182
183
184 /*
185 * memory_points_to_string():
186 *
187 * Returns 1 if there's something string-like in emulated memory at address
188 * addr, otherwise 0.
189 */
memory_points_to_string(struct cpu * cpu,struct memory * mem,uint64_t addr,int min_string_length)190 int memory_points_to_string(struct cpu *cpu, struct memory *mem, uint64_t addr,
191 int min_string_length)
192 {
193 int cur_length = 0;
194 unsigned char c;
195
196 for (;;) {
197 c = '\0';
198 cpu->memory_rw(cpu, mem, addr+cur_length,
199 &c, sizeof(c), MEM_READ, CACHE_NONE | NO_EXCEPTIONS);
200 if (c=='\n' || c=='\t' || c=='\r' || (c>=' ' && c<127)) {
201 cur_length ++;
202 if (cur_length >= min_string_length)
203 return 1;
204 } else {
205 if (cur_length >= min_string_length)
206 return 1;
207 else
208 return 0;
209 }
210 }
211 }
212
213
214 /*
215 * memory_conv_to_string():
216 *
217 * Convert emulated memory contents to a string, placing it in a buffer
218 * provided by the caller.
219 */
memory_conv_to_string(struct cpu * cpu,struct memory * mem,uint64_t addr,char * buf,int bufsize)220 char *memory_conv_to_string(struct cpu *cpu, struct memory *mem, uint64_t addr,
221 char *buf, int bufsize)
222 {
223 int len = 0;
224 int output_index = 0;
225 unsigned char c, p='\0';
226
227 while (output_index < bufsize-1) {
228 c = '\0';
229 cpu->memory_rw(cpu, mem, addr+len, &c, sizeof(c), MEM_READ,
230 CACHE_NONE | NO_EXCEPTIONS);
231 buf[output_index] = c;
232 if (c>=' ' && c<127) {
233 len ++;
234 output_index ++;
235 } else if (c=='\n' || c=='\r' || c=='\t') {
236 len ++;
237 buf[output_index] = '\\';
238 output_index ++;
239 switch (c) {
240 case '\n': p = 'n'; break;
241 case '\r': p = 'r'; break;
242 case '\t': p = 't'; break;
243 }
244 if (output_index < bufsize-1) {
245 buf[output_index] = p;
246 output_index ++;
247 }
248 } else {
249 buf[output_index] = '\0';
250 return buf;
251 }
252 }
253
254 buf[bufsize-1] = '\0';
255 return buf;
256 }
257
258
259 /*
260 * memory_device_dyntrans_access():
261 *
262 * Get the lowest and highest dyntrans access since last time.
263 */
memory_device_dyntrans_access(struct cpu * cpu,struct memory * mem,void * extra,uint64_t * low,uint64_t * high)264 void memory_device_dyntrans_access(struct cpu *cpu, struct memory *mem,
265 void *extra, uint64_t *low, uint64_t *high)
266 {
267 size_t s;
268 int i, need_inval = 0;
269
270 /* TODO: This is O(n), so it might be good to rewrite it some day.
271 For now, it will be enough, as long as this function is not
272 called too often. */
273
274 for (i=0; i<mem->n_mmapped_devices; i++) {
275 if (mem->devices[i].extra == extra &&
276 mem->devices[i].flags & DM_DYNTRANS_WRITE_OK &&
277 mem->devices[i].dyntrans_data != NULL) {
278 if (mem->devices[i].dyntrans_write_low != (uint64_t) -1)
279 need_inval = 1;
280 if (low != NULL)
281 *low = mem->devices[i].dyntrans_write_low;
282 mem->devices[i].dyntrans_write_low = (uint64_t) -1;
283
284 if (high != NULL)
285 *high = mem->devices[i].dyntrans_write_high;
286 mem->devices[i].dyntrans_write_high = 0;
287
288 if (!need_inval)
289 return;
290
291 /* Invalidate any pages of this device that might
292 be in the dyntrans load/store cache, by marking
293 the pages read-only. */
294 if (cpu->invalidate_translation_caches != NULL) {
295 for (s = *low; s <= *high;
296 s += cpu->machine->arch_pagesize)
297 cpu->invalidate_translation_caches
298 (cpu, mem->devices[i].baseaddr + s,
299 JUST_MARK_AS_NON_WRITABLE
300 | INVALIDATE_PADDR);
301 }
302
303 return;
304 }
305 }
306 }
307
308
309 /*
310 * memory_device_update_data():
311 *
312 * Update a device' dyntrans data pointer.
313 *
314 * SUPER-IMPORTANT NOTE: Anyone who changes a dyntrans data pointer while
315 * things are running also needs to invalidate all CPUs' address translation
316 * caches! Otherwise, these may contain old pointers to the old data.
317 */
memory_device_update_data(struct memory * mem,void * extra,unsigned char * data)318 void memory_device_update_data(struct memory *mem, void *extra,
319 unsigned char *data)
320 {
321 int i;
322
323 for (i=0; i<mem->n_mmapped_devices; i++) {
324 if (mem->devices[i].extra != extra)
325 continue;
326
327 mem->devices[i].dyntrans_data = data;
328 mem->devices[i].dyntrans_write_low = (uint64_t)-1;
329 mem->devices[i].dyntrans_write_high = 0;
330 }
331 }
332
333
334 /*
335 * memory_device_register():
336 *
337 * Register a memory mapped device.
338 */
memory_device_register(struct memory * mem,const char * device_name,uint64_t baseaddr,uint64_t len,int (* f)(struct cpu *,struct memory *,uint64_t,unsigned char *,size_t,int,void *),void * extra,int flags,unsigned char * dyntrans_data)339 void memory_device_register(struct memory *mem, const char *device_name,
340 uint64_t baseaddr, uint64_t len,
341 int (*f)(struct cpu *,struct memory *,uint64_t,unsigned char *,
342 size_t,int,void *),
343 void *extra, int flags, unsigned char *dyntrans_data)
344 {
345 int i, newi = 0;
346
347 /*
348 * Figure out at which index to insert this device, and simultaneously
349 * check for collisions:
350 */
351 newi = -1;
352 for (i=0; i<mem->n_mmapped_devices; i++) {
353 if (i == 0 && baseaddr + len <= mem->devices[i].baseaddr)
354 newi = i;
355 if (i > 0 && baseaddr + len <= mem->devices[i].baseaddr &&
356 baseaddr >= mem->devices[i-1].endaddr)
357 newi = i;
358 if (i == mem->n_mmapped_devices - 1 &&
359 baseaddr >= mem->devices[i].endaddr)
360 newi = i + 1;
361
362 /* If this is not colliding with device i, then continue: */
363 if (baseaddr + len <= mem->devices[i].baseaddr)
364 continue;
365 if (baseaddr >= mem->devices[i].endaddr)
366 continue;
367
368 fatal("\nERROR! \"%s\" collides with device %i (\"%s\")!\n",
369 device_name, i, mem->devices[i].name);
370 exit(1);
371 }
372 if (mem->n_mmapped_devices == 0)
373 newi = 0;
374 if (newi == -1) {
375 fatal("INTERNAL ERROR\n");
376 exit(1);
377 }
378
379 if (verbose >= 2) {
380 /* (40 bits of physical address is displayed) */
381 debug("device at 0x%010" PRIx64": %s", (uint64_t) baseaddr,
382 device_name);
383
384 if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
385 && (baseaddr & mem->dev_dyntrans_alignment) != 0) {
386 fatal("\nWARNING: Device dyntrans access, but unaligned"
387 " baseaddr 0x%" PRIx64".\n", (uint64_t) baseaddr);
388 }
389
390 if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {
391 debug(" (dyntrans %s)",
392 (flags & DM_DYNTRANS_WRITE_OK)? "R/W" : "R");
393 }
394 debug("\n");
395 }
396
397 for (i=0; i<mem->n_mmapped_devices; i++) {
398 if (dyntrans_data == mem->devices[i].dyntrans_data &&
399 mem->devices[i].flags&(DM_DYNTRANS_OK|DM_DYNTRANS_WRITE_OK)
400 && flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)) {
401 fatal("ERROR: the data pointer used for dyntrans "
402 "accesses must only be used once!\n");
403 fatal("(%p cannot be used by '%s'; already in use by '"
404 "%s')\n", dyntrans_data, device_name,
405 mem->devices[i].name);
406 exit(1);
407 }
408 }
409
410 mem->n_mmapped_devices++;
411
412 CHECK_ALLOCATION(mem->devices = (struct memory_device *) realloc(mem->devices,
413 sizeof(struct memory_device) * mem->n_mmapped_devices));
414
415 /* Make space for the new entry: */
416 if (newi + 1 != mem->n_mmapped_devices)
417 memmove(&mem->devices[newi+1], &mem->devices[newi],
418 sizeof(struct memory_device)
419 * (mem->n_mmapped_devices - newi - 1));
420
421 CHECK_ALLOCATION(mem->devices[newi].name = strdup(device_name));
422 mem->devices[newi].baseaddr = baseaddr;
423 mem->devices[newi].endaddr = baseaddr + len;
424 mem->devices[newi].length = len;
425 mem->devices[newi].flags = flags;
426 mem->devices[newi].dyntrans_data = dyntrans_data;
427
428 if (flags & (DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK)
429 && !(flags & DM_EMULATED_RAM) && dyntrans_data == NULL) {
430 fatal("\nERROR: Device dyntrans access, but dyntrans_data"
431 " = NULL!\n");
432 exit(1);
433 }
434
435 if ((size_t)dyntrans_data & (sizeof(void *) - 1)) {
436 fprintf(stderr, "memory_device_register():"
437 " dyntrans_data not aligned correctly (%p)\n",
438 dyntrans_data);
439 abort();
440 }
441
442 mem->devices[newi].dyntrans_write_low = (uint64_t)-1;
443 mem->devices[newi].dyntrans_write_high = 0;
444 mem->devices[newi].f = f;
445 mem->devices[newi].extra = extra;
446
447 if (baseaddr < mem->mmap_dev_minaddr)
448 mem->mmap_dev_minaddr = baseaddr & ~mem->dev_dyntrans_alignment;
449 if (baseaddr + len > mem->mmap_dev_maxaddr)
450 mem->mmap_dev_maxaddr = (((baseaddr + len) - 1) |
451 mem->dev_dyntrans_alignment) + 1;
452
453 if (newi < mem->last_accessed_device)
454 mem->last_accessed_device ++;
455 }
456
457
458 /*
459 * memory_device_remove():
460 *
461 * Unregister a memory mapped device from a memory object.
462 */
memory_device_remove(struct memory * mem,int i)463 void memory_device_remove(struct memory *mem, int i)
464 {
465 if (i < 0 || i >= mem->n_mmapped_devices) {
466 fatal("memory_device_remove(): invalid device number %i\n", i);
467 exit(1);
468 }
469
470 mem->n_mmapped_devices --;
471
472 if (i == mem->n_mmapped_devices)
473 return;
474
475 memmove(&mem->devices[i], &mem->devices[i+1],
476 sizeof(struct memory_device) * (mem->n_mmapped_devices - i));
477
478 if (i <= mem->last_accessed_device)
479 mem->last_accessed_device --;
480 if (mem->last_accessed_device < 0)
481 mem->last_accessed_device = 0;
482 }
483
484
485 /*
486 * memory_paddr_to_hostaddr():
487 *
488 * Translate a physical address into a host address. The usual way to call
489 * this function is to make sure that paddr is page aligned, which will result
490 * in the host _page_ corresponding to that address.
491 *
492 * Return value is a pointer to the address in the host, or NULL on failure.
493 * On reads, a NULL return value should be interpreted as reading all zeroes.
494 */
memory_paddr_to_hostaddr(struct memory * mem,uint64_t paddr,int writeflag)495 unsigned char *memory_paddr_to_hostaddr(struct memory *mem,
496 uint64_t paddr, int writeflag)
497 {
498 void **table;
499 int entry;
500 const int mask = (1 << BITS_PER_PAGETABLE) - 1;
501 const int shrcount = MAX_BITS - BITS_PER_PAGETABLE;
502 unsigned char *hostptr;
503
504 table = (void **) mem->pagetable;
505 entry = (paddr >> shrcount) & mask;
506
507 /* printf("memory_paddr_to_hostaddr(): p=%16" PRIx64
508 " w=%i => entry=0x%x\n", (uint64_t) paddr, writeflag, entry); */
509
510 if (table[entry] == NULL) {
511 size_t alloclen;
512
513 /*
514 * Special case: reading from a nonexistant memblock
515 * returns all zeroes, and doesn't allocate anything.
516 * (If any intermediate pagetable is nonexistant, then
517 * the same thing happens):
518 */
519 if (writeflag == MEM_READ)
520 return NULL;
521
522 /* Allocate a memblock: */
523 alloclen = 1 << BITS_PER_MEMBLOCK;
524
525 /* printf(" allocating for entry %i, len=%i\n",
526 entry, alloclen); */
527
528 /* Anonymous mmap() should return zero-filled memory,
529 try malloc + memset if mmap failed. */
530 table[entry] = (void *) mmap(NULL, alloclen,
531 PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
532 if (table[entry] == NULL) {
533 CHECK_ALLOCATION(table[entry] = malloc(alloclen));
534 memset(table[entry], 0, alloclen);
535 }
536 }
537
538 hostptr = (unsigned char *) table[entry];
539
540 if (hostptr != NULL)
541 hostptr += (paddr & ((1 << BITS_PER_MEMBLOCK) - 1));
542
543 return hostptr;
544 }
545
546
547 #define UPDATE_CHECKSUM(value) { \
548 internal_state -= 0x118c7771c0c0a77fULL; \
549 internal_state = ((internal_state + (value)) << 7) ^ \
550 (checksum >> 11) ^ ((checksum - (value)) << 3) ^ \
551 (internal_state - checksum) ^ ((value) - internal_state); \
552 checksum ^= internal_state; \
553 }
554
555
556 /*
557 * memory_checksum():
558 *
559 * Calculate a 64-bit checksum of everything in a struct memory. This is
560 * useful for tracking down bugs; an old (presumably working) version of
561 * the emulator can be compared to a newer (buggy) version.
562 */
memory_checksum(struct memory * mem)563 uint64_t memory_checksum(struct memory *mem)
564 {
565 uint64_t internal_state = 0x80624185376feff2ULL;
566 uint64_t checksum = 0xcb9a87d5c010072cULL;
567 const size_t n_entries = (1 << BITS_PER_PAGETABLE) - 1;
568 const size_t len = (1 << BITS_PER_MEMBLOCK) / sizeof(uint64_t);
569 size_t entry, i;
570
571 for (entry=0; entry<=n_entries; entry++) {
572 uint64_t **table = (uint64_t **) mem->pagetable;
573 uint64_t *memblock = table[entry];
574
575 if (memblock == NULL) {
576 UPDATE_CHECKSUM(0x1198ab7c8174a76fULL);
577 continue;
578 }
579
580 for (i=0; i<len; i++)
581 UPDATE_CHECKSUM(memblock[i]);
582 }
583
584 return checksum;
585 }
586
587
588 /*
589 * memory_warn_about_unimplemented_addr():
590 *
591 * Called from memory_rw whenever memory outside of the physical address space
592 * is accessed (and quiet_mode isn't set).
593 */
memory_warn_about_unimplemented_addr(struct cpu * cpu,struct memory * mem,int writeflag,uint64_t paddr,uint8_t * data,size_t len)594 void memory_warn_about_unimplemented_addr(struct cpu *cpu, struct memory *mem,
595 int writeflag, uint64_t paddr, uint8_t *data, size_t len)
596 {
597 uint64_t offset, old_pc = cpu->pc;
598 char *symbol;
599
600 /*
601 * This allows guest OS kernels to probe memory a few KBs past the
602 * end of memory, without giving too many warnings.
603 */
604 if (paddr < mem->physical_max + 0x40000)
605 return;
606
607 if (!cpu->machine->halt_on_nonexistant_memaccess && quiet_mode)
608 return;
609
610 fatal("[ memory_rw(): %s ", writeflag? "write":"read");
611
612 if (writeflag) {
613 unsigned int i;
614 debug("data={", writeflag);
615 if (len > 16) {
616 int start2 = len-16;
617 for (i=0; i<16; i++)
618 debug("%s%02x", i?",":"", data[i]);
619 debug(" .. ");
620 if (start2 < 16)
621 start2 = 16;
622 for (i=start2; i<len; i++)
623 debug("%s%02x", i?",":"", data[i]);
624 } else
625 for (i=0; i<len; i++)
626 debug("%s%02x", i?",":"", data[i]);
627 debug("} ");
628 }
629
630 fatal("paddr=0x%" PRIx64" >= physical_max; pc=", paddr);
631 if (cpu->is_32bit)
632 fatal("0x%08" PRIx32, (uint32_t) old_pc);
633 else
634 fatal("0x%016" PRIx64, (uint64_t) old_pc);
635 symbol = get_symbol_name(&cpu->machine->symbol_context,
636 old_pc, &offset);
637 fatal(" <%s> ]\n", symbol? symbol : " no symbol ");
638
639 if (cpu->machine->halt_on_nonexistant_memaccess) {
640 /* TODO: Halt in a nicer way. Not possible with the
641 current dyntrans system... */
642 exit(1);
643 }
644 }
645
646
647 /*
648 * dump_mem_string():
649 *
650 * Dump the contents of emulated RAM as readable text. Bytes that aren't
651 * readable are dumped in [xx] notation, where xx is in hexadecimal.
652 * Dumping ends after DUMP_MEM_STRING_MAX bytes, or when a terminating
653 * zero byte is found.
654 */
655 #define DUMP_MEM_STRING_MAX 45
dump_mem_string(struct cpu * cpu,uint64_t addr)656 void dump_mem_string(struct cpu *cpu, uint64_t addr)
657 {
658 int i;
659 for (i=0; i<DUMP_MEM_STRING_MAX; i++) {
660 unsigned char ch = '\0';
661
662 cpu->memory_rw(cpu, cpu->mem, addr + i, &ch, sizeof(ch),
663 MEM_READ, CACHE_DATA | NO_EXCEPTIONS);
664 if (ch == '\0')
665 return;
666 if (ch >= ' ' && ch < 126)
667 debug("%c", ch);
668 else
669 debug("[%02x]", ch);
670 }
671 }
672
673
674 /*
675 * store_byte():
676 *
677 * Stores a byte in emulated ram. (Helper function.)
678 */
store_byte(struct cpu * cpu,uint64_t addr,uint8_t data)679 void store_byte(struct cpu *cpu, uint64_t addr, uint8_t data)
680 {
681 if ((addr >> 32) == 0)
682 addr = (int64_t)(int32_t)addr;
683 cpu->memory_rw(cpu, cpu->mem,
684 addr, &data, sizeof(data), MEM_WRITE, CACHE_DATA);
685 }
686
687
688 /*
689 * store_string():
690 *
691 * Stores chars into emulated RAM until a zero byte (string terminating
692 * character) is found. The zero byte is also copied.
693 * (strcpy()-like helper function, host-RAM-to-emulated-RAM.)
694 */
store_string(struct cpu * cpu,uint64_t addr,const char * s)695 void store_string(struct cpu *cpu, uint64_t addr, const char *s)
696 {
697 do {
698 store_byte(cpu, addr++, *s);
699 } while (*s++);
700 }
701
702
703 /*
704 * add_environment_string():
705 *
706 * Like store_string(), but advances the pointer afterwards. The most
707 * obvious use is to place a number of strings (such as environment variable
708 * strings) after one-another in emulated memory.
709 */
add_environment_string(struct cpu * cpu,const char * s,uint64_t * addr)710 void add_environment_string(struct cpu *cpu, const char *s, uint64_t *addr)
711 {
712 store_string(cpu, *addr, s);
713 (*addr) += strlen(s) + 1;
714 }
715
716
717 /*
718 * add_environment_string_dual():
719 *
720 * Add "dual" environment strings, one for the variable name and one for the
721 * value, and update pointers afterwards.
722 */
add_environment_string_dual(struct cpu * cpu,uint64_t * ptrp,uint64_t * addrp,const char * s1,const char * s2)723 void add_environment_string_dual(struct cpu *cpu,
724 uint64_t *ptrp, uint64_t *addrp, const char *s1, const char *s2)
725 {
726 uint64_t ptr = *ptrp, addr = *addrp;
727
728 store_32bit_word(cpu, ptr, addr);
729 ptr += sizeof(uint32_t);
730 if (addr != 0) {
731 store_string(cpu, addr, s1);
732 addr += strlen(s1) + 1;
733 }
734 store_32bit_word(cpu, ptr, addr);
735 ptr += sizeof(uint32_t);
736 if (addr != 0) {
737 store_string(cpu, addr, s2);
738 addr += strlen(s2) + 1;
739 }
740
741 *ptrp = ptr;
742 *addrp = addr;
743 }
744
745
746 /*
747 * store_64bit_word():
748 *
749 * Stores a 64-bit word in emulated RAM. Byte order is taken into account.
750 * Helper function.
751 */
store_64bit_word(struct cpu * cpu,uint64_t addr,uint64_t data64)752 int store_64bit_word(struct cpu *cpu, uint64_t addr, uint64_t data64)
753 {
754 unsigned char data[8];
755 if ((addr >> 32) == 0)
756 addr = (int64_t)(int32_t)addr;
757 data[0] = (data64 >> 56) & 255;
758 data[1] = (data64 >> 48) & 255;
759 data[2] = (data64 >> 40) & 255;
760 data[3] = (data64 >> 32) & 255;
761 data[4] = (data64 >> 24) & 255;
762 data[5] = (data64 >> 16) & 255;
763 data[6] = (data64 >> 8) & 255;
764 data[7] = (data64) & 255;
765 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
766 int tmp = data[0]; data[0] = data[7]; data[7] = tmp;
767 tmp = data[1]; data[1] = data[6]; data[6] = tmp;
768 tmp = data[2]; data[2] = data[5]; data[5] = tmp;
769 tmp = data[3]; data[3] = data[4]; data[4] = tmp;
770 }
771 return cpu->memory_rw(cpu, cpu->mem,
772 addr, data, sizeof(data), MEM_WRITE, CACHE_DATA);
773 }
774
775
776 /*
777 * store_32bit_word():
778 *
779 * Stores a 32-bit word in emulated RAM. Byte order is taken into account.
780 * (This function takes a 64-bit word as argument, to suppress some
781 * warnings, but only the lowest 32 bits are used.)
782 */
store_32bit_word(struct cpu * cpu,uint64_t addr,uint64_t data32)783 int store_32bit_word(struct cpu *cpu, uint64_t addr, uint64_t data32)
784 {
785 unsigned char data[4];
786
787 data[0] = (data32 >> 24) & 255;
788 data[1] = (data32 >> 16) & 255;
789 data[2] = (data32 >> 8) & 255;
790 data[3] = (data32) & 255;
791 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
792 int tmp = data[0]; data[0] = data[3]; data[3] = tmp;
793 tmp = data[1]; data[1] = data[2]; data[2] = tmp;
794 }
795 return cpu->memory_rw(cpu, cpu->mem,
796 addr, data, sizeof(data), MEM_WRITE, CACHE_DATA);
797 }
798
799
800 /*
801 * store_16bit_word():
802 *
803 * Stores a 16-bit word in emulated RAM. Byte order is taken into account.
804 * (This function takes a 64-bit word as argument, to suppress some
805 * warnings, but only the lowest 16 bits are used.)
806 */
store_16bit_word(struct cpu * cpu,uint64_t addr,uint64_t data16)807 int store_16bit_word(struct cpu *cpu, uint64_t addr, uint64_t data16)
808 {
809 unsigned char data[2];
810
811 data[0] = (data16 >> 8) & 255;
812 data[1] = (data16) & 255;
813 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
814 int tmp = data[0]; data[0] = data[1]; data[1] = tmp;
815 }
816 return cpu->memory_rw(cpu, cpu->mem,
817 addr, data, sizeof(data), MEM_WRITE, CACHE_DATA);
818 }
819
820
821 /*
822 * store_buf():
823 *
824 * memcpy()-like helper function, from host RAM to emulated RAM.
825 */
store_buf(struct cpu * cpu,uint64_t addr,const char * s,size_t len)826 void store_buf(struct cpu *cpu, uint64_t addr, const char *s, size_t len)
827 {
828 size_t psize = 1024; /* 1024 256 64 16 4 1 */
829
830 while (len != 0) {
831 if ((addr & (psize-1)) == 0) {
832 while (len >= psize) {
833 cpu->memory_rw(cpu, cpu->mem, addr,
834 (unsigned char *)s, psize, MEM_WRITE,
835 CACHE_DATA);
836 addr += psize;
837 s += psize;
838 len -= psize;
839 }
840 }
841 psize >>= 2;
842 }
843
844 while (len-- != 0)
845 store_byte(cpu, addr++, *s++);
846 }
847
848
849 /*
850 * store_pointer_and_advance():
851 *
852 * Stores a 32-bit or 64-bit pointer in emulated RAM, and advances the
853 * target address. (Useful for e.g. ARCBIOS environment initialization.)
854 */
store_pointer_and_advance(struct cpu * cpu,uint64_t * addrp,uint64_t data,int flag64)855 void store_pointer_and_advance(struct cpu *cpu, uint64_t *addrp,
856 uint64_t data, int flag64)
857 {
858 uint64_t addr = *addrp;
859 if (flag64) {
860 store_64bit_word(cpu, addr, data);
861 addr += 8;
862 } else {
863 store_32bit_word(cpu, addr, data);
864 addr += 4;
865 }
866 *addrp = addr;
867 }
868
869
870 /*
871 * load_64bit_word():
872 *
873 * Helper function. Emulated byte order is taken into account.
874 */
load_64bit_word(struct cpu * cpu,uint64_t addr)875 uint64_t load_64bit_word(struct cpu *cpu, uint64_t addr)
876 {
877 unsigned char data[8];
878
879 cpu->memory_rw(cpu, cpu->mem,
880 addr, data, sizeof(data), MEM_READ, CACHE_DATA);
881
882 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
883 int tmp = data[0]; data[0] = data[7]; data[7] = tmp;
884 tmp = data[1]; data[1] = data[6]; data[6] = tmp;
885 tmp = data[2]; data[2] = data[5]; data[5] = tmp;
886 tmp = data[3]; data[3] = data[4]; data[4] = tmp;
887 }
888
889 return
890 ((uint64_t)data[0] << 56) + ((uint64_t)data[1] << 48) +
891 ((uint64_t)data[2] << 40) + ((uint64_t)data[3] << 32) +
892 ((uint64_t)data[4] << 24) + ((uint64_t)data[5] << 16) +
893 ((uint64_t)data[6] << 8) + (uint64_t)data[7];
894 }
895
896
897 /*
898 * load_32bit_word():
899 *
900 * Helper function. Emulated byte order is taken into account.
901 */
load_32bit_word(struct cpu * cpu,uint64_t addr)902 uint32_t load_32bit_word(struct cpu *cpu, uint64_t addr)
903 {
904 unsigned char data[4];
905
906 cpu->memory_rw(cpu, cpu->mem,
907 addr, data, sizeof(data), MEM_READ, CACHE_DATA);
908
909 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
910 int tmp = data[0]; data[0] = data[3]; data[3] = tmp;
911 tmp = data[1]; data[1] = data[2]; data[2] = tmp;
912 }
913
914 return (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
915 }
916
917
918 /*
919 * load_16bit_word():
920 *
921 * Helper function. Emulated byte order is taken into account.
922 */
load_16bit_word(struct cpu * cpu,uint64_t addr)923 uint16_t load_16bit_word(struct cpu *cpu, uint64_t addr)
924 {
925 unsigned char data[2];
926
927 cpu->memory_rw(cpu, cpu->mem,
928 addr, data, sizeof(data), MEM_READ, CACHE_DATA);
929
930 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
931 int tmp = data[0]; data[0] = data[1]; data[1] = tmp;
932 }
933
934 return (data[0] << 8) + data[1];
935 }
936
937
938 /*
939 * store_64bit_word_in_host():
940 *
941 * Stores a 64-bit word in the _host's_ RAM. Emulated byte order is taken
942 * into account. This is useful when building structs in the host's RAM
943 * which will later be copied into emulated RAM.
944 */
store_64bit_word_in_host(struct cpu * cpu,unsigned char * data,uint64_t data64)945 void store_64bit_word_in_host(struct cpu *cpu,
946 unsigned char *data, uint64_t data64)
947 {
948 data[0] = (data64 >> 56) & 255;
949 data[1] = (data64 >> 48) & 255;
950 data[2] = (data64 >> 40) & 255;
951 data[3] = (data64 >> 32) & 255;
952 data[4] = (data64 >> 24) & 255;
953 data[5] = (data64 >> 16) & 255;
954 data[6] = (data64 >> 8) & 255;
955 data[7] = (data64) & 255;
956 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
957 int tmp = data[0]; data[0] = data[7]; data[7] = tmp;
958 tmp = data[1]; data[1] = data[6]; data[6] = tmp;
959 tmp = data[2]; data[2] = data[5]; data[5] = tmp;
960 tmp = data[3]; data[3] = data[4]; data[4] = tmp;
961 }
962 }
963
964
965 /*
966 * store_32bit_word_in_host():
967 *
968 * See comment for store_64bit_word_in_host().
969 *
970 * (Note: The data32 parameter is a uint64_t. This is done to suppress
971 * some warnings.)
972 */
store_32bit_word_in_host(struct cpu * cpu,unsigned char * data,uint64_t data32)973 void store_32bit_word_in_host(struct cpu *cpu,
974 unsigned char *data, uint64_t data32)
975 {
976 data[0] = (data32 >> 24) & 255;
977 data[1] = (data32 >> 16) & 255;
978 data[2] = (data32 >> 8) & 255;
979 data[3] = (data32) & 255;
980 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
981 int tmp = data[0]; data[0] = data[3]; data[3] = tmp;
982 tmp = data[1]; data[1] = data[2]; data[2] = tmp;
983 }
984 }
985
986
987 /*
988 * store_16bit_word_in_host():
989 *
990 * See comment for store_64bit_word_in_host().
991 */
store_16bit_word_in_host(struct cpu * cpu,unsigned char * data,uint16_t data16)992 void store_16bit_word_in_host(struct cpu *cpu,
993 unsigned char *data, uint16_t data16)
994 {
995 data[0] = (data16 >> 8) & 255;
996 data[1] = (data16) & 255;
997 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
998 int tmp = data[0]; data[0] = data[1]; data[1] = tmp;
999 }
1000 }
1001
1002