1 /*
2 * Copyright (C) 2005-2019 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 * Common routines for CPU emulation. (Not specific to any CPU type.)
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <sys/types.h>
34 #include <sys/mman.h>
35 #include <string.h>
36
37 #include "cpu.h"
38 #include "machine.h"
39 #include "memory.h"
40 #include "settings.h"
41 #include "timer.h"
42
43
44 extern size_t dyntrans_cache_size;
45
46 static struct cpu_family *first_cpu_family = NULL;
47
48
49 /*
50 * cpu_new():
51 *
52 * Create a new cpu object. Each family is tried in sequence until a
53 * CPU family recognizes the cpu_type_name.
54 *
55 * If there was no match, NULL is returned. Otherwise, a pointer to an
56 * initialized cpu struct is returned.
57 */
cpu_new(struct memory * mem,struct machine * machine,int cpu_id,char * name)58 struct cpu *cpu_new(struct memory *mem, struct machine *machine,
59 int cpu_id, char *name)
60 {
61 struct cpu *cpu;
62 struct cpu_family *fp;
63 char *cpu_type_name;
64 char tmpstr[30];
65
66 if (name == NULL) {
67 fprintf(stderr, "cpu_new(): cpu name = NULL?\n");
68 exit(1);
69 }
70
71 CHECK_ALLOCATION(cpu_type_name = strdup(name));
72
73 cpu = (struct cpu *) zeroed_alloc(sizeof(struct cpu));
74
75 CHECK_ALLOCATION(cpu->path = (char *) malloc(strlen(machine->path) + 15));
76 snprintf(cpu->path, strlen(machine->path) + 15,
77 "%s.cpu[%i]", machine->path, cpu_id);
78
79 cpu->memory_rw = NULL;
80 cpu->name = cpu_type_name;
81 cpu->mem = mem;
82 cpu->machine = machine;
83 cpu->cpu_id = cpu_id;
84 cpu->byte_order = EMUL_UNDEFINED_ENDIAN;
85 cpu->running = 0;
86
87 /* Create settings, and attach to the machine: */
88 cpu->settings = settings_new();
89 snprintf(tmpstr, sizeof(tmpstr), "cpu[%i]", cpu_id);
90 settings_add(machine->settings, tmpstr, 1,
91 SETTINGS_TYPE_SUBSETTINGS, 0, cpu->settings);
92
93 settings_add(cpu->settings, "name", 0, SETTINGS_TYPE_STRING,
94 SETTINGS_FORMAT_STRING, (void *) &cpu->name);
95 settings_add(cpu->settings, "running", 0, SETTINGS_TYPE_UINT8,
96 SETTINGS_FORMAT_YESNO, (void *) &cpu->running);
97
98 cpu_create_or_reset_tc(cpu);
99
100 fp = first_cpu_family;
101
102 while (fp != NULL) {
103 if (fp->cpu_new != NULL) {
104 if (fp->cpu_new(cpu, mem, machine, cpu_id,
105 cpu_type_name)) {
106 /* Sanity check: */
107 if (cpu->memory_rw == NULL) {
108 fatal("\ncpu_new(): memory_rw == "
109 "NULL\n");
110 exit(1);
111 }
112 break;
113 }
114 }
115
116 fp = fp->next;
117 }
118
119 if (fp == NULL) {
120 fatal("\ncpu_new(): unknown cpu type '%s'\n", cpu_type_name);
121 return NULL;
122 }
123
124 fp->init_tables(cpu);
125
126 if (cpu->byte_order == EMUL_UNDEFINED_ENDIAN) {
127 fatal("\ncpu_new(): Internal bug: Endianness not set.\n");
128 exit(1);
129 }
130
131 if (cpu->vaddr_mask == 0) {
132 if (cpu->is_32bit)
133 cpu->vaddr_mask = 0x00000000ffffffffULL;
134 else
135 cpu->vaddr_mask = (int64_t)-1;
136
137 // debug("\n\ncpu_new(): Warning: vaddr_mask should be set in the CPU family's cpu_new()! Assuming 0x%16llx\n\n", (long long)cpu->vaddr_mask);
138 }
139
140 return cpu;
141 }
142
143
144 /*
145 * cpu_destroy():
146 *
147 * Destroy a cpu object.
148 */
cpu_destroy(struct cpu * cpu)149 void cpu_destroy(struct cpu *cpu)
150 {
151 settings_remove(cpu->settings, "name");
152 settings_remove(cpu->settings, "running");
153
154 /* Remove any remaining level-1 settings: */
155 settings_remove_all(cpu->settings);
156
157 settings_destroy(cpu->settings);
158
159 if (cpu->path != NULL)
160 free(cpu->path);
161
162 /* TODO: This assumes that zeroed_alloc() actually succeeded
163 with using mmap(), and not malloc()! */
164 munmap((void *)cpu, sizeof(struct cpu));
165 }
166
167
168 /*
169 * cpu_tlbdump():
170 *
171 * Called from the debugger to dump the TLB in a readable format.
172 * x is the cpu number to dump, or -1 to dump all CPUs.
173 *
174 * If rawflag is nonzero, then the TLB contents isn't formated nicely,
175 * just dumped.
176 */
cpu_tlbdump(struct machine * m,int x,int rawflag)177 void cpu_tlbdump(struct machine *m, int x, int rawflag)
178 {
179 if (m->cpu_family == NULL || m->cpu_family->tlbdump == NULL)
180 fatal("cpu_tlbdump(): NULL\n");
181 else
182 m->cpu_family->tlbdump(m, x, rawflag);
183 }
184
185
186 /*
187 * cpu_disassemble_instr():
188 *
189 * Convert an instruction word into human readable format, for instruction
190 * tracing.
191 */
cpu_disassemble_instr(struct machine * m,struct cpu * cpu,unsigned char * instr,int running,uint64_t addr)192 int cpu_disassemble_instr(struct machine *m, struct cpu *cpu,
193 unsigned char *instr, int running, uint64_t addr)
194 {
195 if (m->cpu_family == NULL || m->cpu_family->disassemble_instr == NULL) {
196 fatal("cpu_disassemble_instr(): NULL\n");
197 return 0;
198 } else
199 return m->cpu_family->disassemble_instr(cpu, instr,
200 running, addr);
201 }
202
203
204 /*
205 * cpu_register_dump():
206 *
207 * Dump cpu registers in a relatively readable format.
208 *
209 * gprs: set to non-zero to dump GPRs. (CPU dependent.)
210 * coprocs: set bit 0..x to dump registers in coproc 0..x. (CPU dependent.)
211 */
cpu_register_dump(struct machine * m,struct cpu * cpu,int gprs,int coprocs)212 void cpu_register_dump(struct machine *m, struct cpu *cpu,
213 int gprs, int coprocs)
214 {
215 if (m->cpu_family == NULL || m->cpu_family->register_dump == NULL)
216 fatal("cpu_register_dump(): NULL\n");
217 else
218 m->cpu_family->register_dump(cpu, gprs, coprocs);
219 }
220
221
222 /*
223 * cpu_functioncall_trace():
224 *
225 * This function should be called if machine->show_trace_tree is enabled, and
226 * a function call is being made. f contains the address of the function.
227 */
cpu_functioncall_trace(struct cpu * cpu,uint64_t f)228 void cpu_functioncall_trace(struct cpu *cpu, uint64_t f)
229 {
230 int show_symbolic_function_name = 1;
231 int i, n_args = -1;
232 char *symbol;
233 uint64_t offset;
234
235 /* Special hack for M88K userspace: */
236 if (cpu->machine->arch == ARCH_M88K &&
237 !(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE))
238 show_symbolic_function_name = 0;
239
240 if (cpu->machine->ncpus > 1)
241 fatal("cpu%i:\t", cpu->cpu_id);
242
243 if (cpu->trace_tree_depth > 100)
244 cpu->trace_tree_depth = 100;
245 for (i=0; i<cpu->trace_tree_depth; i++)
246 fatal(" ");
247
248 cpu->trace_tree_depth ++;
249
250 fatal("<");
251 symbol = get_symbol_name_and_n_args(&cpu->machine->symbol_context,
252 f, &offset, &n_args);
253 if (symbol != NULL && show_symbolic_function_name && offset == 0)
254 fatal("%s", symbol);
255 else {
256 if (cpu->is_32bit)
257 fatal("0x%" PRIx32, (uint32_t) f);
258 else
259 fatal("0x%" PRIx64, (uint64_t) f);
260 }
261 fatal("(");
262
263 if (cpu->machine->cpu_family->functioncall_trace != NULL)
264 cpu->machine->cpu_family->functioncall_trace(cpu, n_args);
265
266 fatal(")>\n");
267
268 #ifdef PRINT_MEMORY_CHECKSUM
269 /* Temporary hack for finding bugs: */
270 fatal("call chksum=%016" PRIx64"\n", memory_checksum(cpu->mem));
271 #endif
272 }
273
274
275 /*
276 * cpu_functioncall_trace_return():
277 *
278 * This function should be called if machine->show_trace_tree is enabled, and
279 * a function is being returned from.
280 *
281 * TODO: Print return value? This could be implemented similar to the
282 * cpu->functioncall_trace function call above.
283 */
cpu_functioncall_trace_return(struct cpu * cpu)284 void cpu_functioncall_trace_return(struct cpu *cpu)
285 {
286 cpu->trace_tree_depth --;
287 if (cpu->trace_tree_depth < 0)
288 cpu->trace_tree_depth = 0;
289 }
290
291
292 /*
293 * cpu_create_or_reset_tc():
294 *
295 * Create the translation cache in memory (ie allocate memory for it), if
296 * necessary, and then reset it to an initial state.
297 */
cpu_create_or_reset_tc(struct cpu * cpu)298 void cpu_create_or_reset_tc(struct cpu *cpu)
299 {
300 size_t s = dyntrans_cache_size + DYNTRANS_CACHE_MARGIN;
301
302 if (cpu->translation_cache == NULL)
303 cpu->translation_cache = (unsigned char *) zeroed_alloc(s);
304
305 /* Create an empty table at the beginning of the translation cache: */
306 memset(cpu->translation_cache, 0, sizeof(uint32_t)
307 * N_BASE_TABLE_ENTRIES);
308
309 cpu->translation_cache_cur_ofs =
310 N_BASE_TABLE_ENTRIES * sizeof(uint32_t);
311
312 /*
313 * There might be other translation pointers that still point to
314 * within the translation_cache region. Let's invalidate those too:
315 */
316 if (cpu->invalidate_code_translation != NULL)
317 cpu->invalidate_code_translation(cpu, 0, INVALIDATE_ALL);
318 }
319
320
321 /*
322 * cpu_dumpinfo():
323 *
324 * Dumps info about a CPU using debug(). "cpu0: CPUNAME, running" (or similar)
325 * is outputed, and it is up to CPU dependent code to complete the line.
326 */
cpu_dumpinfo(struct machine * m,struct cpu * cpu)327 void cpu_dumpinfo(struct machine *m, struct cpu *cpu)
328 {
329 debug("cpu%i: %s, %s", cpu->cpu_id, cpu->name,
330 cpu->running? "running" : "stopped");
331
332 if (m->cpu_family == NULL || m->cpu_family->dumpinfo == NULL)
333 fatal("cpu_dumpinfo(): NULL\n");
334 else
335 m->cpu_family->dumpinfo(cpu);
336 }
337
338
339 /*
340 * cpu_list_available_types():
341 *
342 * Print a list of available CPU types for each cpu family.
343 */
cpu_list_available_types(void)344 void cpu_list_available_types(void)
345 {
346 struct cpu_family *fp;
347 int iadd = DEBUG_INDENTATION;
348
349 fp = first_cpu_family;
350
351 if (fp == NULL) {
352 debug("No CPUs defined!\n");
353 return;
354 }
355
356 while (fp != NULL) {
357 debug("%s:\n", fp->name);
358 debug_indentation(iadd);
359 if (fp->list_available_types != NULL)
360 fp->list_available_types();
361 else
362 debug("(internal error: list_available_types"
363 " = NULL)\n");
364 debug_indentation(-iadd);
365
366 fp = fp->next;
367 }
368 }
369
370
371 /*
372 * cpu_run_deinit():
373 *
374 * Shuts down all CPUs in a machine when ending a simulation. (This function
375 * should only need to be called once for each machine.)
376 */
cpu_run_deinit(struct machine * machine)377 void cpu_run_deinit(struct machine *machine)
378 {
379 int te;
380
381 /*
382 * Two last ticks of every hardware device. This will allow e.g.
383 * framebuffers to draw the last updates to the screen before halting.
384 *
385 * TODO: This should be refactored when redesigning the mainbus
386 * concepts!
387 */
388 for (te=0; te<machine->tick_functions.n_entries; te++) {
389 machine->tick_functions.f[te](machine->cpus[0],
390 machine->tick_functions.extra[te]);
391 machine->tick_functions.f[te](machine->cpus[0],
392 machine->tick_functions.extra[te]);
393 }
394
395 if (machine->show_nr_of_instructions)
396 cpu_show_cycles(machine, 1);
397
398 fflush(stdout);
399 }
400
401
402 /*
403 * cpu_show_cycles():
404 *
405 * If show_nr_of_instructions is on, then print a line to stdout about how
406 * many instructions/cycles have been executed so far.
407 */
cpu_show_cycles(struct machine * machine,int forced)408 void cpu_show_cycles(struct machine *machine, int forced)
409 {
410 uint64_t offset, pc;
411 char *symbol;
412 int64_t mseconds, ninstrs, is, avg;
413 struct timeval tv;
414 struct cpu *cpu = machine->cpus[machine->bootstrap_cpu];
415
416 static int64_t mseconds_last = 0;
417 static int64_t ninstrs_last = -1;
418
419 pc = cpu->pc;
420
421 gettimeofday(&tv, NULL);
422 mseconds = (tv.tv_sec - cpu->starttime.tv_sec) * 1000
423 + (tv.tv_usec - cpu->starttime.tv_usec) / 1000;
424
425 if (mseconds == 0)
426 mseconds = 1;
427
428 if (mseconds - mseconds_last == 0)
429 mseconds ++;
430
431 ninstrs = cpu->ninstrs_since_gettimeofday;
432
433 /* RETURN here, unless show_nr_of_instructions (-N) is turned on: */
434 if (!machine->show_nr_of_instructions && !forced)
435 goto do_return;
436
437 printf("[ %" PRIi64" instrs", (int64_t) cpu->ninstrs);
438
439 /* Instructions per second, and average so far: */
440 is = 1000 * (ninstrs-ninstrs_last) / (mseconds-mseconds_last);
441 avg = (long long)1000 * ninstrs / mseconds;
442 if (is < 0)
443 is = 0;
444 if (avg < 0)
445 avg = 0;
446
447 if (cpu->has_been_idling) {
448 printf("; idling");
449 cpu->has_been_idling = 0;
450 } else
451 printf("; i/s=%" PRIi64" avg=%" PRIi64, is, avg);
452
453 symbol = get_symbol_name(&machine->symbol_context, pc, &offset);
454
455 if (machine->ncpus == 1) {
456 if (cpu->is_32bit)
457 printf("; pc=0x%08" PRIx32, (uint32_t) pc);
458 else
459 printf("; pc=0x%016" PRIx64, (uint64_t) pc);
460 }
461
462 /* Special hack for M88K userland: (Don't show symbols.) */
463 if (cpu->machine->arch == ARCH_M88K &&
464 !(cpu->cd.m88k.cr[M88K_CR_PSR] & M88K_PSR_MODE))
465 symbol = NULL;
466
467 if (symbol != NULL)
468 printf(" <%s>", symbol);
469 printf(" ]\n");
470
471 do_return:
472 ninstrs_last = ninstrs;
473 mseconds_last = mseconds;
474 }
475
476
477 /*
478 * cpu_run_init():
479 *
480 * Prepare to run instructions on all CPUs in this machine. (This function
481 * should only need to be called once for each machine.)
482 */
cpu_run_init(struct machine * machine)483 void cpu_run_init(struct machine *machine)
484 {
485 int i;
486
487 if (machine->ncpus == 0) {
488 printf("Machine with no CPUs? TODO.\n");
489 exit(1);
490 }
491
492 for (i=0; i<machine->ncpus; i++) {
493 struct cpu *cpu = machine->cpus[i];
494
495 cpu->ninstrs_flush = 0;
496 cpu->ninstrs = 0;
497 cpu->ninstrs_show = 0;
498
499 /* For performance measurement: */
500 gettimeofday(&cpu->starttime, NULL);
501 cpu->ninstrs_since_gettimeofday = 0;
502 }
503 }
504
505
506 /*
507 * add_cpu_family():
508 *
509 * Allocates a cpu_family struct and calls an init function for the
510 * family to fill in reasonable data and pointers.
511 */
add_cpu_family(int (* family_init)(struct cpu_family *),int arch)512 static void add_cpu_family(int (*family_init)(struct cpu_family *), int arch)
513 {
514 struct cpu_family *fp, *tmp;
515 int res;
516
517 CHECK_ALLOCATION(fp = (struct cpu_family *) malloc(sizeof(struct cpu_family)));
518 memset(fp, 0, sizeof(struct cpu_family));
519
520 /*
521 * family_init() returns 1 if the struct has been filled with
522 * valid data, 0 if suppor for the cpu family isn't compiled
523 * into the emulator.
524 */
525 res = family_init(fp);
526 if (!res) {
527 free(fp);
528 return;
529 }
530 fp->arch = arch;
531 fp->next = NULL;
532
533 /* Add last in family chain: */
534 tmp = first_cpu_family;
535 if (tmp == NULL) {
536 first_cpu_family = fp;
537 } else {
538 while (tmp->next != NULL)
539 tmp = tmp->next;
540 tmp->next = fp;
541 }
542 }
543
544
545 /*
546 * cpu_family_ptr_by_number():
547 *
548 * Returns a pointer to a CPU family based on the ARCH_* integers.
549 */
cpu_family_ptr_by_number(int arch)550 struct cpu_family *cpu_family_ptr_by_number(int arch)
551 {
552 struct cpu_family *fp;
553 fp = first_cpu_family;
554
555 /* YUCK! This is too hardcoded! TODO */
556
557 while (fp != NULL) {
558 if (arch == fp->arch)
559 return fp;
560 fp = fp->next;
561 }
562
563 return NULL;
564 }
565
566
567 /*
568 * cpu_init():
569 *
570 * Should be called before any other cpu_*() function.
571 *
572 * This function calls add_cpu_family() for each processor architecture.
573 * ADD_ALL_CPU_FAMILIES is defined in the config.h file generated by the
574 * configure script.
575 */
cpu_init(void)576 void cpu_init(void)
577 {
578 ADD_ALL_CPU_FAMILIES;
579 }
580
581