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++)
188  machine_destroy(emul->machines[i]);
189 
190  if (emul->machines != NULL)
191  free(emul->machines);
192 
193  /* Remove any remaining level-1 settings: */
195  settings_destroy(emul->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  m->memory = memory_new(memory_amount, m->arch);
396  debug("\n");
397 
398  /* Create CPUs: */
399  if (m->cpu_name == NULL)
401  if (m->ncpus == 0)
402  m->ncpus = 1;
403 
404  CHECK_ALLOCATION(m->cpus = (struct cpu **) malloc(sizeof(struct cpu *) * m->ncpus));
405  memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);
406 
407  debug("cpu0");
408  if (m->ncpus > 1)
409  debug(" .. cpu%i", m->ncpus - 1);
410  debug(": ");
411  for (i=0; i<m->ncpus; i++) {
412  m->cpus[i] = cpu_new(m->memory, m, i, m->cpu_name);
413  if (m->cpus[i] == NULL) {
414  fprintf(stderr, "Unable to create CPU object. "
415  "Aborting.");
416  exit(1);
417  }
418  }
419  debug("\n");
420 
422  m->bootstrap_cpu = random() % m->ncpus;
423  else
424  m->bootstrap_cpu = 0;
425 
426  cpu = m->cpus[m->bootstrap_cpu];
427 
428  if (m->x11_md.in_use)
429  x11_init(m);
430 
431  /* Fill memory with random bytes: */
432  if (m->random_mem_contents) {
433  for (i=0; i<m->physical_ram_in_mb * 1048576; i+=256) {
434  unsigned char data[256];
435  unsigned int j;
436  for (j=0; j<sizeof(data); j++)
437  data[j] = random() & 255;
438  cpu->memory_rw(cpu, m->memory, i, data, sizeof(data),
440  }
441  }
442 
443  for (i=0; i<n_devices; i++)
444  device_add(m, device_names[i]);
445 
446  machine_setup(m);
447 
450 
451  /* Load files (ROM code, boot code, ...) into memory: */
452  if (n_load == 0) {
453  if (m->first_diskimage != NULL) {
454  if (!load_bootblock(m, cpu, &n_load, &load_names)) {
455  fprintf(stderr, "\nNo executable files were"
456  " specified, and booting directly from disk"
457  " failed.\n");
458  exit(1);
459  }
460  } else {
461  fprintf(stderr, "No executable file(s) loaded, and "
462  "we are not booting directly from a disk image."
463  "\nAborting.\n");
464  exit(1);
465  }
466  }
467 
468  while (n_load > 0) {
469  FILE *tmp_f;
470  char *name_to_load = *load_names;
471  int remove_after_load = 0;
472 
473  /* Special hack for removing temporary files: */
474  if (name_to_load[0] == 8) {
475  name_to_load ++;
476  remove_after_load = 1;
477  }
478 
479  /*
480  * gzipped files are automagically gunzipped:
481  * NOTE/TODO: This isn't secure. system() is used.
482  */
483  tmp_f = fopen(name_to_load, "r");
484  if (tmp_f != NULL) {
485  unsigned char buf[2]; /* gzip header */
486  size_t res;
487 
488  memset(buf, 0, sizeof(buf));
489  res = fread(buf, 1, sizeof(buf), tmp_f);
490 
491  if (res == sizeof(buf) &&
492  buf[0] == 0x1f && buf[1] == 0x8b) {
493  size_t zzlen = strlen(name_to_load)*2 + 100;
494  char *zz;
495 
496  CHECK_ALLOCATION(zz = (char*) malloc(zzlen));
497  debug("gunziping %s\n", name_to_load);
498 
499  /*
500  * gzip header found. If this was a file
501  * extracted from, say, a CDROM image, then it
502  * already has a temporary name. Otherwise we
503  * have to gunzip into a temporary file.
504  */
505  if (remove_after_load) {
506  snprintf(zz, zzlen, "mv %s %s.gz",
507  name_to_load, name_to_load);
508  if (system(zz) != 0)
509  perror(zz);
510  snprintf(zz, zzlen, "gunzip %s.gz",
511  name_to_load);
512  if (system(zz) != 0)
513  perror(zz);
514  } else {
515  /* gunzip into new temp file: */
516  int tmpfile_handle;
517  char *new_temp_name;
518  const char *tmpdir = getenv("TMPDIR");
519 
520  if (tmpdir == NULL)
521  tmpdir = DEFAULT_TMP_DIR;
522 
523  CHECK_ALLOCATION(new_temp_name =
524  (char*) malloc(300));
525  snprintf(new_temp_name, 300,
526  "%s/gxemul.XXXXXXXXXXXX", tmpdir);
527 
528  tmpfile_handle = mkstemp(new_temp_name);
529  close(tmpfile_handle);
530  snprintf(zz, zzlen, "gunzip -c '%s' > "
531  "%s", name_to_load, new_temp_name);
532  if (system(zz) != 0)
533  perror(zz);
534  name_to_load = new_temp_name;
535  remove_after_load = 1;
536  }
537  free(zz);
538  }
539  fclose(tmp_f);
540  }
541 
542  byte_order = NO_BYTE_ORDER_OVERRIDE;
543 
544  /*
545  * Load the file: :-)
546  */
547  file_load(m, m->memory, name_to_load, &entrypoint,
548  m->arch, &gp, &byte_order, &toc);
549 
550  if (remove_after_load) {
551  debug("removing %s\n", name_to_load);
552  unlink(name_to_load);
553  }
554 
555  if (byte_order != NO_BYTE_ORDER_OVERRIDE)
556  cpu->byte_order = byte_order;
557 
558  cpu->pc = entrypoint;
559 
560  switch (m->arch) {
561 
562  case ARCH_ALPHA:
563  /* For position-independent code: */
564  cpu->cd.alpha.r[ALPHA_T12] = cpu->pc;
565  break;
566 
567  case ARCH_ARM:
568  if (cpu->pc & 2) {
569  fatal("ARM: misaligned pc: TODO\n");
570  exit(1);
571  }
572 
573  cpu->pc = (uint32_t)cpu->pc;
574 
575  // Lowest bit of PC indicates THUMB mode.
576  if (cpu->pc & 1)
577  cpu->cd.arm.cpsr |= ARM_FLAG_T;
578  break;
579 
580  case ARCH_M88K:
581  if (cpu->pc & 3) {
582  fatal("M88K: lowest bits of pc set: TODO\n");
583  exit(1);
584  }
585  cpu->pc &= 0xfffffffc;
586  break;
587 
588  case ARCH_MIPS:
589  if ((cpu->pc >> 32) == 0 && (cpu->pc & 0x80000000ULL))
590  cpu->pc |= 0xffffffff00000000ULL;
591 
592  cpu->cd.mips.gpr[MIPS_GPR_GP] = gp;
593 
594  if ((cpu->cd.mips.gpr[MIPS_GPR_GP] >> 32) == 0 &&
595  (cpu->cd.mips.gpr[MIPS_GPR_GP] & 0x80000000ULL))
596  cpu->cd.mips.gpr[MIPS_GPR_GP] |=
597  0xffffffff00000000ULL;
598  break;
599 
600  case ARCH_PPC:
601  /* See http://www.linuxbase.org/spec/ELF/ppc64/
602  spec/x458.html for more info. */
603  cpu->cd.ppc.gpr[2] = toc;
604  /* TODO */
605  if (cpu->cd.ppc.bits == 32)
606  cpu->pc &= 0xffffffffULL;
607  break;
608 
609  case ARCH_SH:
610  if (cpu->cd.sh.cpu_type.bits == 32)
611  cpu->pc &= 0xffffffffULL;
612  cpu->pc &= ~1;
613  break;
614 
615  default:
616  fatal("emul_machine_setup(): Internal error: "
617  "Unimplemented arch %i\n", m->arch);
618  exit(1);
619  }
620 
621  n_load --;
622  load_names ++;
623  }
624 
627 
628  /* Same byte order and entrypoint for all CPUs: */
629  for (i=0; i<m->ncpus; i++)
630  if (i != m->bootstrap_cpu) {
631  m->cpus[i]->byte_order = cpu->byte_order;
632  m->cpus[i]->pc = cpu->pc;
633  }
634 
635  /* Startup the bootstrap CPU: */
636  cpu->running = 1;
637 
638  /* ... or pause all CPUs, if start_paused is set: */
639  if (m->start_paused) {
640  for (i=0; i<m->ncpus; i++)
641  m->cpus[i]->running = 0;
642  }
643 
644  /* Parse and add breakpoints: */
645  add_breakpoints(m);
646 
647  /* TODO: This is MIPS-specific! */
648  if (m->machine_type == MACHINE_PMAX &&
649  cpu->cd.mips.cpu_type.mmu_model == MMU3K)
651  0x9fff0000, 0x10000, "r2k3k_cache", 0, 0);
652 
654 
655  /* Special hack for ARC/SGI emulation: */
656  if ((m->machine_type == MACHINE_ARC ||
658  add_arc_components(m);
659 
660  debug("cpu%i: starting at ", m->bootstrap_cpu);
661 
662  switch (m->arch) {
663 
664  case ARCH_MIPS:
665  if (cpu->is_32bit) {
666  debug("0x%08" PRIx32, (uint32_t)
667  m->cpus[m->bootstrap_cpu]->pc);
668  if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)
669  debug(" (gp=0x%08" PRIx32")", (uint32_t)
670  m->cpus[m->bootstrap_cpu]->cd.mips.gpr[
671  MIPS_GPR_GP]);
672  } else {
673  debug("0x%016" PRIx64, (uint64_t)
674  m->cpus[m->bootstrap_cpu]->pc);
675  if (cpu->cd.mips.gpr[MIPS_GPR_GP] != 0)
676  debug(" (gp=0x%016" PRIx64")", (uint64_t)
677  cpu->cd.mips.gpr[MIPS_GPR_GP]);
678  }
679  break;
680 
681  default:
682  if (cpu->is_32bit)
683  debug("0x%08" PRIx32, (uint32_t) cpu->pc);
684  else
685  debug("0x%016" PRIx64, (uint64_t) cpu->pc);
686  }
687  debug("\n");
688 
689  debug_indentation(-iadd);
690 }
691 
692 
693 /*
694  * emul_dumpinfo():
695  *
696  * Dump info about all machines in an emul.
697  */
698 void emul_dumpinfo(struct emul *e)
699 {
700  int i;
701 
702  if (e->net != NULL)
703  net_dumpinfo(e->net);
704 
705  for (i = 0; i < e->n_machines; i++) {
706  if (e->n_machines > 1)
707  debug("machine %i: \"%s\"\n", i, e->machines[i]->name);
708  else
709  debug("machine:\n");
710 
712 
713  machine_dumpinfo(e->machines[i]);
714 
716  }
717 }
718 
719 
720 /*
721  * emul_simple_init():
722  *
723  * For a normal setup:
724  *
725  * o) Initialize a network.
726  * o) Initialize one machine.
727  */
729 {
730  int iadd = DEBUG_INDENTATION;
731  struct machine *m;
732 
733  if (emul->n_machines != 1) {
734  fprintf(stderr, "emul_simple_init(): n_machines != 1\n");
735  exit(1);
736  }
737 
738  m = emul->machines[0];
739 
740  debug("Simple setup...\n");
741  debug_indentation(iadd);
742 
743  /* Create a simple network: */
744  emul->net = net_init(emul, NET_INIT_FLAG_GATEWAY,
747  NULL, 0, 0, NULL);
748 
749  /* Create the machine: */
751 
752  debug_indentation(-iadd);
753 }
754 
755 
756 /*
757  * emul_create_from_configfile():
758  *
759  * Create an emul struct by reading settings from a configuration file.
760  */
761 struct emul *emul_create_from_configfile(char *fname)
762 {
763  int iadd = DEBUG_INDENTATION;
764  struct emul *e = emul_new(fname);
765 
766  debug("Creating emulation from configfile \"%s\":\n", fname);
767  debug_indentation(iadd);
768 
769  emul_parse_config(e, fname);
770 
771  debug_indentation(-iadd);
772  return e;
773 }
774 
775 
776 /*
777  * emul_run():
778  *
779  * o) Set up things needed before running an emulation.
780  *
781  * o) Run instructions in all machines.
782  *
783  * o) De-initialize things.
784  */
785 void emul_run(struct emul *emul)
786 {
787  int i = 0, j, go = 1, n, anything;
788 
789  atexit(fix_console);
790 
791  if (emul == NULL) {
792  fatal("No emulation defined. Aborting.\n");
793  return;
794  }
795 
796  if (emul->n_machines == 0) {
797  fatal("No machine(s) defined. Aborting.\n");
798  return;
799  }
800 
801  /* Initialize the interactive debugger: */
802  debugger_init(emul);
803 
804  /* Run any additional debugger commands before starting: */
805  if (emul->n_debugger_cmds > 0) {
806  if (i == 0)
808  for (int k = 0; k < emul->n_debugger_cmds; k ++) {
809  debug("> %s\n", emul->debugger_cmds[k]);
811  strlen(emul->debugger_cmds[k]));
812  }
813  }
814 
816  debug("\n");
817 
818 
819  /*
820  * console_init_main() makes sure that the terminal is in a
821  * reasonable state.
822  *
823  * The SIGINT handler is for CTRL-C (enter the interactive debugger).
824  *
825  * The SIGCONT handler is invoked whenever the user presses CTRL-Z
826  * (or sends SIGSTOP) and then continues. It makes sure that the
827  * terminal is in an expected state.
828  */
829  console_init_main(emul);
830 
831  signal(SIGINT, debugger_activate);
832  signal(SIGCONT, console_sigcont);
833 
834  /* Not in verbose mode? Then set quiet_mode. */
835  if (!verbose)
836  quiet_mode = 1;
837 
838 
839  /* Initialize all CPUs in all machines: */
840  for (j=0; j<emul->n_machines; j++)
841  cpu_run_init(emul->machines[j]);
842 
843  /* TODO: Generalize: */
844  if (emul->machines[0]->show_trace_tree)
845  cpu_functioncall_trace(emul->machines[0]->cpus[0],
846  emul->machines[0]->cpus[0]->pc);
847 
848  /* Start emulated clocks: */
849  timer_start();
850 
851 
852  /*
853  * MAIN LOOP:
854  *
855  * Run all emulations in parallel, running instructions from each
856  * cpu in each machine.
857  */
858  while (go) {
859  struct cpu *bootcpu = emul->machines[0]->cpus[
860  emul->machines[0]->bootstrap_cpu];
861 
862  go = 0;
863 
864  /* Flush X11 and serial console output every now and then: */
865  if (bootcpu->ninstrs > bootcpu->ninstrs_flush + (1<<19)) {
866  x11_check_event(emul);
867  console_flush();
868  bootcpu->ninstrs_flush = bootcpu->ninstrs;
869  }
870 
871  if (bootcpu->ninstrs > bootcpu->ninstrs_show + (1<<25)) {
872  bootcpu->ninstrs_since_gettimeofday +=
873  (bootcpu->ninstrs - bootcpu->ninstrs_show);
874  cpu_show_cycles(emul->machines[0], 0);
875  bootcpu->ninstrs_show = bootcpu->ninstrs;
876  }
877 
879  /* TODO: Cleanup! */
881  emul->machines[0]->instruction_trace;
884  emul->machines[0]->show_trace_tree;
885  emul->machines[0]->instruction_trace = 1;
886  emul->machines[0]->show_trace_tree = 1;
887  quiet_mode = 0;
889  }
890 
892  debugger();
893 
894  for (j=0; j<emul->n_machines; j++) {
895  anything = machine_run(emul->machines[j]);
896  if (anything)
897  go = 1;
898  }
899  }
900 
901  /* Stop any running timers: */
902  timer_stop();
903 
904  /* Deinitialize all CPUs in all machines: */
905  for (j=0; j<emul->n_machines; j++)
906  cpu_run_deinit(emul->machines[j]);
907 
908  /* force_debugger_at_exit flag set? Then enter the debugger: */
910  quiet_mode = 0;
911  debugger_reset();
912  debugger();
913  }
914 
915  /* Any machine using X11? Then wait before exiting: */
916  n = 0;
917  for (j=0; j<emul->n_machines; j++)
918  if (emul->machines[j]->x11_md.in_use)
919  n++;
920 
921  if (n > 0) {
922  printf("Press enter to quit.\n");
923  while (!console_charavail(MAIN_CONSOLE)) {
924  x11_check_event(emul);
925  usleep(10000);
926  }
928  }
929 
931 }
932 
#define COMPONENT_FLAG_Removable
Definition: sgi_arcbios.h:316
void fatal(const char *fmt,...)
Definition: main.cc:152
int is_a_cdrom
Definition: diskimage.h:79
#define DEBUG_INDENTATION
Definition: misc.h:212
void timer_stop(void)
Definition: timer.cc:244
int prom_emulation
Definition: machine.h:149
int single_step
Definition: debugger.cc:68
char * cpu_name
Definition: machine.h:133
struct settings * settings_new(void)
Definition: settings.cc:88
void emul_destroy(struct emul *emul)
Definition: emul.cc:178
int arch_pagesize
Definition: machine.h:151
int n_machines
Definition: emul.h:45
void emul_machine_setup(struct machine *m, int n_load, char **load_names, int n_devices, char **device_names)
Definition: emul.cc:354
int serial_nr
Definition: machine.h:120
uint8_t is_32bit
Definition: cpu.h:350
#define ARCH_PPC
Definition: machine.h:204
void machine_memsize_fix(struct machine *)
Definition: machine.cc:527
void print_separator_line(void)
Definition: misc.cc:164
void console_init_main(struct emul *emul)
Definition: console.cc:785
int verbose
Definition: main.cc:77
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:118
int machine_type
Definition: machine.h:111
struct ppc_cpu ppc
Definition: cpu.h:444
union cpu::@1 cd
void x11_check_event(struct emul *emul)
Definition: x11.cc:53
#define DISKIMAGE_SCSI
Definition: diskimage.h:40
void emul_run(struct emul *emul)
Definition: emul.cc:785
#define SETTINGS_TYPE_STRING
Definition: settings.h:39
struct breakpoints breakpoints
Definition: machine.h:159
#define COMPONENT_TYPE_DiskPeripheral
Definition: sgi_arcbios.h:296
#define SINGLE_STEPPING
Definition: debugger.h:49
void cpu_run_deinit(struct machine *machine)
Definition: cpu.cc:368
struct cpu * cpu_new(struct memory *mem, struct machine *machine, int cpu_id, char *name)
Definition: cpu.cc:58
#define COMPONENT_FLAG_Output
Definition: sgi_arcbios.h:320
void debugger_execute_cmd(char *cmd, int cmd_len)
Definition: debugger.cc:258
struct memory * memory
Definition: machine.h:126
#define MACHINE_PMAX
Definition: machine.h:213
int old_show_trace_tree
Definition: debugger.cc:77
int force_debugger_at_exit
Definition: debugger.cc:70
struct settings * settings
Definition: emul.h:38
void x11_init(struct machine *machine)
Definition: x11.cc:49
struct arm_cpu arm
Definition: cpu.h:441
int machine_run(struct machine *machine)
Definition: machine.cc:617
int console_readchar(int handle)
Definition: console.cc:385
void debugger(void)
Definition: debugger.cc:611
void console_sigcont(int x)
Definition: console.cc:159
void * device_add(struct machine *machine, const char *name_and_params)
Definition: device.cc:252
struct cpu ** cpus
Definition: machine.h:140
#define MACHINE_ARC
Definition: machine.h:218
#define SETTINGS_FORMAT_DECIMAL
Definition: settings.h:52
int64_t ninstrs_flush
Definition: cpu.h:342
char * name
Definition: emul.h:40
int physical_ram_in_mb
Definition: machine.h:147
void timer_start(void)
Definition: timer.cc:206
#define MIPS_GPR_GP
void cpu_show_cycles(struct machine *machine, int forced)
Definition: cpu.cc:399
char ** debugger_cmds
Definition: emul.h:51
int ncpus
Definition: machine.h:139
int id
Definition: diskimage.h:59
uint64_t pc
Definition: cpu.h:383
#define COMPONENT_TYPE_CDROMController
Definition: sgi_arcbios.h:284
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
struct diskimage * first_diskimage
Definition: machine.h:142
void debugger_activate(int x)
Definition: debugger.cc:130
struct machine * emul_add_machine(struct emul *e, char *name)
Definition: emul.cc:209
int console_charavail(int handle)
Definition: console.cc:336
#define PHYSICAL
Definition: memory.h:126
int load_bootblock(struct machine *m, struct cpu *cpu, int *n_loadp, char ***load_namesp)
Definition: bootblock.cc:65
struct memory * memory_new(uint64_t physical_max, int arch)
Definition: memory.cc:146
int bootstrap_cpu
Definition: machine.h:136
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:365
#define DEFAULT_TMP_DIR
Definition: misc.h:148
int instruction_trace
Definition: machine.h:162
void settings_remove(struct settings *settings, const char *name)
Definition: settings.cc:383
int writable
Definition: diskimage.h:78
int bits
Definition: cpu_ppc.h:116
void settings_destroy(struct settings *settings)
Definition: settings.cc:105
int64_t ninstrs
Definition: cpu.h:340
struct diskimage * next
Definition: diskimage.h:57
u_short data
Definition: siireg.h:79
void machine_setup(struct machine *)
Definition: machine.cc:449
int start_paused
Definition: machine.h:138
#define COMPONENT_FLAG_Input
Definition: sgi_arcbios.h:319
struct emul * emul_new(char *name)
Definition: emul.cc:143
uint64_t arcbios_get_scsicontroller(struct machine *machine)
Definition: arcbios.cc:424
int extra_argc
Definition: main.cc:61
#define ARCH_ALPHA
Definition: machine.h:205
#define SETTINGS_FORMAT_STRING
Definition: settings.h:59
void diskimage_dump_info(struct machine *machine)
Definition: diskimage.cc:1087
void machine_destroy(struct machine *machine)
Definition: machine.cc:124
uint8_t running
Definition: cpu.h:353
#define MEM_WRITE
Definition: memory.h:117
#define COMPONENT_TYPE_FloppyDiskPeripheral
Definition: sgi_arcbios.h:297
#define ENTER_SINGLE_STEPPING
Definition: debugger.h:48
void machine_default_cputype(struct machine *)
Definition: machine.cc:572
#define ARCH_ARM
Definition: machine.h:206
void emul_simple_init(struct emul *emul)
Definition: emul.cc:728
#define NET_DEFAULT_IPV4_MASK
Definition: net.h:44
#define COMPONENT_CLASS_PeripheralClass
Definition: sgi_arcbios.h:202
#define ARCBIOS_MEM_LoadedProgram
Definition: sgi_arcbios.h:370
struct sh_cpu_type_def cpu_type
Definition: cpu_sh.h:97
Definition: emul.h:37
#define NET_INIT_FLAG_GATEWAY
Definition: net.h:188
struct cpu_family * cpu_family_ptr_by_number(int arch)
Definition: cpu.cc:541
int type
Definition: diskimage.h:58
void cpu_functioncall_trace(struct cpu *cpu, uint64_t f)
Definition: cpu.cc:219
int random_mem_contents
Definition: machine.h:146
struct x11_md x11_md
Definition: machine.h:179
#define COMPONENT_TYPE_DiskController
Definition: sgi_arcbios.h:282
uint32_t addr
#define ARCH_M88K
Definition: machine.h:208
#define ALPHA_T12
Definition: cpu_alpha.h:105
#define debug
Definition: dev_adb.cc:57
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
uint64_t r[N_ALPHA_REGS]
Definition: cpu_alpha.h:151
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:830
void debugger_init(struct emul *emul)
Definition: debugger.cc:709
#define NO_BYTE_ORDER_OVERRIDE
Definition: misc.h:162
#define SETTINGS_TYPE_SUBSETTINGS
Definition: settings.h:38
Definition: cpu.h:326
#define NO_EXCEPTIONS
Definition: memory.h:125
void console_deinit_main(void)
Definition: console.cc:139
void console_flush(void)
Definition: console.cc:447
#define ARCH_SH
Definition: machine.h:207
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
struct machine * machine_new(char *name, struct emul *emul, int id)
Definition: machine.cc:58
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
#define ARCBIOS_MEM_FreeMemory
Definition: sgi_arcbios.h:368
char ** extra_argv
Definition: main.cc:62
void debug_indentation(int diff)
Definition: main.cc:120
int64_t ninstrs_since_gettimeofday
Definition: cpu.h:343
int old_quiet_mode
Definition: debugger.cc:76
struct symbol_context symbol_context
Definition: machine.h:144
void settings_remove_all(struct settings *settings)
Definition: settings.cc:441
void settings_add(struct settings *settings, const char *name, int writable, int type, int format, void *ptr)
Definition: settings.cc:334
char ** string
Definition: machine.h:59
struct net * net
Definition: emul.h:43
struct settings * settings
Definition: machine.h:102
#define MACHINE_NONE
Definition: machine.h:262
#define MACHINE_SGI
Definition: machine.h:217
struct alpha_cpu alpha
Definition: cpu.h:440
int in_use
Definition: machine.h:82
void emul_dumpinfo(struct emul *e)
Definition: emul.cc:698
int get_symbol_addr(struct symbol_context *, const char *symbol, uint64_t *addr)
Definition: symbol.cc:63
struct machine ** machines
Definition: emul.h:46
void cpu_run_init(struct machine *machine)
Definition: cpu.cc:474
#define NET_DEFAULT_IPV4_LEN
Definition: net.h:45
int64_t ninstrs_show
Definition: cpu.h:341
uint8_t byte_order
Definition: cpu.h:347
const char * name
Definition: machine.h:105
void emul_parse_config(struct emul *e, char *fname)
Definition: emul_parse.cc:699
#define ARM_FLAG_T
Definition: cpu_arm.h:101
struct emul * emul_create_from_configfile(char *fname)
Definition: emul.cc:761
uint64_t gpr[N_MIPS_GPRS]
Definition: cpu_mips.h:209
#define COMPONENT_CLASS_ControllerClass
Definition: sgi_arcbios.h:201
struct mips_cpu mips
Definition: cpu.h:443
addr & if(addr >=0x24 &&page !=NULL)
uint32_t cpsr
Definition: cpu_arm.h:175
#define SETTINGS_TYPE_INT
Definition: settings.h:40
int quiet_mode
Definition: emul.cc:68
int memory_offset_in_mb
Definition: machine.h:148
void symbol_recalc_sizes(struct symbol_context *)
Definition: symbol.cc:362
int arch
Definition: machine.h:110
void machine_dumpinfo(struct machine *)
Definition: machine.cc:392
struct mips_cpu_type_def cpu_type
Definition: cpu_mips.h:206
uint64_t * addr
Definition: machine.h:60
#define MAIN_CONSOLE
Definition: console.h:37
void console_debug_dump(struct machine *machine)
Definition: console.cc:837
int old_instruction_trace
Definition: debugger.cc:75
void debugger_reset(void)
Definition: debugger.cc:698
#define MMU3K
#define CACHE_NONE
Definition: memory.h:123
void net_dumpinfo(struct net *net)
Definition: net.cc:655
int show_trace_tree
Definition: machine.h:164
int use_random_bootstrap_cpu
Definition: machine.h:137
void arcbios_add_string_to_component(struct machine *machine, char *string, uint64_t component)
Definition: arcbios.cc:59
struct cpu_family * cpu_family
Definition: machine.h:124
#define COMPONENT_FLAG_ReadOnly
Definition: sgi_arcbios.h:315
void arcbios_add_memory_descriptor(struct cpu *cpu, uint64_t base, uint64_t len, int arctype)
Definition: arcbios.cc:436
struct sh_cpu sh
Definition: cpu.h:445
int n_debugger_cmds
Definition: emul.h:50
uint64_t gpr[PPC_NGPRS]
Definition: cpu_ppc.h:124
#define ARCH_MIPS
Definition: machine.h:203
int byte_order_override
Definition: machine.h:135
int next_serial_nr
Definition: emul.h:42

Generated on Fri Dec 7 2018 19:52:23 for GXemul by doxygen 1.8.13