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