emul.cc Source File

Back to the index.

emul.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003-2018 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  * LEGACY emulation startup and misc. routines.
29  */
30 
31 #include <signal.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <limits.h>
35 #include <stdarg.h>
36 #include <string.h>
37 #include <unistd.h>
38 
39 #include "arcbios.h"
40 #include "cpu.h"
41 #include "emul.h"
42 #include "console.h"
43 #include "debugger.h"
44 #include "device.h"
45 #include "diskimage.h"
46 #include "machine.h"
47 #include "memory.h"
48 #include "mips_cpu_types.h"
49 #include "misc.h"
50 #include "net.h"
51 #include "settings.h"
52 #include "timer.h"
53 #include "x11.h"
54 
55 #include "thirdparty/exec_elf.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 
71 /*
72  * add_breakpoints():
73  *
74  * Take the strings breakpoint_string[] and convert to addresses
75  * (and store them in breakpoint_addr[]).
76  *
77  * TODO: This function should be moved elsewhere.
78  */
79 static void add_breakpoints(struct machine *m)
80 {
81  int i;
82  int string_flag;
83  uint64_t dp;
84 
85  for (i=0; i<m->breakpoints.n; i++) {
86  string_flag = 0;
87  dp = strtoull(m->breakpoints.string[i], NULL, 0);
88 
89  /*
90  * If conversion resulted in 0, then perhaps it is a
91  * symbol:
92  */
93  if (dp == 0) {
94  uint64_t addr;
95  int res = get_symbol_addr(&m->symbol_context,
96  m->breakpoints.string[i], &addr);
97  if (!res) {
98  fprintf(stderr,
99  "ERROR! Breakpoint '%s' could not be"
100  " parsed\n",
101  m->breakpoints.string[i]);
102  exit(1);
103  } else {
104  dp = addr;
105  string_flag = 1;
106  }
107  }
108 
109  /*
110  * TODO: It would be nice if things like symbolname+0x1234
111  * were automatically converted into the correct address.
112  */
113 
114  if (m->arch == ARCH_MIPS) {
115  if ((dp >> 32) == 0 && ((dp >> 31) & 1))
116  dp |= 0xffffffff00000000ULL;
117  }
118 
119  m->breakpoints.addr[i] = dp;
120 
121  debug("breakpoint %i: 0x%" PRIx64, i, dp);
122  if (string_flag)
123  debug(" (%s)", m->breakpoints.string[i]);
124  debug("\n");
125  }
126 }
127 
128 
129 /*
130  * fix_console():
131  */
132 static void fix_console(void)
133 {
135 }
136 
137 
138 /*
139  * emul_new():
140  *
141  * Returns a reasonably initialized struct emul.
142  */
143 struct emul *emul_new(char *name)
144 {
145  struct emul *e;
146 
147  CHECK_ALLOCATION(e = (struct emul *) malloc(sizeof(struct emul)));
148  memset(e, 0, sizeof(struct emul));
149 
150  e->settings = settings_new();
151 
152  settings_add(e->settings, "n_machines", 0,
154  (void *) &e->n_machines);
155 
156  /* TODO: More settings? */
157 
158  /* Sane default values: */
159  e->n_machines = 0;
160  e->next_serial_nr = 1;
161 
162  if (name != NULL) {
163  CHECK_ALLOCATION(e->name = strdup(name));
164  settings_add(e->settings, "name", 0,
166  (void *) &e->name);
167  }
168 
169  return e;
170 }
171 
172 
173 /*
174  * emul_destroy():
175  *
176  * Destroys a previously created emul object.
177  */
178 void emul_destroy(struct emul *emul)
179 {
180  int i;
181 
182  if (emul->name != NULL) {
183  settings_remove(emul->settings, "name");
184  free(emul->name);
185  }
186 
187  for (i=0; i<emul->n_machines; i++)
189 
190  if (emul->machines != NULL)
191  free(emul->machines);
192 
193  /* Remove any remaining level-1 settings: */
196 
197  free(emul);
198 }
199 
200 
201 /*
202  * emul_add_machine():
203  *
204  * Calls machine_new(), adds the new machine into the emul struct, and
205  * returns a pointer to the new machine.
206  *
207  * This function should be used instead of manually calling machine_new().
208  */
209 struct machine *emul_add_machine(struct emul *e, char *name)
210 {
211  struct machine *m;
212  char tmpstr[20];
213  int i;
214 
215  m = machine_new(name, e, e->n_machines);
216  m->serial_nr = (e->next_serial_nr ++);
217 
218  i = e->n_machines ++;
219 
220  CHECK_ALLOCATION(e->machines = (struct machine **) realloc(e->machines,
221  sizeof(struct machine *) * e->n_machines));
222 
223  e->machines[i] = m;
224 
225  snprintf(tmpstr, sizeof(tmpstr), "machine[%i]", i);
227  e->machines[i]->settings);
228 
229  return m;
230 }
231 
232 
233 /*
234  * add_arc_components():
235  *
236  * This function adds ARCBIOS memory descriptors for the loaded program,
237  * and ARCBIOS components for SCSI devices.
238  */
239 static void add_arc_components(struct machine *m)
240 {
241  struct cpu *cpu = m->cpus[m->bootstrap_cpu];
242  uint64_t start = cpu->pc & 0x1fffffff;
243  uint64_t len = 0xc00000 - start;
244  struct diskimage *d;
245  uint64_t scsicontroller, scsidevice, scsidisk;
246 
247  if ((cpu->pc >> 60) != 0xf) {
248  start = cpu->pc & 0xffffffffffULL;
249  len = 0xc00000 - start;
250  }
251 
252  len += 1048576 * m->memory_offset_in_mb;
253 
254  /*
255  * NOTE/TODO: magic 12MB end of load program area
256  *
257  * Hm. This breaks the old FreeBSD/MIPS snapshots...
258  */
259 #if 0
261  0x60000 + m->memory_offset_in_mb * 1048576,
262  start-0x60000 - m->memory_offset_in_mb * 1048576,
264 #endif
266  start, len, ARCBIOS_MEM_LoadedProgram);
267 
268  scsicontroller = arcbios_get_scsicontroller(m);
269  if (scsicontroller == 0)
270  return;
271 
272  /* TODO: The device 'name' should defined be somewhere else. */
273 
274  d = m->first_diskimage;
275  while (d != NULL) {
276  if (d->type == DISKIMAGE_SCSI) {
277  int a, b, flags = COMPONENT_FLAG_Input;
278  char component_string[100];
279  const char *name = "DEC RZ58 (C) DEC2000";
280 
281  /* Read-write, or read-only? */
282  if (d->writable)
283  flags |= COMPONENT_FLAG_Output;
284  else
285  flags |= COMPONENT_FLAG_ReadOnly;
286 
289 
290  if (d->is_a_cdrom) {
291  flags |= COMPONENT_FLAG_Removable;
294  name = "NEC CD-ROM CDR-210P 1.0 ";
295  }
296 
297  scsidevice = arcbios_addchild_manual(cpu,
299  a, flags, 1, 2, d->id, 0xffffffff,
300  name, scsicontroller, NULL, 0);
301 
302  scsidisk = arcbios_addchild_manual(cpu,
304  b, flags, 1, 2, 0, 0xffffffff, NULL,
305  scsidevice, NULL, 0);
306 
307  /*
308  * Add device string to component address mappings:
309  * "scsi(0)disk(0)rdisk(0)partition(0)"
310  */
311 
312  if (d->is_a_cdrom) {
313  snprintf(component_string,
314  sizeof(component_string),
315  "scsi(0)cdrom(%i)", d->id);
317  component_string, scsidevice);
318 
319  snprintf(component_string,
320  sizeof(component_string),
321  "scsi(0)cdrom(%i)fdisk(0)", d->id);
323  component_string, scsidisk);
324  } else {
325  snprintf(component_string,
326  sizeof(component_string),
327  "scsi(0)disk(%i)", d->id);
329  component_string, scsidevice);
330 
331  snprintf(component_string,
332  sizeof(component_string),
333  "scsi(0)disk(%i)rdisk(0)", d->id);
335  component_string, scsidisk);
336  }
337  }
338 
339  d = d->next;
340  }
341 }
342 
343 
344 /*
345  * emul_machine_setup():
346  *
347  * o) Initialize the hardware (RAM, devices, CPUs, ...) which
348  * will be emulated in this machine.
349  *
350  * o) Load ROM code and/or other programs into emulated memory.
351  *
352  * o) Special hacks needed after programs have been loaded.
353  */
354 void emul_machine_setup(struct machine *m, int n_load, char **load_names,
355  int n_devices, char **device_names)
356 {
357  struct cpu *cpu;
358  int i, iadd = DEBUG_INDENTATION;
359  uint64_t memory_amount, entrypoint = 0, gp = 0, toc = 0;
360  int byte_order;
361 
362  if (m->name != NULL)
363  debug("machine \"%s\":\n", m->name);
364  else
365  debug("machine:\n");
366 
367  debug_indentation(iadd);
368 
369  if (m->machine_type == MACHINE_NONE) {
370  fatal("No machine type specified?\n");
371  exit(1);
372  }
373 
375 
376  if (m->arch == ARCH_ALPHA)
377  m->arch_pagesize = 8192;
378 
380 
381  /*
382  * Create the system's memory:
383  */
384  debug("memory: %i MB", m->physical_ram_in_mb);
385  memory_amount = (uint64_t)m->physical_ram_in_mb * 1048576;
386  if (m->memory_offset_in_mb > 0) {
387  /*
388  * A special hack is used for some SGI models,
389  * where memory is offset by 128MB to leave room for
390  * EISA space and other things.
391  */
392  debug(" (offset by %iMB)", m->memory_offset_in_mb);
393  memory_amount += 1048576 * m->memory_offset_in_mb;
394  }
395  if (m->machine_type == MACHINE_SGI && m->machine_subtype == 32) {
396  if (memory_amount > 0x10000000) {
397  memory_amount = 0x10000000;
398  debug(" (SGI O2 hack: %i MB at offset 0)", 0x10000000 / 1048576);
399  }
400  }
401  m->memory = memory_new(memory_amount, m->arch);
402  debug("\n");
403 
404  /* Create CPUs: */
405  if (m->cpu_name == NULL)
407  if (m->ncpus == 0)
408  m->ncpus = 1;
409 
410  CHECK_ALLOCATION(m->cpus = (struct cpu **) malloc(sizeof(struct cpu *) * m->ncpus));
411  memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);
412 
413  debug("cpu0");
414  if (m->ncpus > 1)
415  debug(" .. cpu%i", m->ncpus - 1);
416  debug(": ");
417  for (i=0; i<m->ncpus; i++) {
418  m->cpus[i] = cpu_new(m->memory, m, i, m->cpu_name);
419  if (m->cpus[i] == NULL) {
420  fprintf(stderr, "Unable to create CPU object. "
421  "Aborting.");
422  exit(1);
423  }
424  }
425  debug("\n");
426 
428  m->bootstrap_cpu = random() % m->ncpus;
429  else
430  m->bootstrap_cpu = 0;
431 
432  cpu = m->cpus[m->bootstrap_cpu];
433 
434  if (m->x11_md.in_use)
435  x11_init(m);
436 
437  /* Fill the directly addressable memory with random bytes: */
438  if (m->random_mem_contents) {
439  for (i=0; i<(int)memory_amount; i+=256) {
440  unsigned char data[256];
441  unsigned int j;
442  for (j=0; j<sizeof(data); j++)
443  data[j] = random() & 255;
444  cpu->memory_rw(cpu, m->memory, i, data, sizeof(data),
446  }
447  }
448 
449  for (i=0; i<n_devices; i++)
450  device_add(m, device_names[i]);
451 
452  machine_setup(m);
453 
456 
457  /* Load files (ROM code, boot code, ...) into memory: */
458  if (n_load == 0) {
459  if (m->first_diskimage != NULL) {
460  if (!load_bootblock(m, cpu, &n_load, &load_names)) {
461  fprintf(stderr, "\nNo executable files were"
462  " specified, and booting directly from disk"
463  " failed.\n");
464  exit(1);
465  }
466  } else {
467  fprintf(stderr, "No executable file(s) loaded, and "
468  "we are not booting directly from a disk image."
469  "\nAborting.\n");
470  exit(1);
471  }
472  }
473 
474  while (n_load > 0) {
475  FILE *tmp_f;
476  char *name_to_load = *load_names;
477  int remove_after_load = 0;
478 
479  /* Special hack for removing temporary files: */
480  if (name_to_load[0] == 8) {
481  name_to_load ++;
482  remove_after_load = 1;
483  }
484 
485  /*
486  * gzipped files are automagically gunzipped:
487  * NOTE/TODO: This isn't secure. system() is used.
488  */
489  tmp_f = fopen(name_to_load, "r");
490  if (tmp_f != NULL) {
491  unsigned char buf[2]; /* gzip header */
492  size_t res;
493 
494  memset(buf, 0, sizeof(buf));
495  res = fread(buf, 1, sizeof(buf), tmp_f);
496 
497  if (res == sizeof(buf) &&
498  buf[0] == 0x1f && buf[1] == 0x8b) {
499  size_t zzlen = strlen(name_to_load)*2 + 100;
500  char *zz;
501 
502  CHECK_ALLOCATION(zz = (char*) malloc(zzlen));
503  debug("gunziping %s\n", name_to_load);
504 
505  /*
506  * gzip header found. If this was a file
507  * extracted from, say, a CDROM image, then it
508  * already has a temporary name. Otherwise we
509  * have to gunzip into a temporary file.
510  */
511  if (remove_after_load) {
512  snprintf(zz, zzlen, "mv %s %s.gz",
513  name_to_load, name_to_load);
514  if (system(zz) != 0)
515  perror(zz);
516  snprintf(zz, zzlen, "gunzip %s.gz",
517  name_to_load);
518  if (system(zz) != 0)
519  perror(zz);
520  } else {
521  /* gunzip into new temp file: */
522  int tmpfile_handle;
523  char *new_temp_name;
524  const char *tmpdir = getenv("TMPDIR");
525 
526  if (tmpdir == NULL)
527  tmpdir = DEFAULT_TMP_DIR;
528 
529  CHECK_ALLOCATION(new_temp_name =
530  (char*) malloc(300));
531  snprintf(new_temp_name, 300,
532  "%s/gxemul.XXXXXXXXXXXX", tmpdir);
533 
534  tmpfile_handle = mkstemp(new_temp_name);
535  close(tmpfile_handle);
536  snprintf(zz, zzlen, "gunzip -c '%s' > "
537  "%s", name_to_load, new_temp_name);
538  if (system(zz) != 0)
539  perror(zz);
540  name_to_load = new_temp_name;
541  remove_after_load = 1;
542  }
543  free(zz);
544  }
545  fclose(tmp_f);
546  }
547 
549 
550  /*
551  * Load the file: :-)
552  */
553  file_load(m, m->memory, name_to_load, &entrypoint,
554  m->arch, &gp, &byte_order, &toc);
555 
556  if (remove_after_load) {
557  debug("removing %s\n", name_to_load);
558  unlink(name_to_load);
559  }
560 
563 
564  cpu->pc = entrypoint;
565 
566  switch (m->arch) {
567 
568  case ARCH_ALPHA:
569  /* For position-independent code: */
570  cpu->cd.alpha.r[ALPHA_T12] = cpu->pc;
571  break;
572 
573  case ARCH_ARM:
574  if (cpu->pc & 2) {
575  fatal("ARM: misaligned pc: TODO\n");
576  exit(1);
577  }
578 
579  cpu->pc = (uint32_t)cpu->pc;
580 
581  // Lowest bit of PC indicates THUMB mode.
582  if (cpu->pc & 1)
583  cpu->cd.arm.cpsr |= ARM_FLAG_T;
584  break;
585 
586  case ARCH_M88K:
587  if (cpu->pc & 3) {
588  fatal("M88K: lowest bits of pc set: TODO\n");
589  exit(1);
590  }
591  cpu->pc &= 0xfffffffc;
592  break;
593 
594  case ARCH_MIPS:
595  if ((cpu->pc >> 32) == 0 && (cpu->pc & 0x80000000ULL))
596  cpu->pc |= 0xffffffff00000000ULL;
597 
598  cpu->cd.mips.gpr[MIPS_GPR_GP] = gp;
599 
600  if ((cpu->cd.mips.gpr[MIPS_GPR_GP] >> 32) == 0 &&
601  (cpu->cd.mips.gpr[MIPS_GPR_GP] & 0x80000000ULL))
602  cpu->cd.mips.gpr[MIPS_GPR_GP] |=
603  0xffffffff00000000ULL;
604  break;
605 
606  case ARCH_PPC:
607  /* See http://www.linuxbase.org/spec/ELF/ppc64/
608  spec/x458.html for more info. */
609  cpu->cd.ppc.gpr[2] = toc;
610  /* TODO */
611  if (cpu->cd.ppc.bits == 32)
612  cpu->pc &= 0xffffffffULL;
613  break;
614 
615  case ARCH_SH:
616  if (cpu->cd.sh.cpu_type.bits == 32)
617  cpu->pc &= 0xffffffffULL;
618  cpu->pc &= ~1;
619  break;
620 
621  default:
622  fatal("emul_machine_setup(): Internal error: "
623  "Unimplemented arch %i\n", m->arch);
624  exit(1);
625  }
626 
627  n_load --;
628  load_names ++;
629  }
630 
633 
634  /* Same byte order and entrypoint for all CPUs: */
635  for (i=0; i<m->ncpus; i++)
636  if (i != m->bootstrap_cpu) {
637  m->cpus[i]->byte_order = cpu->byte_order;
638  m->cpus[i]->pc = cpu->pc;
639  }
640 
641  /* Startup the bootstrap CPU: */
642  cpu->running = 1;
643 
644  /* ... or pause all CPUs, if start_paused is set: */
645  if (m->start_paused) {
646  for (i=0; i<m->ncpus; i++)
647  m->cpus[i]->running = 0;
648  }
649 
650  /* Parse and add breakpoints: */
651  add_breakpoints(m);
652 
653  /* TODO: This is MIPS-specific! */
654  if (m->machine_type == MACHINE_PMAX &&
657  0x9fff0000, 0x10000, "r2k3k_cache", 0, 0);
658 
660 
661  /* Special hack for ARC/SGI emulation: */
662  if ((m->machine_type == MACHINE_ARC ||
664  add_arc_components(m);
665 
666  debug("cpu%i: starting at ", m->bootstrap_cpu);
667 
668  switch (m->arch) {
669 
670  case ARCH_MIPS:
671  if (cpu->is_32bit) {
672  debug("0x%08" PRIx32, (uint32_t)
673  m->cpus[m->bootstrap_cpu]->pc);
674  if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)
675  debug(" (gp=0x%08" PRIx32")", (uint32_t)
676  m->cpus[m->bootstrap_cpu]->cd.mips.gpr[
677  MIPS_GPR_GP]);
678  } else {
679  debug("0x%016" PRIx64, (uint64_t)
680  m->cpus[m->bootstrap_cpu]->pc);
681  if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)
682  debug(" (gp=0x%016" PRIx64")", (uint64_t)
684  }
685  break;
686 
687  default:
688  if (cpu->is_32bit)
689  debug("0x%08" PRIx32, (uint32_t) cpu->pc);
690  else
691  debug("0x%016" PRIx64, (uint64_t) cpu->pc);
692  }
693  debug("\n");
694 
695  debug_indentation(-iadd);
696 }
697 
698 
699 /*
700  * emul_dumpinfo():
701  *
702  * Dump info about all machines in an emul.
703  */
704 void emul_dumpinfo(struct emul *e)
705 {
706  int i;
707 
708  if (e->net != NULL)
709  net_dumpinfo(e->net);
710 
711  for (i = 0; i < e->n_machines; i++) {
712  if (e->n_machines > 1)
713  debug("machine %i: \"%s\"\n", i, e->machines[i]->name);
714  else
715  debug("machine:\n");
716 
718 
719  machine_dumpinfo(e->machines[i]);
720 
722  }
723 }
724 
725 
726 /*
727  * emul_simple_init():
728  *
729  * For a normal setup:
730  *
731  * o) Initialize a network.
732  * o) Initialize one machine.
733  */
735 {
736  int iadd = DEBUG_INDENTATION;
737  struct machine *m;
738 
739  if (emul->n_machines != 1) {
740  fprintf(stderr, "emul_simple_init(): n_machines != 1\n");
741  exit(1);
742  }
743 
744  m = emul->machines[0];
745 
746  debug("Simple setup...\n");
747  debug_indentation(iadd);
748 
749  /* Create a simple network: */
753  NULL, 0, 0, NULL);
754 
755  /* Create the machine: */
757 
758  debug_indentation(-iadd);
759 }
760 
761 
762 /*
763  * emul_create_from_configfile():
764  *
765  * Create an emul struct by reading settings from a configuration file.
766  */
767 struct emul *emul_create_from_configfile(char *fname)
768 {
769  int iadd = DEBUG_INDENTATION;
770  struct emul *e = emul_new(fname);
771 
772  debug("Creating emulation from configfile \"%s\":\n", fname);
773  debug_indentation(iadd);
774 
775  emul_parse_config(e, fname);
776 
777  debug_indentation(-iadd);
778  return e;
779 }
780 
781 
782 /*
783  * emul_run():
784  *
785  * o) Set up things needed before running an emulation.
786  *
787  * o) Run instructions in all machines.
788  *
789  * o) De-initialize things.
790  */
791 void emul_run(struct emul *emul)
792 {
793  int i = 0, j, go = 1, n, anything;
794 
795  atexit(fix_console);
796 
797  if (emul == NULL) {
798  fatal("No emulation defined. Aborting.\n");
799  return;
800  }
801 
802  if (emul->n_machines == 0) {
803  fatal("No machine(s) defined. Aborting.\n");
804  return;
805  }
806 
807  /* Initialize the interactive debugger: */
809 
810  /* Run any additional debugger commands before starting: */
811  if (emul->n_debugger_cmds > 0) {
812  if (i == 0)
814  for (int k = 0; k < emul->n_debugger_cmds; k ++) {
815  debug("> %s\n", emul->debugger_cmds[k]);
817  strlen(emul->debugger_cmds[k]));
818  }
819  }
820 
822  debug("\n");
823 
824 
825  /*
826  * console_init_main() makes sure that the terminal is in a
827  * reasonable state.
828  *
829  * The SIGINT handler is for CTRL-C (enter the interactive debugger).
830  *
831  * The SIGCONT handler is invoked whenever the user presses CTRL-Z
832  * (or sends SIGSTOP) and then continues. It makes sure that the
833  * terminal is in an expected state.
834  */
836 
837  signal(SIGINT, debugger_activate);
838  signal(SIGCONT, console_sigcont);
839 
840  /* Not in verbose mode? Then set quiet_mode. */
841  if (!verbose)
842  quiet_mode = 1;
843 
844 
845  /* Initialize all CPUs in all machines: */
846  for (j=0; j<emul->n_machines; j++)
848 
849  /* TODO: Generalize: */
850  if (emul->machines[0]->show_trace_tree)
852  emul->machines[0]->cpus[0]->pc);
853 
854  /* Start emulated clocks: */
855  timer_start();
856 
857 
858  /*
859  * MAIN LOOP:
860  *
861  * Run all emulations in parallel, running instructions from each
862  * cpu in each machine.
863  */
864  while (go) {
865  struct cpu *bootcpu = emul->machines[0]->cpus[
867 
868  go = 0;
869 
870  /* Flush X11 and serial console output every now and then: */
871  if (bootcpu->ninstrs > bootcpu->ninstrs_flush + (1<<19)) {
873  console_flush();
874  bootcpu->ninstrs_flush = bootcpu->ninstrs;
875  }
876 
877  if (bootcpu->ninstrs > bootcpu->ninstrs_show + (1<<25)) {
878  bootcpu->ninstrs_since_gettimeofday +=
879  (bootcpu->ninstrs - bootcpu->ninstrs_show);
880  cpu_show_cycles(emul->machines[0], 0);
881  bootcpu->ninstrs_show = bootcpu->ninstrs;
882  }
883 
885  /* TODO: Cleanup! */
892  emul->machines[0]->show_trace_tree = 1;
893  quiet_mode = 0;
895  }
896 
898  debugger();
899 
900  for (j=0; j<emul->n_machines; j++) {
901  anything = machine_run(emul->machines[j]);
902  if (anything)
903  go = 1;
904  }
905  }
906 
907  /* Stop any running timers: */
908  timer_stop();
909 
910  /* Deinitialize all CPUs in all machines: */
911  for (j=0; j<emul->n_machines; j++)
913 
914  /* force_debugger_at_exit flag set? Then enter the debugger: */
916  quiet_mode = 0;
917  debugger_reset();
918  debugger();
919  }
920 
921  /* Any machine using X11? Then wait before exiting: */
922  n = 0;
923  for (j=0; j<emul->n_machines; j++)
924  if (emul->machines[j]->x11_md.in_use)
925  n++;
926 
927  if (n > 0) {
928  printf("Press enter to quit.\n");
929  while (!console_charavail(MAIN_CONSOLE)) {
931  usleep(10000);
932  }
934  }
935 
937 }
938 
file_load
void file_load(struct machine *machine, struct memory *mem, char *filename, uint64_t *entrypointp, int arch, uint64_t *gpp, int *byte_orderp, uint64_t *tocp)
Definition: file.cc:120
cpu_family_ptr_by_number
struct cpu_family * cpu_family_ptr_by_number(int arch)
Definition: cpu.cc:550
mips_cpu::cpu_type
struct mips_cpu_type_def cpu_type
Definition: cpu_mips.h:206
COMPONENT_CLASS_PeripheralClass
#define COMPONENT_CLASS_PeripheralClass
Definition: sgi_arcbios.h:202
data
u_short data
Definition: siireg.h:79
machine::machine_subtype
int machine_subtype
Definition: machine.h:112
cpu::ninstrs
int64_t ninstrs
Definition: cpu.h:340
force_debugger_at_exit
int force_debugger_at_exit
Definition: debugger.cc:70
machine::arch_pagesize
int arch_pagesize
Definition: machine.h:151
machine::bootstrap_cpu
int bootstrap_cpu
Definition: machine.h:136
emul_destroy
void emul_destroy(struct emul *emul)
Definition: emul.cc:178
x11_init
void x11_init(struct machine *machine)
Definition: x11.cc:49
emul::next_serial_nr
int next_serial_nr
Definition: emul.h:42
ARCH_PPC
#define ARCH_PPC
Definition: machine.h:204
machine::cpu_family
struct cpu_family * cpu_family
Definition: machine.h:124
debugger_reset
void debugger_reset(void)
Definition: debugger.cc:698
machine::name
const char * name
Definition: machine.h:105
cpu_run_deinit
void cpu_run_deinit(struct machine *machine)
Definition: cpu.cc:377
emul::settings
struct settings * settings
Definition: emul.h:38
cpu::running
uint8_t running
Definition: cpu.h:353
old_quiet_mode
int old_quiet_mode
Definition: debugger.cc:76
machine::symbol_context
struct symbol_context symbol_context
Definition: machine.h:144
machine::breakpoints
struct breakpoints breakpoints
Definition: machine.h:159
diskimage.h
emul::n_debugger_cmds
int n_debugger_cmds
Definition: emul.h:50
cpu_new
struct cpu * cpu_new(struct memory *mem, struct machine *machine, int cpu_id, char *name)
Definition: cpu.cc:58
settings.h
arcbios_add_memory_descriptor
void arcbios_add_memory_descriptor(struct cpu *cpu, uint64_t base, uint64_t len, int arctype)
Definition: arcbios.cc:437
settings_remove
void settings_remove(struct settings *settings, const char *name)
Definition: settings.cc:383
COMPONENT_FLAG_ReadOnly
#define COMPONENT_FLAG_ReadOnly
Definition: sgi_arcbios.h:315
SETTINGS_FORMAT_STRING
#define SETTINGS_FORMAT_STRING
Definition: settings.h:59
debug
#define debug
Definition: dev_adb.cc:57
machine::cpus
struct cpu ** cpus
Definition: machine.h:140
SETTINGS_FORMAT_DECIMAL
#define SETTINGS_FORMAT_DECIMAL
Definition: settings.h:52
settings_add
void settings_add(struct settings *settings, const char *name, int writable, int type, int format, void *ptr)
Definition: settings.cc:334
machine_destroy
void machine_destroy(struct machine *machine)
Definition: machine.cc:124
old_show_trace_tree
int old_show_trace_tree
Definition: debugger.cc:77
arcbios_get_scsicontroller
uint64_t arcbios_get_scsicontroller(struct machine *machine)
Definition: arcbios.cc:425
breakpoints::string
char ** string
Definition: machine.h:59
SETTINGS_TYPE_STRING
#define SETTINGS_TYPE_STRING
Definition: settings.h:39
COMPONENT_FLAG_Removable
#define COMPONENT_FLAG_Removable
Definition: sgi_arcbios.h:316
machine::show_trace_tree
int show_trace_tree
Definition: machine.h:164
machine_default_cputype
void machine_default_cputype(struct machine *)
Definition: machine.cc:572
if
addr & if(addr >=0x24 &&page !=NULL)
Definition: tmp_arm_multi.cc:56
diskimage::id
int id
Definition: diskimage.h:59
cpu::alpha
struct alpha_cpu alpha
Definition: cpu.h:443
emul::n_machines
int n_machines
Definition: emul.h:45
machine::use_random_bootstrap_cpu
int use_random_bootstrap_cpu
Definition: machine.h:137
cpu::byte_order
uint8_t byte_order
Definition: cpu.h:347
machine_memsize_fix
void machine_memsize_fix(struct machine *)
Definition: machine.cc:527
x11_check_event
void x11_check_event(struct emul *emul)
Definition: x11.cc:53
cpu_functioncall_trace
void cpu_functioncall_trace(struct cpu *cpu, uint64_t f)
Definition: cpu.cc:228
arm_cpu::cpsr
uint32_t cpsr
Definition: cpu_arm.h:175
debugger_execute_cmd
void debugger_execute_cmd(char *cmd, int cmd_len)
Definition: debugger.cc:258
arcbios_addchild_manual
uint64_t arcbios_addchild_manual(struct cpu *cpu, uint64_t cclass, uint64_t type, uint64_t flags, uint64_t version, uint64_t revision, uint64_t key, uint64_t affinitymask, const char *identifier, uint64_t parent, void *config_data, size_t config_len)
Definition: arcbios.cc:835
machine_run
int machine_run(struct machine *machine)
Definition: machine.cc:617
MACHINE_NONE
#define MACHINE_NONE
Definition: machine.h:261
timer_start
void timer_start(void)
Definition: timer.cc:206
console.h
addr
uint32_t addr
Definition: tmp_arm_multi.cc:52
machine::start_paused
int start_paused
Definition: machine.h:138
console_charavail
int console_charavail(int handle)
Definition: console.cc:347
cpu_show_cycles
void cpu_show_cycles(struct machine *machine, int forced)
Definition: cpu.cc:408
cpu::ninstrs_since_gettimeofday
int64_t ninstrs_since_gettimeofday
Definition: cpu.h:343
machine::prom_emulation
int prom_emulation
Definition: machine.h:149
console_init_main
void console_init_main(struct emul *emul)
Definition: console.cc:790
cpu::mips
struct mips_cpu mips
Definition: cpu.h:446
machine::first_diskimage
struct diskimage * first_diskimage
Definition: machine.h:142
device.h
emul::name
char * name
Definition: emul.h:40
machine_setup
void machine_setup(struct machine *)
Definition: machine.cc:449
load_bootblock
int load_bootblock(struct machine *m, struct cpu *cpu, int *n_loadp, char ***load_namesp)
Definition: bootblock.cc:65
SINGLE_STEPPING
#define SINGLE_STEPPING
Definition: debugger.h:49
cpu::ninstrs_show
int64_t ninstrs_show
Definition: cpu.h:341
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
ARCH_M88K
#define ARCH_M88K
Definition: machine.h:208
COMPONENT_TYPE_DiskController
#define COMPONENT_TYPE_DiskController
Definition: sgi_arcbios.h:282
NET_DEFAULT_IPV4_MASK
#define NET_DEFAULT_IPV4_MASK
Definition: net.h:44
breakpoints::n
int n
Definition: machine.h:56
emul_dumpinfo
void emul_dumpinfo(struct emul *e)
Definition: emul.cc:704
exec_elf.h
net_dumpinfo
void net_dumpinfo(struct net *net)
Definition: net.cc:655
machine::instruction_trace
int instruction_trace
Definition: machine.h:162
debugger.h
emul_run
void emul_run(struct emul *emul)
Definition: emul.cc:791
NO_BYTE_ORDER_OVERRIDE
#define NO_BYTE_ORDER_OVERRIDE
Definition: misc.h:162
machine::byte_order_override
int byte_order_override
Definition: machine.h:135
ENTER_SINGLE_STEPPING
#define ENTER_SINGLE_STEPPING
Definition: debugger.h:48
machine_dumpinfo
void machine_dumpinfo(struct machine *)
Definition: machine.cc:392
ARCH_MIPS
#define ARCH_MIPS
Definition: machine.h:203
strlen
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
Definition: cpu_arm_instr.cc:2686
PHYSICAL
#define PHYSICAL
Definition: memory.h:126
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
DISKIMAGE_SCSI
#define DISKIMAGE_SCSI
Definition: diskimage.h:40
machine::cpu_name
char * cpu_name
Definition: machine.h:133
x11_md::in_use
int in_use
Definition: machine.h:82
machine::serial_nr
int serial_nr
Definition: machine.h:120
debugger
void debugger(void)
Definition: debugger.cc:611
debugger_activate
void debugger_activate(int x)
Definition: debugger.cc:130
misc.h
settings_remove_all
void settings_remove_all(struct settings *settings)
Definition: settings.cc:441
console_sigcont
void console_sigcont(int x)
Definition: console.cc:159
console_flush
void console_flush(void)
Definition: console.cc:452
CACHE_NONE
#define CACHE_NONE
Definition: memory.h:123
cpu::cd
union cpu::@1 cd
device_add
void * device_add(struct machine *machine, const char *name_and_params)
Definition: device.cc:252
machine.h
machine
Definition: machine.h:97
console_readchar
int console_readchar(int handle)
Definition: console.cc:390
timer.h
ARCH_SH
#define ARCH_SH
Definition: machine.h:207
MMU3K
#define MMU3K
Definition: mips_cpu_types.h:44
breakpoints::addr
uint64_t * addr
Definition: machine.h:60
alpha_cpu::r
uint64_t r[N_ALPHA_REGS]
Definition: cpu_alpha.h:151
old_instruction_trace
int old_instruction_trace
Definition: debugger.cc:75
cpu::sh
struct sh_cpu sh
Definition: cpu.h:448
emul.h
machine::settings
struct settings * settings
Definition: machine.h:102
emul::debugger_cmds
char ** debugger_cmds
Definition: emul.h:51
ARCBIOS_MEM_FreeMemory
#define ARCBIOS_MEM_FreeMemory
Definition: sgi_arcbios.h:368
COMPONENT_CLASS_ControllerClass
#define COMPONENT_CLASS_ControllerClass
Definition: sgi_arcbios.h:201
machine::x11_md
struct x11_md x11_md
Definition: machine.h:179
cpu::is_32bit
uint8_t is_32bit
Definition: cpu.h:350
MACHINE_SGI
#define MACHINE_SGI
Definition: machine.h:217
emul_new
struct emul * emul_new(char *name)
Definition: emul.cc:143
emul_machine_setup
void emul_machine_setup(struct machine *m, int n_load, char **load_names, int n_devices, char **device_names)
Definition: emul.cc:354
cpu.h
mips_cpu_type_def::mmu_model
char mmu_model
Definition: cpu_mips.h:52
extra_argc
int extra_argc
Definition: main.cc:61
NET_INIT_FLAG_GATEWAY
#define NET_INIT_FLAG_GATEWAY
Definition: net.h:188
debugger_init
void debugger_init(struct emul *emul)
Definition: debugger.cc:709
ARM_FLAG_T
#define ARM_FLAG_T
Definition: cpu_arm.h:101
extra_argv
char ** extra_argv
Definition: main.cc:62
cpu::ppc
struct ppc_cpu ppc
Definition: cpu.h:447
emul::net
struct net * net
Definition: emul.h:43
machine_new
struct machine * machine_new(char *name, struct emul *emul, int id)
Definition: machine.cc:58
machine::memory
struct memory * memory
Definition: machine.h:126
arcbios_add_string_to_component
void arcbios_add_string_to_component(struct machine *machine, char *string, uint64_t component)
Definition: arcbios.cc:60
SETTINGS_TYPE_SUBSETTINGS
#define SETTINGS_TYPE_SUBSETTINGS
Definition: settings.h:38
machine::physical_ram_in_mb
uint32_t physical_ram_in_mb
Definition: machine.h:147
diskimage::writable
int writable
Definition: diskimage.h:78
x11.h
emul_parse_config
void emul_parse_config(struct emul *e, char *fname)
Definition: emul_parse.cc:699
diskimage::next
struct diskimage * next
Definition: diskimage.h:57
get_symbol_addr
int get_symbol_addr(struct symbol_context *, const char *symbol, uint64_t *addr)
Definition: symbol.cc:63
ALPHA_T12
#define ALPHA_T12
Definition: cpu_alpha.h:105
machine::random_mem_contents
int random_mem_contents
Definition: machine.h:146
sh_cpu::cpu_type
struct sh_cpu_type_def cpu_type
Definition: cpu_sh.h:97
settings_destroy
void settings_destroy(struct settings *settings)
Definition: settings.cc:105
MIPS_GPR_GP
#define MIPS_GPR_GP
Definition: cpu_mips.h:162
NO_EXCEPTIONS
#define NO_EXCEPTIONS
Definition: memory.h:125
cpu::arm
struct arm_cpu arm
Definition: cpu.h:444
console_debug_dump
void console_debug_dump(struct machine *machine)
Definition: console.cc:842
COMPONENT_TYPE_DiskPeripheral
#define COMPONENT_TYPE_DiskPeripheral
Definition: sgi_arcbios.h:296
verbose
int verbose
Definition: main.cc:77
sh_cpu_type_def::bits
int bits
Definition: cpu_sh.h:55
quiet_mode
int quiet_mode
Definition: emul.cc:68
diskimage::type
int type
Definition: diskimage.h:58
mips_cpu::gpr
uint64_t gpr[N_MIPS_GPRS]
Definition: cpu_mips.h:209
ppc_cpu::bits
int bits
Definition: cpu_ppc.h:116
MACHINE_PMAX
#define MACHINE_PMAX
Definition: machine.h:213
diskimage
Definition: diskimage.h:56
COMPONENT_FLAG_Input
#define COMPONENT_FLAG_Input
Definition: sgi_arcbios.h:319
emul_simple_init
void emul_simple_init(struct emul *emul)
Definition: emul.cc:734
machine::machine_type
int machine_type
Definition: machine.h:111
COMPONENT_FLAG_Output
#define COMPONENT_FLAG_Output
Definition: sgi_arcbios.h:320
emul_add_machine
struct machine * emul_add_machine(struct emul *e, char *name)
Definition: emul.cc:209
DEBUG_INDENTATION
#define DEBUG_INDENTATION
Definition: misc.h:212
emul
Definition: emul.h:37
ARCH_ARM
#define ARCH_ARM
Definition: machine.h:206
ppc_cpu::gpr
uint64_t gpr[PPC_NGPRS]
Definition: cpu_ppc.h:124
ARCH_ALPHA
#define ARCH_ALPHA
Definition: machine.h:205
add_symbol_name
void add_symbol_name(struct symbol_context *, uint64_t addr, uint64_t len, const char *name, int type, int n_args)
Definition: symbol.cc:199
COMPONENT_TYPE_FloppyDiskPeripheral
#define COMPONENT_TYPE_FloppyDiskPeripheral
Definition: sgi_arcbios.h:297
ARCBIOS_MEM_LoadedProgram
#define ARCBIOS_MEM_LoadedProgram
Definition: sgi_arcbios.h:370
arcbios.h
COMPONENT_TYPE_CDROMController
#define COMPONENT_TYPE_CDROMController
Definition: sgi_arcbios.h:284
emul::machines
struct machine ** machines
Definition: emul.h:46
NET_DEFAULT_IPV4_LEN
#define NET_DEFAULT_IPV4_LEN
Definition: net.h:45
DEFAULT_TMP_DIR
#define DEFAULT_TMP_DIR
Definition: misc.h:148
settings_new
struct settings * settings_new(void)
Definition: settings.cc:88
MAIN_CONSOLE
#define MAIN_CONSOLE
Definition: console.h:37
cpu
Definition: cpu.h:326
print_separator_line
void print_separator_line(void)
Definition: misc.cc:164
diskimage::is_a_cdrom
int is_a_cdrom
Definition: diskimage.h:79
emul_create_from_configfile
struct emul * emul_create_from_configfile(char *fname)
Definition: emul.cc:767
cpu::ninstrs_flush
int64_t ninstrs_flush
Definition: cpu.h:342
console_deinit_main
void console_deinit_main(void)
Definition: console.cc:139
MACHINE_ARC
#define MACHINE_ARC
Definition: machine.h:218
symbol_recalc_sizes
void symbol_recalc_sizes(struct symbol_context *)
Definition: symbol.cc:362
net.h
machine::memory_offset_in_mb
int memory_offset_in_mb
Definition: machine.h:148
memory_new
struct memory * memory_new(uint64_t physical_max, int arch)
Definition: memory.cc:146
cpu::memory_rw
int(* memory_rw)(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int cache_flags)
Definition: cpu.h:368
net_init
struct net * net_init(struct emul *emul, int init_flags, const char *ipv4addr, int netipv4len, char **remote, int n_remote, int local_port, const char *settings_prefix)
Definition: net.cc:720
machine::arch
int arch
Definition: machine.h:110
timer_stop
void timer_stop(void)
Definition: timer.cc:245
cpu_run_init
void cpu_run_init(struct machine *machine)
Definition: cpu.cc:483
cpu::pc
uint64_t pc
Definition: cpu.h:386
memory.h
mips_cpu_types.h
diskimage_dump_info
void diskimage_dump_info(struct machine *machine)
Definition: diskimage.cc:1099
debug_indentation
void debug_indentation(int diff)
Definition: main.cc:120
SETTINGS_TYPE_INT
#define SETTINGS_TYPE_INT
Definition: settings.h:40
single_step
int single_step
Definition: debugger.cc:68
machine::ncpus
int ncpus
Definition: machine.h:139
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18