/[gxemul]/trunk/src/emul.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/emul.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 41779 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


1 /*
2 * Copyright (C) 2003-2006 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 * $Id: emul.c,v 1.260 2006/07/26 23:21:47 debug Exp $
29 *
30 * Emulation startup and misc. routines.
31 */
32
33 #include <signal.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <limits.h>
37 #include <stdarg.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #include "arcbios.h"
42 #include "cpu.h"
43 #include "emul.h"
44 #include "console.h"
45 #include "debugger.h"
46 #include "device.h"
47 #include "diskimage.h"
48 #include "exec_elf.h"
49 #include "machine.h"
50 #include "memory.h"
51 #include "mips_cpu_types.h"
52 #include "misc.h"
53 #include "net.h"
54 #include "sgi_arcbios.h"
55 #include "x11.h"
56
57
58 extern int extra_argc;
59 extern char **extra_argv;
60
61 extern int verbose;
62 extern int quiet_mode;
63 extern int force_debugger_at_exit;
64 extern int single_step;
65 extern int old_show_trace_tree;
66 extern int old_instruction_trace;
67 extern int old_quiet_mode;
68 extern int quiet_mode;
69
70 extern struct emul *debugger_emul;
71 extern struct diskimage *diskimages[];
72
73 static char *diskimage_types[] = DISKIMAGE_TYPES;
74
75
76 static void print_separator(void)
77 {
78 int i = 79;
79 while (i-- > 0)
80 debug("-");
81 debug("\n");
82 }
83
84
85 /*
86 * add_dump_points():
87 *
88 * Take the strings breakpoint_string[] and convert to addresses
89 * (and store them in breakpoint_addr[]).
90 *
91 * TODO: This function should be moved elsewhere.
92 */
93 static void add_dump_points(struct machine *m)
94 {
95 int i;
96 int string_flag;
97 uint64_t dp;
98
99 for (i=0; i<m->n_breakpoints; i++) {
100 string_flag = 0;
101 dp = strtoull(m->breakpoint_string[i], NULL, 0);
102
103 /*
104 * If conversion resulted in 0, then perhaps it is a
105 * symbol:
106 */
107 if (dp == 0) {
108 uint64_t addr;
109 int res = get_symbol_addr(&m->symbol_context,
110 m->breakpoint_string[i], &addr);
111 if (!res) {
112 fprintf(stderr,
113 "ERROR! Breakpoint '%s' could not be"
114 " parsed\n",
115 m->breakpoint_string[i]);
116 } else {
117 dp = addr;
118 string_flag = 1;
119 }
120 }
121
122 /*
123 * TODO: It would be nice if things like symbolname+0x1234
124 * were automatically converted into the correct address.
125 */
126
127 if (m->arch == ARCH_MIPS) {
128 if ((dp >> 32) == 0 && ((dp >> 31) & 1))
129 dp |= 0xffffffff00000000ULL;
130 }
131
132 m->breakpoint_addr[i] = dp;
133
134 debug("breakpoint %i: 0x%llx", i, (long long)dp);
135 if (string_flag)
136 debug(" (%s)", m->breakpoint_string[i]);
137 debug("\n");
138 }
139 }
140
141
142 /*
143 * fix_console():
144 */
145 static void fix_console(void)
146 {
147 console_deinit();
148 }
149
150
151 /*
152 * iso_load_bootblock():
153 *
154 * Try to load a kernel from an ISO 9660 disk image. iso_type is 1 for
155 * "CD001" (standard), 2 for "CDW01" (ECMA), and 3 for "CDROM" (Sierra).
156 *
157 * TODO: This function uses too many magic offsets and so on; it should be
158 * cleaned up some day.
159 *
160 * Returns 1 on success, 0 on failure.
161 */
162 static int iso_load_bootblock(struct machine *m, struct cpu *cpu,
163 int disk_id, int disk_type, int iso_type, unsigned char *buf,
164 int *n_loadp, char ***load_namesp)
165 {
166 char str[35];
167 int filenr, i, ofs, dirlen, res = 0, res2, iadd = DEBUG_INDENTATION;
168 int found_dir;
169 uint64_t dirofs;
170 uint64_t fileofs, filelen;
171 unsigned char *dirbuf = NULL, *dp;
172 unsigned char *match_entry = NULL;
173 char *p, *filename_orig;
174 char *filename = strdup(cpu->machine->boot_kernel_filename);
175 unsigned char *filebuf = NULL;
176 char *tmpfname = NULL;
177 char **new_array;
178 int tmpfile_handle;
179
180 if (filename == NULL) {
181 fatal("out of memory\n");
182 exit(1);
183 }
184 filename_orig = filename;
185
186 debug("ISO9660 boot:\n");
187 debug_indentation(iadd);
188
189 /* Volume ID: */
190 ofs = iso_type == 3? 48 : 40;
191 memcpy(str, buf + ofs, sizeof(str));
192 str[32] = '\0'; i = 31;
193 while (i >= 0 && str[i]==' ')
194 str[i--] = '\0';
195 if (str[0])
196 debug("\"%s\"", str);
197 else {
198 /* System ID: */
199 ofs = iso_type == 3? 16 : 8;
200 memcpy(str, buf + ofs, sizeof(str));
201 str[32] = '\0'; i = 31;
202 while (i >= 0 && str[i]==' ')
203 str[i--] = '\0';
204 if (str[0])
205 debug("\"%s\"", str);
206 else
207 debug("(no ID)");
208 }
209
210 debug(":%s\n", filename);
211
212
213 /*
214 * Traverse the directory structure to find the kernel.
215 */
216
217 dirlen = buf[0x84] + 256*buf[0x85] + 65536*buf[0x86];
218 if (dirlen != buf[0x8b] + 256*buf[0x8a] + 65536*buf[0x89])
219 fatal("WARNING: Root directory length mismatch?\n");
220
221 dirofs = (int64_t)(buf[0x8c] + (buf[0x8d] << 8) + (buf[0x8e] << 16) +
222 ((uint64_t)buf[0x8f] << 24)) * 2048;
223
224 /* debug("root = %i bytes at 0x%llx\n", dirlen, (long long)dirofs); */
225
226 dirbuf = malloc(dirlen);
227 if (dirbuf == NULL) {
228 fatal("out of memory in iso_load_bootblock()\n");
229 exit(1);
230 }
231
232 res2 = diskimage_access(m, disk_id, disk_type, 0, dirofs, dirbuf,
233 dirlen);
234 if (!res2) {
235 fatal("Couldn't read the disk image. Aborting.\n");
236 goto ret;
237 }
238
239 found_dir = 1; /* Assume root dir */
240 dp = dirbuf; filenr = 1;
241 p = NULL;
242 while (dp < dirbuf + dirlen) {
243 size_t i, nlen = dp[0];
244 int x = dp[2] + (dp[3] << 8) + (dp[4] << 16) +
245 ((uint64_t)dp[5] << 24);
246 int y = dp[6] + (dp[7] << 8);
247 char direntry[65];
248
249 dp += 8;
250
251 /*
252 * As long as there is an \ or / in the filename, then we
253 * have not yet found the directory.
254 */
255 p = strchr(filename, '/');
256 if (p == NULL)
257 p = strchr(filename, '\\');
258
259 /* debug("%i%s: %i, %i, \"", filenr, filenr == found_dir?
260 " [CURRENT]" : "", x, y); */
261 for (i=0; i<nlen && i<sizeof(direntry)-1; i++)
262 if (dp[i]) {
263 direntry[i] = dp[i];
264 /* debug("%c", dp[i]); */
265 } else
266 break;
267 /* debug("\"\n"); */
268 direntry[i] = '\0';
269
270 /* A directory name match? */
271 if (p != NULL && strncasecmp(filename, direntry, nlen) == 0
272 && nlen == (size_t)p - (size_t)filename && found_dir == y) {
273 found_dir = filenr;
274 filename = p+1;
275 dirofs = 2048 * (int64_t)x;
276 }
277
278 dp += nlen;
279
280 /* 16-bit aligned lenght: */
281 if (nlen & 1)
282 dp ++;
283
284 filenr ++;
285 }
286
287 p = strchr(filename, '/');
288 if (p == NULL)
289 p = strchr(filename, '\\');
290
291 if (p != NULL) {
292 char *blah = filename_orig;
293
294 fatal("could not find '%s' in /", filename);
295
296 /* Print the first part of the filename: */
297 while (blah != filename)
298 fatal("%c", *blah++);
299
300 fatal("\n");
301 goto ret;
302 }
303
304 /* debug("dirofs = 0x%llx\n", (long long)dirofs); */
305
306 /* Free the old dirbuf, and allocate a new one: */
307 free(dirbuf);
308 dirbuf = malloc(512);
309 if (dirbuf == NULL) {
310 fatal("out of memory in iso_load_bootblock()\n");
311 exit(1);
312 }
313
314 for (;;) {
315 size_t len, i;
316
317 /* Too close to another sector? Then realign. */
318 if ((dirofs & 2047) + 70 > 2047) {
319 dirofs = (dirofs | 2047) + 1;
320 /* debug("realign dirofs = 0x%llx\n", dirofs); */
321 }
322
323 res2 = diskimage_access(m, disk_id, disk_type, 0, dirofs,
324 dirbuf, 256);
325 if (!res2) {
326 fatal("Couldn't read the disk image. Aborting.\n");
327 goto ret;
328 }
329
330 dp = dirbuf;
331 len = dp[0];
332 if (len < 2)
333 break;
334
335 /*
336 * TODO: Actually parse the directory entry!
337 *
338 * Haha, this must be rewritten.
339 */
340 for (i=32; i<len; i++) {
341 if (i < len - strlen(filename))
342 if (strncasecmp(filename, (char *)dp + i,
343 strlen(filename)) == 0) {
344 /* The filename was found somewhere
345 in the directory entry. */
346 if (match_entry != NULL) {
347 fatal("TODO: I'm too lazy to"
348 " implement a correct "
349 "directory parser right "
350 "now... (BUG)\n");
351 exit(1);
352 }
353 match_entry = malloc(512);
354 if (match_entry == NULL) {
355 fatal("out of memory\n");
356 exit(1);
357 }
358 memcpy(match_entry, dp, 512);
359 break;
360 }
361 }
362
363 dirofs += len;
364 }
365
366 if (match_entry == NULL) {
367 char *blah = filename_orig;
368
369 fatal("could not find '%s' in /", filename);
370
371 /* Print the first part of the filename: */
372 while (blah != filename)
373 fatal("%c", *blah++);
374
375 fatal("\n");
376 goto ret;
377 }
378
379 fileofs = match_entry[2] + (match_entry[3] << 8) +
380 (match_entry[4] << 16) + ((uint64_t)match_entry[5] << 24);
381 filelen = match_entry[10] + (match_entry[11] << 8) +
382 (match_entry[12] << 16) + ((uint64_t)match_entry[13] << 24);
383 fileofs *= 2048;
384
385 /* debug("filelen=%llx fileofs=%llx\n", (long long)filelen,
386 (long long)fileofs); */
387
388 filebuf = malloc(filelen);
389 if (filebuf == NULL) {
390 fatal("could not allocate %lli bytes to read the file"
391 " from the disk image!\n", (long long)filelen);
392 goto ret;
393 }
394
395 tmpfname = strdup("/tmp/gxemul.XXXXXXXXXXXX");
396
397 res2 = diskimage_access(m, disk_id, disk_type, 0, fileofs, filebuf,
398 filelen);
399 if (!res2) {
400 fatal("could not read the file from the disk image!\n");
401 goto ret;
402 }
403
404 tmpfile_handle = mkstemp(tmpfname);
405 if (tmpfile_handle < 0) {
406 fatal("could not create %s\n", tmpfname);
407 exit(1);
408 }
409 write(tmpfile_handle, filebuf, filelen);
410 close(tmpfile_handle);
411
412 debug("extracted %lli bytes into %s\n", (long long)filelen, tmpfname);
413
414 /* Add the temporary filename to the load_namesp array: */
415 (*n_loadp)++;
416 new_array = malloc(sizeof(char *) * (*n_loadp));
417 if (new_array == NULL) {
418 fatal("out of memory\n");
419 exit(1);
420 }
421 memcpy(new_array, *load_namesp, sizeof(char *) * (*n_loadp));
422 *load_namesp = new_array;
423
424 /* This adds a Backspace char in front of the filename; this
425 is a special hack which causes the file to be removed once
426 it has been loaded. */
427 tmpfname = realloc(tmpfname, strlen(tmpfname) + 2);
428 memmove(tmpfname + 1, tmpfname, strlen(tmpfname) + 1);
429 tmpfname[0] = 8;
430
431 (*load_namesp)[*n_loadp - 1] = tmpfname;
432
433 res = 1;
434
435 ret:
436 if (dirbuf != NULL)
437 free(dirbuf);
438
439 if (filebuf != NULL)
440 free(filebuf);
441
442 if (match_entry != NULL)
443 free(match_entry);
444
445 free(filename_orig);
446
447 debug_indentation(-iadd);
448 return res;
449 }
450
451
452 /*
453 * apple_load_bootblock():
454 *
455 * Try to load a kernel from a disk image with an Apple Partition Table.
456 *
457 * TODO: This function uses too many magic offsets and so on; it should be
458 * cleaned up some day. See http://www.awprofessional.com/articles/
459 * article.asp?p=376123&seqNum=3&rl=1 for some info on the Apple
460 * partition format.
461 *
462 * Returns 1 on success, 0 on failure.
463 */
464 static int apple_load_bootblock(struct machine *m, struct cpu *cpu,
465 int disk_id, int disk_type, int *n_loadp, char ***load_namesp)
466 {
467 unsigned char buf[0x8000];
468 int res, partnr, n_partitions = 0, n_hfs_partitions = 0;
469 uint64_t hfs_start, hfs_length;
470
471 res = diskimage_access(m, disk_id, disk_type, 0, 0x0, buf, sizeof(buf));
472 if (!res) {
473 fatal("apple_load_bootblock: couldn't read the disk "
474 "image. Aborting.\n");
475 return 0;
476 }
477
478 partnr = 0;
479 do {
480 int start, length;
481 int ofs = 0x200 * (partnr + 1);
482 if (partnr == 0)
483 n_partitions = buf[ofs + 7];
484 start = ((uint64_t)buf[ofs + 8] << 24) + (buf[ofs + 9] << 16) +
485 (buf[ofs + 10] << 8) + buf[ofs + 11];
486 length = ((uint64_t)buf[ofs+12] << 24) + (buf[ofs + 13] << 16) +
487 (buf[ofs + 14] << 8) + buf[ofs + 15];
488
489 debug("partition %i: '%s', type '%s', start %i, length %i\n",
490 partnr, buf + ofs + 0x10, buf + ofs + 0x30,
491 start, length);
492
493 if (strcmp((char *)buf + ofs + 0x30, "Apple_HFS") == 0) {
494 n_hfs_partitions ++;
495 hfs_start = 512 * start;
496 hfs_length = 512 * length;
497 }
498
499 /* Any more partitions? */
500 partnr ++;
501 } while (partnr < n_partitions);
502
503 if (n_hfs_partitions == 0) {
504 fatal("Error: No HFS partition found! TODO\n");
505 return 0;
506 }
507 if (n_hfs_partitions >= 2) {
508 fatal("Error: Too many HFS partitions found! TODO\n");
509 return 0;
510 }
511
512 return 0;
513 }
514
515
516 /*
517 * load_bootblock():
518 *
519 * For some emulation modes, it is possible to boot from a harddisk image by
520 * loading a bootblock from a specific disk offset into memory, and executing
521 * that, instead of requiring a separate kernel file. It is then up to the
522 * bootblock to load a kernel.
523 *
524 * Returns 1 on success, 0 on failure.
525 */
526 static int load_bootblock(struct machine *m, struct cpu *cpu,
527 int *n_loadp, char ***load_namesp)
528 {
529 int boot_disk_id, boot_disk_type = 0, n_blocks, res, readofs,
530 iso_type, retval = 0;
531 unsigned char minibuf[0x20];
532 unsigned char *bootblock_buf;
533 uint64_t bootblock_offset;
534 uint64_t bootblock_loadaddr, bootblock_pc;
535
536 boot_disk_id = diskimage_bootdev(m, &boot_disk_type);
537 if (boot_disk_id < 0)
538 return 0;
539
540 switch (m->machine_type) {
541 case MACHINE_PMAX:
542 /*
543 * The first few bytes of a disk contains information about
544 * where the bootblock(s) are located. (These are all 32-bit
545 * little-endian words.)
546 *
547 * Offset 0x10 = load address
548 * 0x14 = initial PC value
549 * 0x18 = nr of 512-byte blocks to read
550 * 0x1c = offset on disk to where the bootblocks
551 * are (in 512-byte units)
552 * 0x20 = nr of blocks to read...
553 * 0x24 = offset...
554 *
555 * nr of blocks to read and offset are repeated until nr of
556 * blocks to read is zero.
557 */
558 res = diskimage_access(m, boot_disk_id, boot_disk_type, 0, 0,
559 minibuf, sizeof(minibuf));
560
561 bootblock_loadaddr = minibuf[0x10] + (minibuf[0x11] << 8)
562 + (minibuf[0x12] << 16) + ((uint64_t)minibuf[0x13] << 24);
563
564 /* Convert loadaddr to uncached: */
565 if ((bootblock_loadaddr & 0xf0000000ULL) != 0x80000000 &&
566 (bootblock_loadaddr & 0xf0000000ULL) != 0xa0000000)
567 fatal("\nWARNING! Weird load address 0x%08x.\n\n",
568 (int)bootblock_loadaddr);
569 bootblock_loadaddr &= 0x0fffffffULL;
570 bootblock_loadaddr |= 0xffffffffa0000000ULL;
571
572 bootblock_pc = minibuf[0x14] + (minibuf[0x15] << 8)
573 + (minibuf[0x16] << 16) + ((uint64_t)minibuf[0x17] << 24);
574
575 bootblock_pc &= 0x0fffffffULL;
576 bootblock_pc |= 0xffffffffa0000000ULL;
577 cpu->pc = bootblock_pc;
578
579 debug("DEC boot: loadaddr=0x%08x, pc=0x%08x",
580 (int)bootblock_loadaddr, (int)bootblock_pc);
581
582 readofs = 0x18;
583
584 for (;;) {
585 res = diskimage_access(m, boot_disk_id, boot_disk_type,
586 0, readofs, minibuf, sizeof(minibuf));
587 if (!res) {
588 fatal("Couldn't read the disk image. "
589 "Aborting.\n");
590 return 0;
591 }
592
593 n_blocks = minibuf[0] + (minibuf[1] << 8)
594 + (minibuf[2] << 16) + ((uint64_t)minibuf[3] << 24);
595
596 bootblock_offset = (minibuf[4] + (minibuf[5] << 8) +
597 (minibuf[6]<<16) + ((uint64_t)minibuf[7]<<24)) * 512;
598
599 if (n_blocks < 1)
600 break;
601
602 debug(readofs == 0x18? ": %i" : " + %i", n_blocks);
603
604 if (n_blocks * 512 > 65536)
605 fatal("\nWARNING! Unusually large bootblock "
606 "(%i bytes)\n\n", n_blocks * 512);
607
608 bootblock_buf = malloc(n_blocks * 512);
609 if (bootblock_buf == NULL) {
610 fprintf(stderr, "out of memory in "
611 "load_bootblock()\n");
612 exit(1);
613 }
614
615 res = diskimage_access(m, boot_disk_id, boot_disk_type,
616 0, bootblock_offset, bootblock_buf, n_blocks * 512);
617 if (!res) {
618 fatal("WARNING: could not load bootblocks from"
619 " disk offset 0x%llx\n",
620 (long long)bootblock_offset);
621 }
622
623 store_buf(cpu, bootblock_loadaddr,
624 (char *)bootblock_buf, n_blocks * 512);
625
626 bootblock_loadaddr += 512*n_blocks;
627 free(bootblock_buf);
628 readofs += 8;
629 }
630
631 debug(readofs == 0x18? ": no blocks?\n" : " blocks\n");
632 return 1;
633
634 case MACHINE_X86:
635 /* TODO: "El Torito" etc? */
636 if (diskimage_is_a_cdrom(cpu->machine, boot_disk_id,
637 boot_disk_type))
638 break;
639
640 bootblock_buf = malloc(512);
641 if (bootblock_buf == NULL) {
642 fprintf(stderr, "Out of memory.\n");
643 exit(1);
644 }
645
646 debug("loading PC bootsector from %s id %i\n",
647 diskimage_types[boot_disk_type], boot_disk_id);
648
649 res = diskimage_access(m, boot_disk_id, boot_disk_type, 0, 0,
650 bootblock_buf, 512);
651 if (!res) {
652 fatal("Couldn't read the disk image. Aborting.\n");
653 return 0;
654 }
655
656 if (bootblock_buf[510] != 0x55 || bootblock_buf[511] != 0xaa)
657 debug("WARNING! The 0x55,0xAA marker is missing! "
658 "Booting anyway.\n");
659 store_buf(cpu, 0x7c00, (char *)bootblock_buf, 512);
660 free(bootblock_buf);
661
662 return 1;
663 }
664
665
666 /*
667 * Try reading a kernel manually from the disk. The code here
668 * does not rely on machine-dependent boot blocks etc.
669 */
670 /* ISO9660: (0x800 bytes at 0x8000) */
671 bootblock_buf = malloc(0x800);
672 if (bootblock_buf == NULL) {
673 fprintf(stderr, "Out of memory.\n");
674 exit(1);
675 }
676
677 res = diskimage_access(m, boot_disk_id, boot_disk_type,
678 0, 0x8000, bootblock_buf, 0x800);
679 if (!res) {
680 fatal("Couldn't read the disk image. Aborting.\n");
681 return 0;
682 }
683
684 iso_type = 0;
685 if (strncmp((char *)bootblock_buf+1, "CD001", 5) == 0)
686 iso_type = 1;
687 if (strncmp((char *)bootblock_buf+1, "CDW01", 5) == 0)
688 iso_type = 2;
689 if (strncmp((char *)bootblock_buf+1, "CDROM", 5) == 0)
690 iso_type = 3;
691
692 if (iso_type != 0) {
693 /* We can't load a kernel if the name
694 isn't specified. */
695 if (cpu->machine->boot_kernel_filename == NULL ||
696 cpu->machine->boot_kernel_filename[0] == '\0')
697 fatal("\nISO9660 filesystem, but no kernel "
698 "specified? (Use the -j option.)\n");
699 else
700 retval = iso_load_bootblock(m, cpu, boot_disk_id,
701 boot_disk_type, iso_type, bootblock_buf,
702 n_loadp, load_namesp);
703 }
704
705 if (retval != 0)
706 goto ret_ok;
707
708 /* Apple parition table: */
709 res = diskimage_access(m, boot_disk_id, boot_disk_type,
710 0, 0x0, bootblock_buf, 0x800);
711 if (!res) {
712 fatal("Couldn't read the disk image. Aborting.\n");
713 return 0;
714 }
715 if (bootblock_buf[0x000] == 'E' && bootblock_buf[0x001] == 'R' &&
716 bootblock_buf[0x200] == 'P' && bootblock_buf[0x201] == 'M') {
717 /* We can't load a kernel if the name
718 isn't specified. */
719 if (cpu->machine->boot_kernel_filename == NULL ||
720 cpu->machine->boot_kernel_filename[0] == '\0')
721 fatal("\nApple partition table, but no kernel "
722 "specified? (Use the -j option.)\n");
723 else
724 retval = apple_load_bootblock(m, cpu, boot_disk_id,
725 boot_disk_type, n_loadp, load_namesp);
726 }
727
728 ret_ok:
729 free(bootblock_buf);
730 return retval;
731 }
732
733
734 /*
735 * emul_new():
736 *
737 * Returns a reasonably initialized struct emul.
738 */
739 struct emul *emul_new(char *name)
740 {
741 struct emul *e;
742 e = malloc(sizeof(struct emul));
743 if (e == NULL) {
744 fprintf(stderr, "out of memory in emul_new()\n");
745 exit(1);
746 }
747
748 memset(e, 0, sizeof(struct emul));
749
750 /* Sane default values: */
751 e->n_machines = 0;
752 e->next_serial_nr = 1;
753
754 if (name != NULL) {
755 e->name = strdup(name);
756 if (e->name == NULL) {
757 fprintf(stderr, "out of memory in emul_new()\n");
758 exit(1);
759 }
760 }
761
762 return e;
763 }
764
765
766 /*
767 * emul_add_machine():
768 *
769 * Calls machine_new(), adds the new machine into the emul struct, and
770 * returns a pointer to the new machine.
771 *
772 * This function should be used instead of manually calling machine_new().
773 */
774 struct machine *emul_add_machine(struct emul *e, char *name)
775 {
776 struct machine *m;
777
778 m = machine_new(name, e);
779 m->serial_nr = (e->next_serial_nr ++);
780
781 e->n_machines ++;
782 e->machines = realloc(e->machines,
783 sizeof(struct machine *) * e->n_machines);
784 if (e->machines == NULL) {
785 fprintf(stderr, "emul_add_machine(): out of memory\n");
786 exit(1);
787 }
788
789 e->machines[e->n_machines - 1] = m;
790 return m;
791 }
792
793
794 /*
795 * add_arc_components():
796 *
797 * This function adds ARCBIOS memory descriptors for the loaded program,
798 * and ARCBIOS components for SCSI devices.
799 */
800 static void add_arc_components(struct machine *m)
801 {
802 struct cpu *cpu = m->cpus[m->bootstrap_cpu];
803 uint64_t start = cpu->pc & 0x1fffffff;
804 uint64_t len = 0xc00000 - start;
805 struct diskimage *d;
806 uint64_t scsicontroller, scsidevice, scsidisk;
807
808 if ((cpu->pc >> 60) != 0xf) {
809 start = cpu->pc & 0xffffffffffULL;
810 len = 0xc00000 - start;
811 }
812
813 len += 1048576 * m->memory_offset_in_mb;
814
815 /*
816 * NOTE/TODO: magic 12MB end of load program area
817 *
818 * Hm. This breaks the old FreeBSD/MIPS snapshots...
819 */
820 #if 0
821 arcbios_add_memory_descriptor(cpu,
822 0x60000 + m->memory_offset_in_mb * 1048576,
823 start-0x60000 - m->memory_offset_in_mb * 1048576,
824 ARCBIOS_MEM_FreeMemory);
825 #endif
826 arcbios_add_memory_descriptor(cpu,
827 start, len, ARCBIOS_MEM_LoadedProgram);
828
829 scsicontroller = arcbios_get_scsicontroller(m);
830 if (scsicontroller == 0)
831 return;
832
833 /* TODO: The device 'name' should defined be somewhere else. */
834
835 d = m->first_diskimage;
836 while (d != NULL) {
837 if (d->type == DISKIMAGE_SCSI) {
838 int a, b, flags = COMPONENT_FLAG_Input;
839 char component_string[100];
840 char *name = "DEC RZ58 (C) DEC2000";
841
842 /* Read-write, or read-only? */
843 if (d->writable)
844 flags |= COMPONENT_FLAG_Output;
845 else
846 flags |= COMPONENT_FLAG_ReadOnly;
847
848 a = COMPONENT_TYPE_DiskController;
849 b = COMPONENT_TYPE_DiskPeripheral;
850
851 if (d->is_a_cdrom) {
852 flags |= COMPONENT_FLAG_Removable;
853 a = COMPONENT_TYPE_CDROMController;
854 b = COMPONENT_TYPE_FloppyDiskPeripheral;
855 name = "NEC CD-ROM CDR-210P 1.0 ";
856 }
857
858 scsidevice = arcbios_addchild_manual(cpu,
859 COMPONENT_CLASS_ControllerClass,
860 a, flags, 1, 2, d->id, 0xffffffff,
861 name, scsicontroller, NULL, 0);
862
863 scsidisk = arcbios_addchild_manual(cpu,
864 COMPONENT_CLASS_PeripheralClass,
865 b, flags, 1, 2, 0, 0xffffffff, NULL,
866 scsidevice, NULL, 0);
867
868 /*
869 * Add device string to component address mappings:
870 * "scsi(0)disk(0)rdisk(0)partition(0)"
871 */
872
873 if (d->is_a_cdrom) {
874 snprintf(component_string,
875 sizeof(component_string),
876 "scsi(0)cdrom(%i)", d->id);
877 arcbios_add_string_to_component(m,
878 component_string, scsidevice);
879
880 snprintf(component_string,
881 sizeof(component_string),
882 "scsi(0)cdrom(%i)fdisk(0)", d->id);
883 arcbios_add_string_to_component(m,
884 component_string, scsidisk);
885 } else {
886 snprintf(component_string,
887 sizeof(component_string),
888 "scsi(0)disk(%i)", d->id);
889 arcbios_add_string_to_component(m,
890 component_string, scsidevice);
891
892 snprintf(component_string,
893 sizeof(component_string),
894 "scsi(0)disk(%i)rdisk(0)", d->id);
895 arcbios_add_string_to_component(m,
896 component_string, scsidisk);
897 }
898 }
899
900 d = d->next;
901 }
902 }
903
904
905 /*
906 * emul_machine_setup():
907 *
908 * o) Initialize the hardware (RAM, devices, CPUs, ...) which
909 * will be emulated in this machine.
910 *
911 * o) Load ROM code and/or other programs into emulated memory.
912 *
913 * o) Special hacks needed after programs have been loaded.
914 */
915 void emul_machine_setup(struct machine *m, int n_load, char **load_names,
916 int n_devices, char **device_names)
917 {
918 struct cpu *cpu;
919 int i, iadd = DEBUG_INDENTATION;
920 uint64_t memory_amount, entrypoint = 0, gp = 0, toc = 0;
921 int byte_order;
922
923 debug("machine \"%s\":\n", m->name);
924 debug_indentation(iadd);
925
926 /* For userland-only, this decides which ARCH/cpu_name to use: */
927 if (m->machine_type == MACHINE_USERLAND && m->userland_emul != NULL) {
928 useremul_name_to_useremul(NULL, m->userland_emul,
929 &m->arch, &m->machine_name, &m->cpu_name);
930 if (m->arch == ARCH_NOARCH) {
931 printf("Unsupported userland emulation mode.\n");
932 exit(1);
933 }
934 }
935
936 if (m->machine_type == MACHINE_NONE) {
937 fatal("No machine type specified?\n");
938 exit(1);
939 }
940
941 m->cpu_family = cpu_family_ptr_by_number(m->arch);
942
943 if (m->arch == ARCH_ALPHA)
944 m->arch_pagesize = 8192;
945
946 machine_memsize_fix(m);
947
948 /*
949 * Create the system's memory:
950 *
951 * (Don't print the amount for userland-only emulation; the
952 * size doesn't matter.)
953 */
954 if (m->machine_type != MACHINE_USERLAND)
955 debug("memory: %i MB", m->physical_ram_in_mb);
956 memory_amount = (uint64_t)m->physical_ram_in_mb * 1048576;
957 if (m->memory_offset_in_mb > 0) {
958 /*
959 * A special hack is used for some SGI models,
960 * where memory is offset by 128MB to leave room for
961 * EISA space and other things.
962 */
963 debug(" (offset by %iMB)", m->memory_offset_in_mb);
964 memory_amount += 1048576 * m->memory_offset_in_mb;
965 }
966 m->memory = memory_new(memory_amount, m->arch);
967 if (m->machine_type != MACHINE_USERLAND)
968 debug("\n");
969
970 /* Create CPUs: */
971 if (m->cpu_name == NULL)
972 machine_default_cputype(m);
973 if (m->ncpus == 0) {
974 /* TODO: This should be moved elsewhere... */
975 if (m->machine_type == MACHINE_BEBOX)
976 m->ncpus = 2;
977 else if (m->machine_type == MACHINE_ARC &&
978 m->machine_subtype == MACHINE_ARC_NEC_R96)
979 m->ncpus = 2;
980 else if (m->machine_type == MACHINE_ARC &&
981 m->machine_subtype == MACHINE_ARC_NEC_R98)
982 m->ncpus = 4;
983 else
984 m->ncpus = 1;
985 }
986 m->cpus = malloc(sizeof(struct cpu *) * m->ncpus);
987 if (m->cpus == NULL) {
988 fprintf(stderr, "out of memory\n");
989 exit(1);
990 }
991 memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);
992
993 debug("cpu0");
994 if (m->ncpus > 1)
995 debug(" .. cpu%i", m->ncpus - 1);
996 debug(": ");
997 for (i=0; i<m->ncpus; i++) {
998 m->cpus[i] = cpu_new(m->memory, m, i, m->cpu_name);
999 if (m->cpus[i] == NULL) {
1000 fprintf(stderr, "Unable to create CPU object. "
1001 "Aborting.");
1002 exit(1);
1003 }
1004 }
1005 debug("\n");
1006
1007 #if 0
1008 /* Special case: The Playstation Portable has an additional CPU: */
1009 if (m->machine_type == MACHINE_PSP) {
1010 debug("cpu%i: ", m->ncpus);
1011 m->cpus[m->ncpus] = cpu_new(m->memory, m,
1012 0 /* use 0 here to show info with debug() */,
1013 "Allegrex" /* TODO */);
1014 debug("\n");
1015 m->ncpus ++;
1016 }
1017 #endif
1018
1019 if (m->use_random_bootstrap_cpu)
1020 m->bootstrap_cpu = random() % m->ncpus;
1021 else
1022 m->bootstrap_cpu = 0;
1023
1024 cpu = m->cpus[m->bootstrap_cpu];
1025
1026 /* Set cpu->useremul_syscall, and use userland_memory_rw: */
1027 if (m->userland_emul != NULL) {
1028 useremul_name_to_useremul(cpu,
1029 m->userland_emul, NULL, NULL, NULL);
1030
1031 switch (m->arch) {
1032 #ifdef ENABLE_ALPHA
1033 case ARCH_ALPHA:
1034 cpu->memory_rw = alpha_userland_memory_rw;
1035 break;
1036 #endif
1037 default:cpu->memory_rw = userland_memory_rw;
1038 }
1039 }
1040
1041 if (m->use_x11)
1042 x11_init(m);
1043
1044 /* Fill memory with random bytes: */
1045 if (m->random_mem_contents) {
1046 for (i=0; i<m->physical_ram_in_mb * 1048576; i+=256) {
1047 unsigned char data[256];
1048 unsigned int j;
1049 for (j=0; j<sizeof(data); j++)
1050 data[j] = random() & 255;
1051 cpu->memory_rw(cpu, m->memory, i, data, sizeof(data),
1052 MEM_WRITE, CACHE_NONE | NO_EXCEPTIONS | PHYSICAL);
1053 }
1054 }
1055
1056 if (m->userland_emul != NULL) {
1057 /*
1058 * For userland-only emulation, no machine emulation
1059 * is needed.
1060 */
1061 } else {
1062 for (i=0; i<n_devices; i++)
1063 device_add(m, device_names[i]);
1064
1065 machine_setup(m);
1066 }
1067
1068 diskimage_dump_info(m);
1069 console_debug_dump(m);
1070
1071 /* Load files (ROM code, boot code, ...) into memory: */
1072 if (n_load == 0) {
1073 if (m->first_diskimage != NULL) {
1074 if (!load_bootblock(m, cpu, &n_load, &load_names)) {
1075 fprintf(stderr, "\nNo executable files were"
1076 " specified, and booting directly from disk"
1077 " failed.\n");
1078 exit(1);
1079 }
1080 } else {
1081 fprintf(stderr, "No executable file(s) loaded, and "
1082 "we are not booting directly from a disk image."
1083 "\nAborting.\n");
1084 exit(1);
1085 }
1086 }
1087
1088 while (n_load > 0) {
1089 FILE *tmp_f;
1090 char *name_to_load = *load_names;
1091 int remove_after_load = 0;
1092
1093 /* Special hack for removing temporary files: */
1094 if (name_to_load[0] == 8) {
1095 name_to_load ++;
1096 remove_after_load = 1;
1097 }
1098
1099 /*
1100 * gzipped files are automagically gunzipped:
1101 * NOTE/TODO: This isn't secure. system() is used.
1102 */
1103 tmp_f = fopen(name_to_load, "r");
1104 if (tmp_f != NULL) {
1105 unsigned char buf[2]; /* gzip header */
1106 memset(buf, 0, sizeof(buf));
1107 fread(buf, 1, sizeof(buf), tmp_f);
1108 if (buf[0]==0x1f && buf[1]==0x8b) {
1109 size_t zzlen = strlen(name_to_load)*2 + 100;
1110 char *zz = malloc(zzlen);
1111 debug("gunziping %s\n", name_to_load);
1112 /*
1113 * gzip header found. If this was a file
1114 * extracted from, say, a CDROM image, then it
1115 * already has a temporary name. Otherwise we
1116 * have to gunzip into a temporary file.
1117 */
1118 if (remove_after_load) {
1119 snprintf(zz, zzlen, "mv %s %s.gz",
1120 name_to_load, name_to_load);
1121 system(zz);
1122 snprintf(zz, zzlen, "gunzip %s.gz",
1123 name_to_load);
1124 system(zz);
1125 } else {
1126 /* gunzip into new temp file: */
1127 int tmpfile_handle;
1128 char *new_temp_name =
1129 strdup("/tmp/gxemul.XXXXXXXXXXXX");
1130 tmpfile_handle = mkstemp(new_temp_name);
1131 close(tmpfile_handle);
1132 snprintf(zz, zzlen, "gunzip -c '%s' > "
1133 "%s", name_to_load, new_temp_name);
1134 system(zz);
1135 name_to_load = new_temp_name;
1136 remove_after_load = 1;
1137 }
1138 free(zz);
1139 }
1140 fclose(tmp_f);
1141 }
1142
1143 /*
1144 * Ugly (but usable) hack for Playstation Portable: If the
1145 * filename ends with ".pbp" and the file contains an ELF
1146 * header, then extract the ELF file into a temporary file.
1147 */
1148 if (strlen(name_to_load) > 4 && strcasecmp(name_to_load +
1149 strlen(name_to_load) - 4, ".pbp") == 0 &&
1150 (tmp_f = fopen(name_to_load, "r")) != NULL) {
1151 off_t filesize, j, found=0;
1152 unsigned char *buf;
1153 fseek(tmp_f, 0, SEEK_END);
1154 filesize = ftello(tmp_f);
1155 fseek(tmp_f, 0, SEEK_SET);
1156 buf = malloc(filesize);
1157 if (buf == NULL) {
1158 fprintf(stderr, "out of memory while trying"
1159 " to read %s\n", name_to_load);
1160 exit(1);
1161 }
1162 fread(buf, 1, filesize, tmp_f);
1163 fclose(tmp_f);
1164 /* Search for the ELF header, from offset 1 (!): */
1165 for (j=1; j<filesize - 4; j++)
1166 if (memcmp(buf + j, ELFMAG, SELFMAG) == 0) {
1167 found = j;
1168 break;
1169 }
1170 if (found != 0) {
1171 int tmpfile_handle;
1172 char *new_temp_name =
1173 strdup("/tmp/gxemul.XXXXXXXXXXXX");
1174 debug("extracting ELF from %s (offset 0x%x)\n",
1175 name_to_load, (int)found);
1176 tmpfile_handle = mkstemp(new_temp_name);
1177 write(tmpfile_handle, buf + found,
1178 filesize - found);
1179 close(tmpfile_handle);
1180 name_to_load = new_temp_name;
1181 remove_after_load = 1;
1182 }
1183 }
1184
1185 /* Special things required _before_ loading the file: */
1186 switch (m->arch) {
1187 case ARCH_X86:
1188 /*
1189 * X86 machines normally don't need to load any files,
1190 * they can boot from disk directly. Therefore, an x86
1191 * machine usually boots up in 16-bit real mode. When
1192 * loading a 32-bit (or even 64-bit) ELF, that's not
1193 * very nice, hence this special case.
1194 */
1195 pc_bios_simple_pmode_setup(cpu);
1196 break;
1197 }
1198
1199 byte_order = NO_BYTE_ORDER_OVERRIDE;
1200
1201 /*
1202 * Load the file: :-)
1203 */
1204 file_load(m, m->memory, name_to_load, &entrypoint,
1205 m->arch, &gp, &byte_order, &toc);
1206
1207 if (remove_after_load) {
1208 debug("removing %s\n", name_to_load);
1209 unlink(name_to_load);
1210 }
1211
1212 if (byte_order != NO_BYTE_ORDER_OVERRIDE)
1213 cpu->byte_order = byte_order;
1214
1215 cpu->pc = entrypoint;
1216
1217 switch (m->arch) {
1218
1219 case ARCH_ALPHA:
1220 /* For position-independent code: */
1221 cpu->cd.alpha.r[ALPHA_T12] = cpu->pc;
1222 break;
1223
1224 case ARCH_ARM:
1225 if (cpu->pc & 3) {
1226 fatal("ARM: lowest bits of pc set: TODO\n");
1227 exit(1);
1228 }
1229 cpu->pc &= 0xfffffffc;
1230 break;
1231
1232 case ARCH_AVR:
1233 cpu->pc &= 0xfffff;
1234 if (cpu->pc & 1) {
1235 fatal("AVR: lowest bit of pc set: TODO\n");
1236 exit(1);
1237 }
1238 break;
1239
1240 case ARCH_HPPA:
1241 break;
1242
1243 case ARCH_I960:
1244 break;
1245
1246 case ARCH_IA64:
1247 break;
1248
1249 case ARCH_M68K:
1250 break;
1251
1252 case ARCH_MIPS:
1253 if ((cpu->pc >> 32) == 0 && (cpu->pc & 0x80000000ULL))
1254 cpu->pc |= 0xffffffff00000000ULL;
1255
1256 cpu->cd.mips.gpr[MIPS_GPR_GP] = gp;
1257
1258 if ((cpu->cd.mips.gpr[MIPS_GPR_GP] >> 32) == 0 &&
1259 (cpu->cd.mips.gpr[MIPS_GPR_GP] & 0x80000000ULL))
1260 cpu->cd.mips.gpr[MIPS_GPR_GP] |=
1261 0xffffffff00000000ULL;
1262 break;
1263
1264 case ARCH_PPC:
1265 /* See http://www.linuxbase.org/spec/ELF/ppc64/
1266 spec/x458.html for more info. */
1267 cpu->cd.ppc.gpr[2] = toc;
1268 /* TODO */
1269 if (cpu->cd.ppc.bits == 32)
1270 cpu->pc &= 0xffffffffULL;
1271 break;
1272
1273 case ARCH_SH:
1274 if (cpu->cd.sh.cpu_type.bits == 32)
1275 cpu->pc &= 0xffffffffULL;
1276 cpu->pc &= ~1;
1277 break;
1278
1279 case ARCH_SPARC:
1280 break;
1281
1282 case ARCH_TRANSPUTER:
1283 cpu->pc &= 0xffffffffULL;
1284 break;
1285
1286 case ARCH_X86:
1287 /*
1288 * NOTE: The toc field is used to indicate an ELF32
1289 * or ELF64 load.
1290 */
1291 switch (toc) {
1292 case 0: /* 16-bit? TODO */
1293 cpu->pc &= 0xffffffffULL;
1294 break;
1295 case 1: /* 32-bit. */
1296 cpu->pc &= 0xffffffffULL;
1297 break;
1298 case 2: /* 64-bit: TODO */
1299 fatal("64-bit x86 load. TODO\n");
1300 exit(1);
1301 }
1302 break;
1303
1304 default:
1305 fatal("emul_machine_setup(): Internal error: "
1306 "Unimplemented arch %i\n", m->arch);
1307 exit(1);
1308 }
1309
1310 /*
1311 * For userland emulation, the remaining items
1312 * on the command line will be passed as parameters
1313 * to the emulated program, and will not be treated
1314 * as filenames to load into the emulator.
1315 * The program's name will be in load_names[0], and the
1316 * rest of the parameters in load_names[1] and up.
1317 */
1318 if (m->userland_emul != NULL)
1319 break;
1320
1321 n_load --;
1322 load_names ++;
1323 }
1324
1325 if (m->byte_order_override != NO_BYTE_ORDER_OVERRIDE)
1326 cpu->byte_order = m->byte_order_override;
1327
1328 /* Same byte order and entrypoint for all CPUs: */
1329 for (i=0; i<m->ncpus; i++)
1330 if (i != m->bootstrap_cpu) {
1331 m->cpus[i]->byte_order = cpu->byte_order;
1332 m->cpus[i]->pc = cpu->pc;
1333 }
1334
1335 if (m->userland_emul != NULL)
1336 useremul_setup(cpu, n_load, load_names);
1337
1338 /* Startup the bootstrap CPU: */
1339 cpu->running = 1;
1340
1341 /* ... or pause all CPUs, if start_paused is set: */
1342 if (m->start_paused) {
1343 for (i=0; i<m->ncpus; i++)
1344 m->cpus[i]->running = 0;
1345 }
1346
1347 /* Add PC dump points: */
1348 add_dump_points(m);
1349
1350 /* TODO: This is MIPS-specific! */
1351 if (m->machine_type == MACHINE_PMAX &&
1352 cpu->cd.mips.cpu_type.mmu_model == MMU3K)
1353 add_symbol_name(&m->symbol_context,
1354 0x9fff0000, 0x10000, "r2k3k_cache", 0, 0);
1355
1356 symbol_recalc_sizes(&m->symbol_context);
1357
1358 /* Special hack for ARC/SGI emulation: */
1359 if ((m->machine_type == MACHINE_ARC ||
1360 m->machine_type == MACHINE_SGI) && m->prom_emulation)
1361 add_arc_components(m);
1362
1363 debug("starting cpu%i at ", m->bootstrap_cpu);
1364 switch (m->arch) {
1365
1366 case ARCH_ARM:
1367 /* ARM cpus aren't 64-bit: */
1368 debug("0x%08x", (int)entrypoint);
1369 break;
1370
1371 case ARCH_AVR:
1372 /* Atmel AVR uses a 16-bit or 22-bit program counter: */
1373 debug("0x%04x", (int)entrypoint);
1374 break;
1375
1376 case ARCH_MIPS:
1377 if (cpu->is_32bit) {
1378 debug("0x%08x", (int)m->cpus[
1379 m->bootstrap_cpu]->pc);
1380 if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)
1381 debug(" (gp=0x%08x)", (int)m->cpus[
1382 m->bootstrap_cpu]->cd.mips.gpr[
1383 MIPS_GPR_GP]);
1384 } else {
1385 debug("0x%016llx", (long long)m->cpus[
1386 m->bootstrap_cpu]->pc);
1387 if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)
1388 debug(" (gp=0x%016llx)", (long long)
1389 cpu->cd.mips.gpr[MIPS_GPR_GP]);
1390 }
1391 break;
1392
1393 case ARCH_PPC:
1394 if (cpu->cd.ppc.bits == 32)
1395 debug("0x%08x", (int)entrypoint);
1396 else
1397 debug("0x%016llx", (long long)entrypoint);
1398 break;
1399
1400 case ARCH_X86:
1401 debug("0x%04x:0x%llx", cpu->cd.x86.s[X86_S_CS],
1402 (long long)cpu->pc);
1403 break;
1404
1405 default:
1406 if (cpu->is_32bit)
1407 debug("0x%08x", (int)cpu->pc);
1408 else
1409 debug("0x%016llx", (long long)cpu->pc);
1410 }
1411 debug("\n");
1412
1413 debug_indentation(-iadd);
1414 }
1415
1416
1417 /*
1418 * emul_dumpinfo():
1419 *
1420 * Dump info about all machines in an emul.
1421 */
1422 void emul_dumpinfo(struct emul *e)
1423 {
1424 int j, nm, iadd = DEBUG_INDENTATION;
1425
1426 if (e->net != NULL)
1427 net_dumpinfo(e->net);
1428
1429 nm = e->n_machines;
1430 for (j=0; j<nm; j++) {
1431 debug("machine %i: \"%s\"\n", j, e->machines[j]->name);
1432 debug_indentation(iadd);
1433 machine_dumpinfo(e->machines[j]);
1434 debug_indentation(-iadd);
1435 }
1436 }
1437
1438
1439 /*
1440 * emul_simple_init():
1441 *
1442 * For a normal setup:
1443 *
1444 * o) Initialize a network.
1445 * o) Initialize one machine.
1446 *
1447 * For a userland-only setup:
1448 *
1449 * o) Initialize a "pseudo"-machine.
1450 */
1451 void emul_simple_init(struct emul *emul)
1452 {
1453 int iadd = DEBUG_INDENTATION;
1454 struct machine *m;
1455
1456 if (emul->n_machines != 1) {
1457 fprintf(stderr, "emul_simple_init(): n_machines != 1\n");
1458 exit(1);
1459 }
1460
1461 m = emul->machines[0];
1462
1463 if (m->userland_emul == NULL) {
1464 debug("Simple setup...\n");
1465 debug_indentation(iadd);
1466
1467 /* Create a simple network: */
1468 emul->net = net_init(emul, NET_INIT_FLAG_GATEWAY,
1469 "10.0.0.0", 8, NULL, 0, 0);
1470 } else {
1471 /* Userland pseudo-machine: */
1472 debug("Syscall emulation (userland-only) setup...\n");
1473 debug_indentation(iadd);
1474 }
1475
1476 /* Create the machine: */
1477 emul_machine_setup(m, extra_argc, extra_argv, 0, NULL);
1478
1479 debug_indentation(-iadd);
1480 }
1481
1482
1483 /*
1484 * emul_create_from_configfile():
1485 *
1486 * Create an emul struct by reading settings from a configuration file.
1487 */
1488 struct emul *emul_create_from_configfile(char *fname)
1489 {
1490 int iadd = DEBUG_INDENTATION;
1491 struct emul *e = emul_new(fname);
1492
1493 debug("Creating emulation from configfile \"%s\":\n", fname);
1494 debug_indentation(iadd);
1495
1496 emul_parse_config(e, fname);
1497
1498 debug_indentation(-iadd);
1499 return e;
1500 }
1501
1502
1503 /*
1504 * emul_run():
1505 *
1506 * o) Set up things needed before running emulations.
1507 *
1508 * o) Run emulations (one or more, in parallel).
1509 *
1510 * o) De-initialize things.
1511 */
1512 void emul_run(struct emul **emuls, int n_emuls)
1513 {
1514 struct emul *e;
1515 int i = 0, j, go = 1, n, anything;
1516
1517 if (n_emuls < 1) {
1518 fprintf(stderr, "emul_run(): no thing to do\n");
1519 return;
1520 }
1521
1522 atexit(fix_console);
1523
1524 /* Initialize the interactive debugger: */
1525 debugger_init(emuls, n_emuls);
1526
1527 /* Run any additional debugger commands before starting: */
1528 for (i=0; i<n_emuls; i++) {
1529 struct emul *emul = emuls[i];
1530 if (emul->n_debugger_cmds > 0) {
1531 int j;
1532 if (i == 0)
1533 print_separator();
1534 for (j = 0; j < emul->n_debugger_cmds; j ++) {
1535 debug("> %s\n", emul->debugger_cmds[j]);
1536 debugger_execute_cmd(emul->debugger_cmds[j],
1537 strlen(emul->debugger_cmds[j]));
1538 }
1539 }
1540 }
1541
1542 print_separator();
1543 debug("\n");
1544
1545
1546 /*
1547 * console_init_main() makes sure that the terminal is in a
1548 * reasonable state.
1549 *
1550 * The SIGINT handler is for CTRL-C (enter the interactive debugger).
1551 *
1552 * The SIGCONT handler is invoked whenever the user presses CTRL-Z
1553 * (or sends SIGSTOP) and then continues. It makes sure that the
1554 * terminal is in an expected state.
1555 */
1556 console_init_main(emuls[0]); /* TODO: what is a good argument? */
1557 signal(SIGINT, debugger_activate);
1558 signal(SIGCONT, console_sigcont);
1559
1560 /* Not in verbose mode? Then set quiet_mode. */
1561 if (!verbose)
1562 quiet_mode = 1;
1563
1564 /* Initialize all CPUs in all machines in all emulations: */
1565 for (i=0; i<n_emuls; i++) {
1566 e = emuls[i];
1567 if (e == NULL)
1568 continue;
1569 for (j=0; j<e->n_machines; j++)
1570 cpu_run_init(e->machines[j]);
1571 }
1572
1573 /* TODO: Generalize: */
1574 if (emuls[0]->machines[0]->show_trace_tree)
1575 cpu_functioncall_trace(emuls[0]->machines[0]->cpus[0],
1576 emuls[0]->machines[0]->cpus[0]->pc);
1577
1578 /*
1579 * MAIN LOOP:
1580 *
1581 * Run all emulations in parallel, running each machine in
1582 * each emulation.
1583 */
1584 while (go) {
1585 go = 0;
1586
1587 /* Flush X11 and serial console output every now and then: */
1588 if (emuls[0]->machines[0]->ninstrs >
1589 emuls[0]->machines[0]->ninstrs_flush + (1<<19)) {
1590 x11_check_event(emuls, n_emuls);
1591 console_flush();
1592 emuls[0]->machines[0]->ninstrs_flush =
1593 emuls[0]->machines[0]->ninstrs;
1594 }
1595
1596 if (emuls[0]->machines[0]->ninstrs >
1597 emuls[0]->machines[0]->ninstrs_show + (1<<25)) {
1598 emuls[0]->machines[0]->ninstrs_since_gettimeofday +=
1599 (emuls[0]->machines[0]->ninstrs -
1600 emuls[0]->machines[0]->ninstrs_show);
1601 cpu_show_cycles(emuls[0]->machines[0], 0);
1602 emuls[0]->machines[0]->ninstrs_show =
1603 emuls[0]->machines[0]->ninstrs;
1604 }
1605
1606 if (single_step == ENTER_SINGLE_STEPPING) {
1607 /* TODO: Cleanup! */
1608 old_instruction_trace =
1609 emuls[0]->machines[0]->instruction_trace;
1610 old_quiet_mode = quiet_mode;
1611 old_show_trace_tree =
1612 emuls[0]->machines[0]->show_trace_tree;
1613 emuls[0]->machines[0]->instruction_trace = 1;
1614 emuls[0]->machines[0]->show_trace_tree = 1;
1615 quiet_mode = 0;
1616 single_step = SINGLE_STEPPING;
1617 }
1618
1619 if (single_step == SINGLE_STEPPING)
1620 debugger();
1621
1622 e = emuls[0]; /* Note: Only 1 emul supported now. */
1623
1624 for (j=0; j<e->n_machines; j++) {
1625 if (e->machines[j]->gdb.port > 0)
1626 debugger_gdb_check_incoming(e->machines[j]);
1627
1628 anything = machine_run(e->machines[j]);
1629 if (anything)
1630 go = 1;
1631 }
1632 }
1633
1634 /* Deinitialize all CPUs in all machines in all emulations: */
1635 for (i=0; i<n_emuls; i++) {
1636 e = emuls[i];
1637 if (e == NULL)
1638 continue;
1639 for (j=0; j<e->n_machines; j++)
1640 cpu_run_deinit(e->machines[j]);
1641 }
1642
1643 /* force_debugger_at_exit flag set? Then enter the debugger: */
1644 if (force_debugger_at_exit) {
1645 quiet_mode = 0;
1646 debugger_reset();
1647 debugger();
1648 }
1649
1650 /* Any machine using X11? Then we should wait before exiting: */
1651 n = 0;
1652 for (i=0; i<n_emuls; i++)
1653 for (j=0; j<emuls[i]->n_machines; j++)
1654 if (emuls[i]->machines[j]->use_x11)
1655 n++;
1656 if (n > 0) {
1657 printf("Press enter to quit.\n");
1658 while (!console_charavail(MAIN_CONSOLE)) {
1659 x11_check_event(emuls, n_emuls);
1660 usleep(1);
1661 }
1662 console_readchar(MAIN_CONSOLE);
1663 }
1664
1665 console_deinit();
1666 }
1667

  ViewVC Help
Powered by ViewVC 1.1.26