1 /*
2  *  Copyright (C) 2005-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  *  COMMENT: Various test machines
29  *
30  *  Generally, the machines are as follows:
31  *
32  *	bareXYZ:	A bare machine using an XYZ processor.
33  *
34  *	testXYZ:	A machine with an XYZ processor, and some experimental
35  *			devices connected to it.
36  *
37  *  The experimental devices in the test machines are:
38  *
39  *	cons		A serial I/O console device.
40  *	disk		A device for reading/writing (emulated) disk sectors.
41  *	ether		An ethernet device, for sending/receiving ethernet
42  *			frames on an emulated network.
43  *	fb		Framebuffer (24-bit RGB per pixel).
44  *	irqc		A generic interrupt controller.
45  *	mp		A multiprocessor controller.
46  *	rtc		A real-time clock device.
47  */
48 
49 #include <stdio.h>
50 #include <string.h>
51 
52 #include "cpu.h"
53 #include "device.h"
54 #include "devices.h"
55 #include "machine.h"
56 #include "memory.h"
57 #include "misc.h"
58 
59 #include "thirdparty/sh4_exception.h"
60 
61 #include "testmachine/dev_cons.h"
62 #include "testmachine/dev_disk.h"
63 #include "testmachine/dev_ether.h"
64 #include "testmachine/dev_fb.h"
65 #include "testmachine/dev_irqc.h"
66 #include "testmachine/dev_mp.h"
67 #include "testmachine/dev_rtc.h"
68 
69 
70 /*
71  *  default_test():
72  *
73  *  Initializes devices for most test machines. (Note: MIPS is different,
74  *  because of legacy reasons.)
75  */
default_test(struct machine * machine,struct cpu * cpu)76 static void default_test(struct machine *machine, struct cpu *cpu)
77 {
78 	char tmpstr[2000];
79 	char base_irq[1000];
80 	char end_of_base_irq[50];
81 
82 	/*
83 	 *  First add the interrupt controller. Most processor architectures
84 	 *  in GXemul have only 1 interrupt pin on the CPU, and it is simply
85 	 *  called "machine[y].cpu[z]".
86 	 *
87 	 *  MIPS is an exception, dealt with in a separate setup function.
88 	 *  ARM and SH are dealt with here.
89 	 */
90 
91 	switch (machine->arch) {
92 
93 	case ARCH_ARM:
94 		snprintf(end_of_base_irq, sizeof(end_of_base_irq), ".irq");
95 		break;
96 
97 	case ARCH_SH:
98 		snprintf(end_of_base_irq, sizeof(end_of_base_irq),
99 		    ".irq[0x%x]", SH4_INTEVT_IRQ15);
100 		break;
101 
102 	default:
103 		end_of_base_irq[0] = '\0';
104 	}
105 
106 	snprintf(base_irq, sizeof(base_irq), "%s.cpu[%i]%s",
107 	    machine->path, machine->bootstrap_cpu, end_of_base_irq);
108 
109 	snprintf(tmpstr, sizeof(tmpstr), "irqc addr=0x%" PRIx64" irq=%s",
110 	    (uint64_t) DEV_IRQC_ADDRESS, base_irq);
111 	device_add(machine, tmpstr);
112 
113 
114 	/*  Now, add the other devices:  */
115 
116 	snprintf(tmpstr, sizeof(tmpstr), "cons addr=0x%" PRIx64
117 	    " irq=%s.irqc.2 in_use=%i",
118 	    (uint64_t) DEV_CONS_ADDRESS, base_irq, machine->arch != ARCH_SH);
119 	machine->main_console_handle = (size_t)device_add(machine, tmpstr);
120 
121 	snprintf(tmpstr, sizeof(tmpstr), "mp addr=0x%" PRIx64" irq=%s%sirqc.6",
122 	    (uint64_t) DEV_MP_ADDRESS,
123 	    end_of_base_irq[0]? end_of_base_irq + 1 : "",
124 	    end_of_base_irq[0]? "." : "");
125 	device_add(machine, tmpstr);
126 
127 	snprintf(tmpstr, sizeof(tmpstr), "fbctrl addr=0x%" PRIx64,
128 	    (uint64_t) DEV_FBCTRL_ADDRESS);
129 	device_add(machine, tmpstr);
130 
131 	snprintf(tmpstr, sizeof(tmpstr), "disk addr=0x%" PRIx64,
132 	    (uint64_t) DEV_DISK_ADDRESS);
133 	device_add(machine, tmpstr);
134 
135 	snprintf(tmpstr, sizeof(tmpstr), "ether addr=0x%" PRIx64" irq=%s.irqc.3",
136 	    (uint64_t) DEV_ETHER_ADDRESS, base_irq);
137 	device_add(machine, tmpstr);
138 
139 	snprintf(tmpstr, sizeof(tmpstr), "rtc addr=0x%" PRIx64" irq=%s.irqc.4",
140 	    (uint64_t) DEV_RTC_ADDRESS, base_irq);
141 	device_add(machine, tmpstr);
142 }
143 
144 
MACHINE_SETUP(barearm)145 MACHINE_SETUP(barearm)
146 {
147 	machine->machine_name = strdup("Generic \"bare\" ARM machine");
148 
149 #if 1
150 	// An experiment with running a particular firmware image on a device;
151 	// move some other place when/if it works?
152 	cpu->byte_order = EMUL_BIG_ENDIAN;
153 
154 	dev_ram_init(machine, 0xa0000000, 128 * 1048576, DEV_RAM_MIRROR
155 		| DEV_RAM_MIGHT_POINT_TO_DEVICES, 0x00000000, "ram_mirror");
156 #endif
157 }
158 
159 
MACHINE_SETUP(testarm)160 MACHINE_SETUP(testarm)
161 {
162 	machine->machine_name = strdup("ARM test machine");
163 
164 	default_test(machine, cpu);
165 
166 	/*
167 	 *  Place a tiny stub at end of memory, and set the link register to
168 	 *  point to it. This stub halts the machine (making it easy to try
169 	 *  out simple stand-alone C functions).
170 	 */
171 	cpu->cd.arm.r[ARM_SP] = machine->physical_ram_in_mb * 1048576 - 4096;
172 	cpu->cd.arm.r[ARM_LR] = cpu->cd.arm.r[ARM_SP] + 32;
173 	store_32bit_word(cpu, cpu->cd.arm.r[ARM_LR] + 0, 0xe3a00201);
174 	store_32bit_word(cpu, cpu->cd.arm.r[ARM_LR] + 4, 0xe5c00010);
175 	store_32bit_word(cpu, cpu->cd.arm.r[ARM_LR] + 8, 0xeafffffe);
176 }
177 
178 
MACHINE_DEFAULT_CPU(barearm)179 MACHINE_DEFAULT_CPU(barearm)
180 {
181 	machine->cpu_name = strdup("SA1110");
182 }
183 
184 
MACHINE_DEFAULT_CPU(testarm)185 MACHINE_DEFAULT_CPU(testarm)
186 {
187 	machine->cpu_name = strdup("SA1110");
188 }
189 
190 
MACHINE_REGISTER(barearm)191 MACHINE_REGISTER(barearm)
192 {
193 	MR_DEFAULT(barearm, "Generic \"bare\" ARM machine",
194 	    ARCH_ARM, MACHINE_BAREARM);
195 
196 	machine_entry_add_alias(me, "barearm");
197 }
198 
199 
MACHINE_REGISTER(testarm)200 MACHINE_REGISTER(testarm)
201 {
202 	MR_DEFAULT(testarm, "Test-machine for ARM", ARCH_ARM, MACHINE_TESTARM);
203 
204 	machine_entry_add_alias(me, "testarm");
205 }
206 
207 
208 
MACHINE_SETUP(barem88k)209 MACHINE_SETUP(barem88k)
210 {
211 	machine->machine_name = strdup("Generic \"bare\" M88K machine");
212 }
213 
214 
MACHINE_SETUP(oldtestm88k)215 MACHINE_SETUP(oldtestm88k)
216 {
217 	machine->machine_name = strdup("M88K test machine");
218 
219 	default_test(machine, cpu);
220 }
221 
222 
MACHINE_DEFAULT_CPU(barem88k)223 MACHINE_DEFAULT_CPU(barem88k)
224 {
225 	machine->cpu_name = strdup("88110");
226 }
227 
228 
MACHINE_DEFAULT_CPU(oldtestm88k)229 MACHINE_DEFAULT_CPU(oldtestm88k)
230 {
231 	machine->cpu_name = strdup("88110");
232 }
233 
234 
MACHINE_REGISTER(barem88k)235 MACHINE_REGISTER(barem88k)
236 {
237 	MR_DEFAULT(barem88k, "Generic \"bare\" M88K machine",
238 	    ARCH_M88K, MACHINE_BAREM88K);
239 
240 	machine_entry_add_alias(me, "barem88k");
241 }
242 
243 
MACHINE_REGISTER(oldtestm88k)244 MACHINE_REGISTER(oldtestm88k)
245 {
246 	MR_DEFAULT(oldtestm88k, "Test-machine for M88K",
247 	    ARCH_M88K, MACHINE_TESTM88K);
248 
249 	machine_entry_add_alias(me, "oldtestm88k");
250 }
251 
252 
MACHINE_SETUP(baremips)253 MACHINE_SETUP(baremips)
254 {
255 	machine->machine_name = strdup("Generic \"bare\" MIPS machine");
256 	cpu->byte_order = EMUL_BIG_ENDIAN;
257 }
258 
259 
MACHINE_SETUP(testmips)260 MACHINE_SETUP(testmips)
261 {
262 	/*
263 	 *  A MIPS test machine. Originally, this was created as a way for
264 	 *  me to test my master's thesis code; since then it has both
265 	 *  evolved to support new things, and suffered bit rot so that it
266 	 *  no longer can run my thesis code. Well, well...
267 	 *
268 	 *  IRQ map:
269 	 *      7       CPU counter
270 	 *      6       SMP IPIs
271 	 *      5       not used yet
272 	 *      4       rtc
273 	 *      3       ethernet
274 	 *      2       serial console
275 	 */
276 
277 	char tmpstr[300];
278 
279 	machine->machine_name = strdup("MIPS test machine");
280 	cpu->byte_order = EMUL_BIG_ENDIAN;
281 
282 	snprintf(tmpstr, sizeof(tmpstr), "cons addr=0x%" PRIx64" irq=%s."
283 	    "cpu[%i].2", (uint64_t) DEV_CONS_ADDRESS, machine->path,
284 	    machine->bootstrap_cpu);
285 	machine->main_console_handle = (size_t)device_add(machine, tmpstr);
286 
287 	snprintf(tmpstr, sizeof(tmpstr), "mp addr=0x%" PRIx64" irq=6",
288 	    (uint64_t) DEV_MP_ADDRESS);
289 	device_add(machine, tmpstr);
290 
291 	snprintf(tmpstr, sizeof(tmpstr), "fbctrl addr=0x%" PRIx64,
292 	    (uint64_t) DEV_FBCTRL_ADDRESS);
293 	device_add(machine, tmpstr);
294 
295 	snprintf(tmpstr, sizeof(tmpstr), "disk addr=0x%" PRIx64,
296 	    (uint64_t) DEV_DISK_ADDRESS);
297 	device_add(machine, tmpstr);
298 
299 	snprintf(tmpstr, sizeof(tmpstr), "ether addr=0x%" PRIx64" irq=%s."
300 	    "cpu[%i].3", (uint64_t) DEV_ETHER_ADDRESS, machine->path,
301 	    machine->bootstrap_cpu);
302 	device_add(machine, tmpstr);
303 
304 	snprintf(tmpstr, sizeof(tmpstr), "rtc addr=0x%" PRIx64" irq=%s."
305 	    "cpu[%i].4", (uint64_t) DEV_RTC_ADDRESS, machine->path,
306 	    machine->bootstrap_cpu);
307 	device_add(machine, tmpstr);
308 }
309 
310 
MACHINE_DEFAULT_CPU(baremips)311 MACHINE_DEFAULT_CPU(baremips)
312 {
313 	machine->cpu_name = strdup("5KE");
314 }
315 
316 
MACHINE_DEFAULT_CPU(testmips)317 MACHINE_DEFAULT_CPU(testmips)
318 {
319 	machine->cpu_name = strdup("5KE");
320 }
321 
322 
MACHINE_REGISTER(baremips)323 MACHINE_REGISTER(baremips)
324 {
325 	MR_DEFAULT(baremips, "Generic \"bare\" MIPS machine",
326 	    ARCH_MIPS, MACHINE_BAREMIPS);
327 
328 	machine_entry_add_alias(me, "baremips");
329 }
330 
331 
MACHINE_REGISTER(testmips)332 MACHINE_REGISTER(testmips)
333 {
334 	MR_DEFAULT(testmips, "Test-machine for MIPS",
335 	    ARCH_MIPS, MACHINE_TESTMIPS);
336 
337 	machine_entry_add_alias(me, "testmips");
338 }
339 
340 
MACHINE_SETUP(bareppc)341 MACHINE_SETUP(bareppc)
342 {
343 	machine->machine_name = strdup("Generic \"bare\" PPC machine");
344 }
345 
346 
MACHINE_SETUP(testppc)347 MACHINE_SETUP(testppc)
348 {
349 	machine->machine_name = strdup("PPC test machine");
350 
351 	default_test(machine, cpu);
352 }
353 
354 
MACHINE_DEFAULT_CPU(bareppc)355 MACHINE_DEFAULT_CPU(bareppc)
356 {
357 	machine->cpu_name = strdup("PPC970");
358 }
359 
360 
MACHINE_DEFAULT_CPU(testppc)361 MACHINE_DEFAULT_CPU(testppc)
362 {
363 	machine->cpu_name = strdup("PPC970");
364 }
365 
366 
MACHINE_REGISTER(bareppc)367 MACHINE_REGISTER(bareppc)
368 {
369 	MR_DEFAULT(bareppc, "Generic \"bare\" PPC machine",
370 	    ARCH_PPC, MACHINE_BAREPPC);
371 
372 	machine_entry_add_alias(me, "bareppc");
373 }
374 
375 
MACHINE_REGISTER(testppc)376 MACHINE_REGISTER(testppc)
377 {
378 	MR_DEFAULT(testppc, "Test-machine for PPC", ARCH_PPC, MACHINE_TESTPPC);
379 
380 	machine_entry_add_alias(me, "testppc");
381 }
382 
383 
MACHINE_SETUP(baresh)384 MACHINE_SETUP(baresh)
385 {
386 	machine->machine_name = strdup("Generic \"bare\" SH machine");
387 }
388 
389 
MACHINE_SETUP(testsh)390 MACHINE_SETUP(testsh)
391 {
392 	machine->machine_name = strdup("SH test machine");
393 
394 	default_test(machine, cpu);
395 }
396 
397 
MACHINE_DEFAULT_CPU(baresh)398 MACHINE_DEFAULT_CPU(baresh)
399 {
400 	machine->cpu_name = strdup("SH7750");
401 }
402 
403 
MACHINE_DEFAULT_CPU(testsh)404 MACHINE_DEFAULT_CPU(testsh)
405 {
406 	machine->cpu_name = strdup("SH7750");
407 }
408 
409 
MACHINE_REGISTER(baresh)410 MACHINE_REGISTER(baresh)
411 {
412 	MR_DEFAULT(baresh, "Generic \"bare\" SH machine",
413 	    ARCH_SH, MACHINE_BARESH);
414 
415 	machine_entry_add_alias(me, "baresh");
416 }
417 
418 
MACHINE_REGISTER(testsh)419 MACHINE_REGISTER(testsh)
420 {
421 	MR_DEFAULT(testsh, "Test-machine for SH", ARCH_SH, MACHINE_TESTSH);
422 
423 	machine_entry_add_alias(me, "testsh");
424 }
425 
426 
427 
428