/[gxemul]/upstream/0.3.2/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 /upstream/0.3.2/src/emul.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (show annotations)
Mon Oct 8 16:18:06 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 24856 byte(s)
0.3.2
1 /*
2 * Copyright (C) 2003-2005 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.184 2005/04/20 04:43:52 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 "bintrans.h"
43 #include "cpu.h"
44 #include "emul.h"
45 #include "console.h"
46 #include "debugger.h"
47 #include "device.h"
48 #include "diskimage.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 force_debugger_at_exit;
59
60 extern int extra_argc;
61 extern char **extra_argv;
62
63 extern int verbose;
64 extern int quiet_mode;
65
66 extern struct emul *debugger_emul;
67 extern struct diskimage *diskimages[];
68
69
70 /*
71 * add_dump_points():
72 *
73 * Take the strings breakpoint_string[] and convert to addresses
74 * (and store them in breakpoint_addr[]).
75 *
76 * TODO: This function should be moved elsewhere.
77 */
78 static void add_dump_points(struct machine *m)
79 {
80 int i;
81 int string_flag;
82 uint64_t dp;
83
84 for (i=0; i<m->n_breakpoints; i++) {
85 string_flag = 0;
86 dp = strtoull(m->breakpoint_string[i], NULL, 0);
87
88 /*
89 * If conversion resulted in 0, then perhaps it is a
90 * symbol:
91 */
92 if (dp == 0) {
93 uint64_t addr;
94 int res = get_symbol_addr(&m->symbol_context,
95 m->breakpoint_string[i], &addr);
96 if (!res)
97 fprintf(stderr,
98 "WARNING! Breakpoint '%s' could not be"
99 " parsed\n",
100 m->breakpoint_string[i]);
101 else {
102 dp = addr;
103 string_flag = 1;
104 }
105 }
106
107 /*
108 * TODO: It would be nice if things like symbolname+0x1234
109 * were automatically converted into the correct address.
110 */
111
112 if ((dp >> 32) == 0 && ((dp >> 31) & 1))
113 dp |= 0xffffffff00000000ULL;
114 m->breakpoint_addr[i] = dp;
115
116 debug("breakpoint %i: 0x%016llx", i, (long long)dp);
117 if (string_flag)
118 debug(" (%s)", m->breakpoint_string[i]);
119 debug("\n");
120 }
121 }
122
123
124 /*
125 * fix_console():
126 */
127 static void fix_console(void)
128 {
129 console_deinit();
130 }
131
132
133 /*
134 * load_bootblock():
135 *
136 * For some emulation modes, it is possible to boot from a harddisk image by
137 * loading a bootblock from a specific disk offset into memory, and executing
138 * that, instead of requiring a separate kernel file. It is then up to the
139 * bootblock to load a kernel.
140 */
141 static void load_bootblock(struct machine *m, struct cpu *cpu)
142 {
143 int boot_disk_id;
144 unsigned char minibuf[0x20];
145 unsigned char *bootblock_buf;
146 uint64_t bootblock_offset;
147 uint64_t bootblock_loadaddr, bootblock_pc;
148 int n_blocks, res, readofs;
149
150 boot_disk_id = diskimage_bootdev(m);
151 if (boot_disk_id < 0)
152 return;
153
154 switch (m->machine_type) {
155 case MACHINE_DEC:
156 /*
157 * The first few bytes of a disk contains information about
158 * where the bootblock(s) are located. (These are all 32-bit
159 * little-endian words.)
160 *
161 * Offset 0x10 = load address
162 * 0x14 = initial PC value
163 * 0x18 = nr of 512-byte blocks to read
164 * 0x1c = offset on disk to where the bootblocks
165 * are (in 512-byte units)
166 * 0x20 = nr of blocks to read...
167 * 0x24 = offset...
168 *
169 * nr of blocks to read and offset are repeated until nr of
170 * blocks to read is zero.
171 */
172 res = diskimage_access(m, boot_disk_id, 0, 0,
173 minibuf, sizeof(minibuf));
174
175 bootblock_loadaddr = minibuf[0x10] + (minibuf[0x11] << 8)
176 + (minibuf[0x12] << 16) + (minibuf[0x13] << 24);
177
178 /* Convert loadaddr to uncached: */
179 if ((bootblock_loadaddr & 0xf0000000ULL) != 0x80000000 &&
180 (bootblock_loadaddr & 0xf0000000ULL) != 0xa0000000)
181 fatal("\nWARNING! Weird load address 0x%08x.\n\n",
182 (int)bootblock_loadaddr);
183 bootblock_loadaddr &= 0x0fffffffULL;
184 bootblock_loadaddr |= 0xffffffffa0000000ULL;
185
186 bootblock_pc = minibuf[0x14] + (minibuf[0x15] << 8)
187 + (minibuf[0x16] << 16) + (minibuf[0x17] << 24);
188
189 bootblock_pc &= 0x0fffffffULL;
190 bootblock_pc |= 0xffffffffa0000000ULL;
191 cpu->pc = bootblock_pc;
192
193 debug("DEC boot: loadaddr=0x%08x, pc=0x%08x",
194 (int)bootblock_loadaddr, (int)bootblock_pc);
195
196 readofs = 0x18;
197
198 for (;;) {
199 res = diskimage_access(m, boot_disk_id, 0, readofs,
200 minibuf, sizeof(minibuf));
201 if (!res) {
202 printf("couldn't read disk?\n");
203 exit(1);
204 }
205
206 n_blocks = minibuf[0] + (minibuf[1] << 8)
207 + (minibuf[2] << 16) + (minibuf[3] << 24);
208
209 bootblock_offset = (minibuf[4] + (minibuf[5] << 8)
210 + (minibuf[6] << 16) + (minibuf[7] << 24)) * 512;
211
212 if (n_blocks < 1)
213 break;
214
215 debug(readofs == 0x18? ": %i" : " + %i", n_blocks);
216
217 if (n_blocks * 512 > 65536)
218 fatal("\nWARNING! Unusually large bootblock "
219 "(%i bytes)\n\n", n_blocks * 512);
220
221 bootblock_buf = malloc(n_blocks * 512);
222 if (bootblock_buf == NULL) {
223 fprintf(stderr, "out of memory in "
224 "load_bootblock()\n");
225 exit(1);
226 }
227
228 res = diskimage_access(m, boot_disk_id, 0,
229 bootblock_offset, bootblock_buf, n_blocks * 512);
230 if (!res) {
231 fatal("WARNING: could not load bootblocks from"
232 " disk offset 0x%llx\n",
233 (long long)bootblock_offset);
234 }
235
236 store_buf(cpu, bootblock_loadaddr,
237 (char *)bootblock_buf, n_blocks * 512);
238
239 bootblock_loadaddr += 512*n_blocks;
240 free(bootblock_buf);
241 readofs += 8;
242 }
243
244 debug(readofs == 0x18? ": no blocks?\n" : " blocks\n");
245 break;
246
247 case MACHINE_X86:
248 cpu->cd.x86.mode = 16;
249 cpu->pc = 0x7c00;
250
251 bootblock_buf = malloc(512);
252 if (bootblock_buf == NULL) {
253 fprintf(stderr, "Out of memory.\n");
254 exit(1);
255 }
256
257 res = diskimage_access(m, boot_disk_id, 0, 0,
258 bootblock_buf, 512);
259 if (!res) {
260 printf("Couldn't read the disk image. Aborting.\n");
261 exit(1);
262 }
263
264 debug("loading PC bootsector from disk %i\n", boot_disk_id);
265 if (bootblock_buf[510] != 0x55 || bootblock_buf[511] != 0xaa)
266 debug("WARNING! The 0x55,0xAA marker is missing! "
267 "Booting anyway.\n");
268 store_buf(cpu, 0x7c00, (char *)bootblock_buf, 512);
269 free(bootblock_buf);
270 break;
271
272 default:
273 fatal("Booting from disk without a separate kernel "
274 "doesn't work in this emulation mode.\n");
275 exit(1);
276 }
277 }
278
279
280 /*
281 * emul_new():
282 *
283 * Returns a reasonably initialized struct emul.
284 */
285 struct emul *emul_new(char *name)
286 {
287 struct emul *e;
288 e = malloc(sizeof(struct emul));
289 if (e == NULL) {
290 fprintf(stderr, "out of memory in emul_new()\n");
291 exit(1);
292 }
293
294 memset(e, 0, sizeof(struct emul));
295
296 /* Sane default values: */
297 e->n_machines = 0;
298
299 if (name != NULL) {
300 e->name = strdup(name);
301 if (e->name == NULL) {
302 fprintf(stderr, "out of memory in emul_new()\n");
303 exit(1);
304 }
305 }
306
307 return e;
308 }
309
310
311 /*
312 * emul_add_machine():
313 *
314 * Calls machine_new(), adds the new machine into the emul struct, and
315 * returns a pointer to the new machine.
316 *
317 * This function should be used instead of manually calling machine_new().
318 */
319 struct machine *emul_add_machine(struct emul *e, char *name)
320 {
321 struct machine *m;
322
323 m = machine_new(name, e);
324 m->serial_nr = (e->next_serial_nr ++);
325
326 e->n_machines ++;
327 e->machines = realloc(e->machines,
328 sizeof(struct machine *) * e->n_machines);
329 if (e->machines == NULL) {
330 fprintf(stderr, "emul_add_machine(): out of memory\n");
331 exit(1);
332 }
333
334 e->machines[e->n_machines - 1] = m;
335 return m;
336 }
337
338
339 /*
340 * add_arc_components():
341 *
342 * This function adds ARCBIOS memory descriptors for the loaded program,
343 * and ARCBIOS components for SCSI devices.
344 */
345 static void add_arc_components(struct machine *m)
346 {
347 struct cpu *cpu = m->cpus[m->bootstrap_cpu];
348 uint64_t start = cpu->pc & 0x1fffffff;
349 uint64_t len = 0xc00000 - start;
350 struct diskimage *d;
351 uint64_t scsicontroller, scsidevice, scsidisk;
352
353 if ((cpu->pc >> 60) != 0xf) {
354 start = cpu->pc & 0xffffffffffULL;
355 len = 0xc00000 - start;
356 }
357
358 len += 1048576 * m->memory_offset_in_mb;
359
360 /* NOTE/TODO: magic 12MB end of load program area */
361 arcbios_add_memory_descriptor(cpu,
362 0x60000 + m->memory_offset_in_mb * 1048576,
363 start-0x60000 - m->memory_offset_in_mb * 1048576,
364 ARCBIOS_MEM_FreeMemory);
365 arcbios_add_memory_descriptor(cpu,
366 start, len, ARCBIOS_MEM_LoadedProgram);
367
368 scsicontroller = arcbios_get_scsicontroller();
369 if (scsicontroller == 0)
370 return;
371
372 /* TODO: The device 'name' should defined be somewhere else. */
373
374 d = m->first_diskimage;
375 while (d != NULL) {
376 if (d->type == DISKIMAGE_SCSI) {
377 int a, b, flags = COMPONENT_FLAG_Input;
378 char component_string[100];
379 char *name = "DEC RZ58 (C) DEC2000";
380
381 /* Read-write, or read-only? */
382 if (d->writable)
383 flags |= COMPONENT_FLAG_Output;
384 else
385 flags |= COMPONENT_FLAG_ReadOnly;
386
387 a = COMPONENT_TYPE_DiskController;
388 b = COMPONENT_TYPE_DiskPeripheral;
389
390 if (d->is_a_cdrom) {
391 flags |= COMPONENT_FLAG_Removable;
392 a = COMPONENT_TYPE_CDROMController;
393 b = COMPONENT_TYPE_FloppyDiskPeripheral;
394 name = "NEC CD-ROM CDR-210P 1.0 ";
395 }
396
397 scsidevice = arcbios_addchild_manual(cpu,
398 COMPONENT_CLASS_ControllerClass,
399 a, flags, 1, 2, d->id, 0xffffffff,
400 name, scsicontroller, NULL, 0);
401
402 scsidisk = arcbios_addchild_manual(cpu,
403 COMPONENT_CLASS_PeripheralClass,
404 b, flags, 1, 2, 0, 0xffffffff, NULL,
405 scsidevice, NULL, 0);
406
407 /*
408 * Add device string to component address mappings:
409 * "scsi(0)disk(0)rdisk(0)partition(0)"
410 */
411
412 if (d->is_a_cdrom) {
413 snprintf(component_string,
414 sizeof(component_string),
415 "scsi(0)cdrom(%i)", d->id);
416 arcbios_add_string_to_component(
417 component_string, scsidevice);
418
419 snprintf(component_string,
420 sizeof(component_string),
421 "scsi(0)cdrom(%i)fdisk(0)", d->id);
422 arcbios_add_string_to_component(
423 component_string, scsidisk);
424 } else {
425 snprintf(component_string,
426 sizeof(component_string),
427 "scsi(0)disk(%i)", d->id);
428 arcbios_add_string_to_component(
429 component_string, scsidevice);
430
431 snprintf(component_string,
432 sizeof(component_string),
433 "scsi(0)disk(%i)rdisk(0)", d->id);
434 arcbios_add_string_to_component(
435 component_string, scsidisk);
436 }
437 }
438
439 d = d->next;
440 }
441 }
442
443
444 /*
445 * emul_machine_setup():
446 *
447 * o) Initialize the hardware (RAM, devices, CPUs, ...) which
448 * will be emulated in this machine.
449 *
450 * o) Load ROM code and/or other programs into emulated memory.
451 *
452 * o) Special hacks needed after programs have been loaded.
453 */
454 void emul_machine_setup(struct machine *m, int n_load, char **load_names,
455 int n_devices, char **device_names)
456 {
457 struct emul *emul;
458 struct cpu *cpu;
459 int i, iadd=4;
460 uint64_t addr, memory_amount, entrypoint = 0, gp = 0, toc = 0;
461 int byte_order;
462
463 emul = m->emul;
464
465 debug("machine \"%s\":\n", m->name);
466 debug_indentation(iadd);
467
468 /* For userland-only, this decides which ARCH/cpu_name to use: */
469 if (m->machine_type == MACHINE_USERLAND && m->userland_emul != NULL) {
470 useremul_name_to_useremul(NULL, m->userland_emul,
471 &m->arch, &m->machine_name, &m->cpu_name);
472 if (m->arch == ARCH_NOARCH) {
473 printf("Unsupported userland emulation mode.\n");
474 exit(1);
475 }
476 }
477
478 if (m->machine_type == MACHINE_NONE) {
479 fatal("No machine type specified?\n");
480 exit(1);
481 }
482
483 m->cpu_family = cpu_family_ptr_by_number(m->arch);
484
485 machine_memsize_fix(m);
486
487 /*
488 * Create the system's memory:
489 *
490 * (Don't print the amount for userland-only emulation; the
491 * size doesn't matter.)
492 */
493 if (m->machine_type != MACHINE_USERLAND)
494 debug("memory: %i MB", m->physical_ram_in_mb);
495 memory_amount = (uint64_t)m->physical_ram_in_mb * 1048576;
496 if (m->memory_offset_in_mb > 0) {
497 /*
498 * A special hack is used for some SGI models,
499 * where memory is offset by 128MB to leave room for
500 * EISA space and other things.
501 */
502 debug(" (offset by %iMB)", m->memory_offset_in_mb);
503 memory_amount += 1048576 * m->memory_offset_in_mb;
504 }
505 m->memory = memory_new(memory_amount);
506 if (m->machine_type != MACHINE_USERLAND)
507 debug("\n");
508
509 /* Create CPUs: */
510 if (m->cpu_name == NULL)
511 machine_default_cputype(m);
512 if (m->ncpus == 0) {
513 /* TODO: This should be moved elsewhere... */
514 if (m->machine_type == MACHINE_BEBOX)
515 m->ncpus = 2;
516 else if (m->machine_type == MACHINE_ARC &&
517 m->machine_subtype == MACHINE_ARC_NEC_R96)
518 m->ncpus = 2;
519 else if (m->machine_type == MACHINE_ARC &&
520 m->machine_subtype == MACHINE_ARC_NEC_R98)
521 m->ncpus = 4;
522 else
523 m->ncpus = 1;
524 }
525 m->cpus = malloc(sizeof(struct cpu *) * m->ncpus);
526 if (m->cpus == NULL) {
527 fprintf(stderr, "out of memory\n");
528 exit(1);
529 }
530 memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);
531
532 /* Initialize dynamic binary translation, if available: */
533 if (m->bintrans_enable)
534 bintrans_init(m, m->memory);
535
536 debug("cpu0");
537 if (m->ncpus > 1)
538 debug(" .. cpu%i", m->ncpus - 1);
539 debug(": ");
540 for (i=0; i<m->ncpus; i++) {
541 m->cpus[i] = cpu_new(m->memory, m, i, m->cpu_name);
542 if (m->bintrans_enable)
543 bintrans_init_cpu(m->cpus[i]);
544 }
545 debug("\n");
546
547 if (m->use_random_bootstrap_cpu)
548 m->bootstrap_cpu = random() % m->ncpus;
549 else
550 m->bootstrap_cpu = 0;
551
552 cpu = m->cpus[m->bootstrap_cpu];
553
554 /* Set cpu->useremul_syscall, and use userland_memory_rw: */
555 if (m->userland_emul != NULL) {
556 useremul_name_to_useremul(cpu,
557 m->userland_emul, NULL, NULL, NULL);
558 cpu->memory_rw = userland_memory_rw;
559 }
560
561 if (m->use_x11)
562 x11_init(m);
563
564 /* Fill memory with random bytes: */
565 /* TODO: This is MIPS-specific! */
566 if (m->random_mem_contents) {
567 for (i=0; i<m->physical_ram_in_mb * 1048576; i+=256) {
568 unsigned char data[256];
569 unsigned int j;
570 for (j=0; j<sizeof(data); j++)
571 data[j] = random() & 255;
572 addr = 0xffffffff80000000ULL + i;
573 cpu->memory_rw(cpu, m->memory, addr, data, sizeof(data),
574 MEM_WRITE, CACHE_NONE | NO_EXCEPTIONS);
575 }
576 }
577
578 if ((m->machine_type == MACHINE_ARC ||
579 m->machine_type == MACHINE_SGI) && m->prom_emulation)
580 arcbios_init();
581
582 if (m->userland_emul != NULL) {
583 /*
584 * For userland-only emulation, no machine emulation
585 * is needed.
586 */
587 } else {
588 for (i=0; i<n_devices; i++)
589 device_add(m, device_names[i]);
590
591 machine_setup(m);
592 }
593
594 diskimage_dump_info(m);
595
596 /* Load files (ROM code, boot code, ...) into memory: */
597 if (n_load == 0) {
598 if (m->first_diskimage != NULL)
599 load_bootblock(m, cpu);
600 else {
601 fprintf(stderr, "No executable file(s) loaded, and "
602 "we are not booting directly from a disk image."
603 "\nAborting.\n");
604 exit(1);
605 }
606 }
607
608 while (n_load > 0) {
609 byte_order = NO_BYTE_ORDER_OVERRIDE;
610
611 file_load(m, m->memory, *load_names, &entrypoint,
612 m->arch, &gp, &byte_order, &toc);
613
614 if (byte_order != NO_BYTE_ORDER_OVERRIDE)
615 cpu->byte_order = byte_order;
616
617 cpu->pc = entrypoint;
618
619 switch (m->arch) {
620 case ARCH_MIPS:
621 if ((cpu->pc >> 32) == 0
622 && (cpu->pc & 0x80000000ULL))
623 cpu->pc |= 0xffffffff00000000ULL;
624
625 cpu->cd.mips.gpr[MIPS_GPR_GP] = gp;
626
627 if ((cpu->cd.mips.gpr[MIPS_GPR_GP] >> 32) == 0 &&
628 (cpu->cd.mips.gpr[MIPS_GPR_GP] & 0x80000000ULL))
629 cpu->cd.mips.gpr[MIPS_GPR_GP] |=
630 0xffffffff00000000ULL;
631 break;
632
633 case ARCH_PPC:
634 cpu->cd.ppc.gpr[2] = toc;
635 break;
636
637 case ARCH_ALPHA:
638 case ARCH_HPPA:
639 case ARCH_SPARC:
640 case ARCH_URISC:
641 break;
642
643 case ARCH_X86:
644 /*
645 * NOTE: The toc field is used to indicate an ELF64
646 * load, on AMD64!
647 */
648 if (toc != 0) {
649 cpu->cd.x86.mode = 64;
650 } else
651 cpu->pc &= 0xffffffffULL;
652 break;
653
654 default:
655 fatal("emul_machine_setup(): Internal error: "
656 "Unimplemented arch %i\n", m->arch);
657 exit(1);
658 }
659
660 /*
661 * For userland emulation, the remaining items
662 * on the command line will be passed as parameters
663 * to the emulated program, and will not be treated
664 * as filenames to load into the emulator.
665 * The program's name will be in load_names[0], and the
666 * rest of the parameters in load_names[1] and up.
667 */
668 if (m->userland_emul != NULL)
669 break;
670
671 n_load --;
672 load_names ++;
673 }
674
675 if (m->byte_order_override != NO_BYTE_ORDER_OVERRIDE)
676 cpu->byte_order = m->byte_order_override;
677
678 /* Same byte order and entrypoint for all CPUs: */
679 for (i=0; i<m->ncpus; i++)
680 if (i != m->bootstrap_cpu) {
681 m->cpus[i]->byte_order = cpu->byte_order;
682 m->cpus[i]->pc = cpu->pc;
683 }
684
685 if (m->userland_emul != NULL)
686 useremul_setup(cpu, n_load, load_names);
687
688 /* Startup the bootstrap CPU: */
689 cpu->bootstrap_cpu_flag = 1;
690 cpu->running = 1;
691
692 /* ... or pause all CPUs, if start_paused is set: */
693 if (m->start_paused) {
694 for (i=0; i<m->ncpus; i++)
695 m->cpus[i]->running = 0;
696 }
697
698 /* Add PC dump points: */
699 add_dump_points(m);
700
701 /* TODO: This is MIPS-specific! */
702 if (m->machine_type == MACHINE_DEC &&
703 cpu->cd.mips.cpu_type.mmu_model == MMU3K)
704 add_symbol_name(&m->symbol_context,
705 0x9fff0000, 0x10000, "r2k3k_cache", 0);
706
707 symbol_recalc_sizes(&m->symbol_context);
708
709 if (m->max_random_cycles_per_chunk > 0)
710 debug("using random cycle chunks (1 to %i cycles)\n",
711 m->max_random_cycles_per_chunk);
712
713 /* Special hack for ARC/SGI emulation: */
714 if ((m->machine_type == MACHINE_ARC ||
715 m->machine_type == MACHINE_SGI) && m->prom_emulation)
716 add_arc_components(m);
717
718 debug("starting cpu%i at ", m->bootstrap_cpu);
719 switch (m->arch) {
720 case ARCH_MIPS:
721 if (cpu->cd.mips.cpu_type.isa_level < 3 ||
722 cpu->cd.mips.cpu_type.isa_level == 32) {
723 debug("0x%08x", (int)m->cpus[
724 m->bootstrap_cpu]->pc);
725 if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)
726 debug(" (gp=0x%08x)", (int)m->cpus[
727 m->bootstrap_cpu]->cd.mips.gpr[
728 MIPS_GPR_GP]);
729 } else {
730 debug("0x%016llx", (long long)m->cpus[
731 m->bootstrap_cpu]->pc);
732 if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)
733 debug(" (gp=0x%016llx)", (long long)
734 cpu->cd.mips.gpr[MIPS_GPR_GP]);
735 }
736 break;
737 case ARCH_PPC:
738 if (cpu->cd.ppc.bits == 32)
739 debug("0x%08x", (int)entrypoint);
740 else
741 debug("0x%016llx", (long long)entrypoint);
742 break;
743 case ARCH_URISC:
744 {
745 char tmps[100];
746 unsigned char buf[sizeof(uint64_t)];
747
748 cpu->memory_rw(cpu, m->memory, 0, buf, sizeof(buf),
749 MEM_READ, CACHE_NONE | NO_EXCEPTIONS);
750
751 entrypoint = 0;
752 for (i=0; i<cpu->cd.urisc.wordlen/8; i++) {
753 entrypoint <<= 8;
754 if (cpu->byte_order == EMUL_BIG_ENDIAN)
755 entrypoint += buf[i];
756 else
757 entrypoint += buf[cpu->
758 cd.urisc.wordlen/8 - 1 - i];
759 }
760
761 sprintf(tmps, "0x%%0%illx", cpu->cd.urisc.wordlen / 4);
762 debug(tmps, (long long)entrypoint);
763 cpu->pc = entrypoint;
764 }
765 break;
766 case ARCH_X86:
767 if (cpu->cd.x86.mode == 16)
768 debug("0x%04x:0x%04x", cpu->cd.x86.s[X86_S_CS],
769 (int)cpu->pc);
770 else if (cpu->cd.x86.mode == 32)
771 debug("0x%08x", (int)cpu->pc);
772 else
773 debug("0x%016llx", (long long)cpu->pc);
774 break;
775 default:
776 debug("0x%016llx", (long long)cpu->pc);
777 }
778 debug("\n");
779
780 debug_indentation(-iadd);
781 }
782
783
784 /*
785 * emul_dumpinfo():
786 *
787 * Dump info about all machines in an emul.
788 */
789 void emul_dumpinfo(struct emul *e)
790 {
791 int j, nm, iadd = 4;
792
793 if (e->net != NULL)
794 net_dumpinfo(e->net);
795
796 nm = e->n_machines;
797 for (j=0; j<nm; j++) {
798 debug("machine %i: \"%s\"\n", j, e->machines[j]->name);
799 debug_indentation(iadd);
800 machine_dumpinfo(e->machines[j]);
801 debug_indentation(-iadd);
802 }
803 }
804
805
806 /*
807 * emul_simple_init():
808 *
809 * For a normal setup:
810 *
811 * o) Initialize a network.
812 * o) Initialize one machine.
813 *
814 * For a userland-only setup:
815 *
816 * o) Initialize a "pseudo"-machine.
817 */
818 void emul_simple_init(struct emul *emul)
819 {
820 int iadd=4;
821 struct machine *m;
822
823 if (emul->n_machines != 1) {
824 fprintf(stderr, "emul_simple_init(): n_machines != 1\n");
825 exit(1);
826 }
827
828 m = emul->machines[0];
829
830 if (m->userland_emul == NULL) {
831 debug("Simple setup...\n");
832 debug_indentation(iadd);
833
834 /* Create a network: */
835 emul->net = net_init(emul, NET_INIT_FLAG_GATEWAY,
836 "10.0.0.0", 8);
837 } else {
838 /* Userland pseudo-machine: */
839 debug("Syscall emulation (userland-only) setup...\n");
840 debug_indentation(iadd);
841 }
842
843 /* Create the machine: */
844 emul_machine_setup(m, extra_argc, extra_argv, 0, NULL);
845
846 debug_indentation(-iadd);
847 }
848
849
850 /*
851 * emul_create_from_configfile():
852 *
853 * Create an emul struct by reading settings from a configuration file.
854 */
855 struct emul *emul_create_from_configfile(char *fname)
856 {
857 int iadd = 4;
858 struct emul *e = emul_new(fname);
859 FILE *f;
860 char buf[128];
861 size_t len;
862
863 debug("Creating emulation from configfile \"%s\":\n", fname);
864 debug_indentation(iadd);
865
866 f = fopen(fname, "r");
867 if (f == NULL) {
868 perror(fname);
869 exit(1);
870 }
871
872 /* Read header: (must be !!gxemul) */
873 len = fread(buf, 1, 8, f);
874 if (len != 8 || strncmp(buf, "!!gxemul", 8) != 0) {
875 fprintf(stderr, "%s: must start with '!!gxemul'\n", fname);
876 exit(1);
877 }
878
879 /* Restart from beginning: */
880 rewind(f);
881
882 emul_parse_config(e, f);
883
884 fclose(f);
885 debug_indentation(-iadd);
886 return e;
887 }
888
889
890 /*
891 * emul_run():
892 *
893 * o) Set up things needed before running emulations.
894 *
895 * o) Run emulations (one or more, in parallel).
896 *
897 * o) De-initialize things.
898 */
899 void emul_run(struct emul **emuls, int n_emuls)
900 {
901 struct emul *e;
902 int i = 0, j, go = 1, n, anything;
903
904 if (n_emuls < 1) {
905 fprintf(stderr, "emul_run(): no thing to do\n");
906 return;
907 }
908
909 atexit(fix_console);
910
911 i = 79;
912 while (i-- > 0)
913 debug("-");
914 debug("\n\n");
915
916 /* Initialize the interactive debugger: */
917 debugger_init(emuls, n_emuls);
918
919 /*
920 * console_init_main() makes sure that the terminal is in a
921 * reasonable state.
922 *
923 * The SIGINT handler is for CTRL-C (enter the interactive debugger).
924 *
925 * The SIGCONT handler is invoked whenever the user presses CTRL-Z
926 * (or sends SIGSTOP) and then continues. It makes sure that the
927 * terminal is in an expected state.
928 */
929 console_init_main(emuls[0]); /* TODO: what is a good argument? */
930 signal(SIGINT, debugger_activate);
931 signal(SIGCONT, console_sigcont);
932
933 /* Not in verbose mode? Then set quiet_mode. */
934 if (!verbose)
935 quiet_mode = 1;
936
937 /* Initialize all CPUs in all machines in all emulations: */
938 for (i=0; i<n_emuls; i++) {
939 e = emuls[i];
940 if (e == NULL)
941 continue;
942 for (j=0; j<e->n_machines; j++)
943 cpu_run_init(e, e->machines[j]);
944 }
945
946 /*
947 * MAIN LOOP:
948 *
949 * Run all emulations in parallel, running each machine in
950 * each emulation.
951 */
952 while (go) {
953 go = 0;
954
955 x11_check_event(emuls, n_emuls);
956
957 for (i=0; i<n_emuls; i++) {
958 e = emuls[i];
959 if (e == NULL)
960 continue;
961
962 for (j=0; j<e->n_machines; j++) {
963 /* TODO: cpu_run() is a strange name, since
964 there can be multiple cpus in a machine */
965 anything = cpu_run(e, e->machines[j]);
966 if (anything)
967 go = 1;
968 }
969 }
970 }
971
972 /* Deinitialize all CPUs in all machines in all emulations: */
973 for (i=0; i<n_emuls; i++) {
974 e = emuls[i];
975 if (e == NULL)
976 continue;
977 for (j=0; j<e->n_machines; j++)
978 cpu_run_deinit(e, e->machines[j]);
979 }
980
981 /* force_debugger_at_exit flag set? Then enter the debugger: */
982 if (force_debugger_at_exit) {
983 quiet_mode = 0;
984 debugger_reset();
985 debugger();
986 }
987
988 /* Any machine using X11? Then we should wait before exiting: */
989 n = 0;
990 for (i=0; i<n_emuls; i++)
991 for (j=0; j<emuls[i]->n_machines; j++)
992 if (emuls[i]->machines[j]->use_x11)
993 n++;
994 if (n > 0) {
995 printf("Press enter to quit.\n");
996 while (!console_charavail(MAIN_CONSOLE)) {
997 x11_check_event(emuls, n_emuls);
998 usleep(1);
999 }
1000 console_readchar(MAIN_CONSOLE);
1001 }
1002
1003 console_deinit();
1004 }
1005

  ViewVC Help
Powered by ViewVC 1.1.26