1 |
<html><head><title>GXemul documentation: Technical details</title> |
<html><head><title>Gavare's eXperimental Emulator: Technical details</title> |
2 |
<meta name="robots" content="noarchive,nofollow,noindex"></head> |
<meta name="robots" content="noarchive,nofollow,noindex"></head> |
3 |
<body bgcolor="#f8f8f8" text="#000000" link="#4040f0" vlink="#404040" alink="#ff0000"> |
<body bgcolor="#f8f8f8" text="#000000" link="#4040f0" vlink="#404040" alink="#ff0000"> |
4 |
<table border=0 width=100% bgcolor="#d0d0d0"><tr> |
<table border=0 width=100% bgcolor="#d0d0d0"><tr> |
5 |
<td width=100% align=center valign=center><table border=0 width=100%><tr> |
<td width=100% align=center valign=center><table border=0 width=100%><tr> |
6 |
<td align="left" valign=center bgcolor="#d0efff"><font color="#6060e0" size="6"> |
<td align="left" valign=center bgcolor="#d0efff"><font color="#6060e0" size="6"> |
7 |
<b>GXemul documentation:</b></font> |
<b>Gavare's eXperimental Emulator:</b></font><br> |
8 |
<font color="#000000" size="6"><b>Technical details</b> |
<font color="#000000" size="6"><b>Technical details</b> |
9 |
</font></td></tr></table></td></tr></table><p> |
</font></td></tr></table></td></tr></table><p> |
10 |
|
|
11 |
<!-- |
<!-- |
12 |
|
|
13 |
$Id: technical.html,v 1.53 2005/06/27 17:31:50 debug Exp $ |
$Id: technical.html,v 1.72 2006/02/18 15:18:15 debug Exp $ |
14 |
|
|
15 |
Copyright (C) 2004-2005 Anders Gavare. All rights reserved. |
Copyright (C) 2004-2006 Anders Gavare. All rights reserved. |
16 |
|
|
17 |
Redistribution and use in source and binary forms, with or without |
Redistribution and use in source and binary forms, with or without |
18 |
modification, are permitted provided that the following conditions are met: |
modification, are permitted provided that the following conditions are met: |
40 |
--> |
--> |
41 |
|
|
42 |
|
|
43 |
|
|
44 |
<a href="./">Back to the index</a> |
<a href="./">Back to the index</a> |
45 |
|
|
46 |
<p><br> |
<p><br> |
53 |
<li><a href="#speed">Speed and emulation modes</a> |
<li><a href="#speed">Speed and emulation modes</a> |
54 |
<li><a href="#net">Networking</a> |
<li><a href="#net">Networking</a> |
55 |
<li><a href="#devices">Emulation of hardware devices</a> |
<li><a href="#devices">Emulation of hardware devices</a> |
|
<li><a href="#regtest">Regression tests</a> |
|
56 |
</ul> |
</ul> |
57 |
|
|
58 |
|
|
64 |
<a name="speed"></a> |
<a name="speed"></a> |
65 |
<h3>Speed and emulation modes</h3> |
<h3>Speed and emulation modes</h3> |
66 |
|
|
67 |
So, how fast is GXemul? There is no good answer to this. There is |
So, how fast is GXemul? There is no short answer to this. There is |
68 |
especially no answer to the question <b>What is the slowdown factor?</b>, |
especially no answer to the question <b>What is the slowdown factor?</b>, |
69 |
because the host architecture and emulated architecture can usually not be |
because the host architecture and emulated architecture can usually not be |
70 |
compared just like that. |
compared just like that. |
89 |
install NetBSD?", or "How long does it take to compile XYZ inside NetBSD |
install NetBSD?", or "How long does it take to compile XYZ inside NetBSD |
90 |
in the emulator?". |
in the emulator?". |
91 |
|
|
92 |
|
<p>So, how fast is it? :-) Answer: it varies. |
93 |
|
|
94 |
<p>The emulation technique used varies depending on which processor type |
<p>The emulation technique used varies depending on which processor type |
95 |
is being emulated. (One of my main goals with GXemul is to experiment with |
is being emulated. (One of my main goals with GXemul is to experiment with |
96 |
different kinds of emulation, so these might change in the future.) |
different kinds of emulation, so these might change in the future.) |
97 |
|
|
98 |
<ul> |
<ul> |
99 |
<li><b>MIPS</b><br> |
<li><b>MIPS:</b><br> |
100 |
There are two emulation modes. The most important one is an |
There are two emulation modes. The most important one is an |
101 |
implementation of a <i>dynamic binary translator</i>. |
implementation of a <i>dynamic binary translator</i>. |
102 |
(Compared to real binary translators, though, GXemul's bintrans |
(Compared to real binary translators, though, GXemul's bintrans |
107 |
works. It can be forcefully used by using the <tt>-B</tt> command |
works. It can be forcefully used by using the <tt>-B</tt> command |
108 |
line option.) |
line option.) |
109 |
<p> |
<p> |
110 |
<li><b>ARM</b><br> |
<li><b>All other modes:</b><br> |
111 |
This mode does not really work yet, but will use |
These use a kind of dynamic translation system. This system does |
112 |
dynamic translation, but not binary translation. Stay tuned. :-) |
not recompile anything into native code, it only uses tables of |
113 |
<p> |
pointers to functions written in (sometimes machine-generated) C |
114 |
<li><b>URISC</b><br> |
code. Speed is lower than what can be achieved using real binary |
115 |
Simple interpretation, one instruction at a time. There is probably |
translation into native code, but higher than when traditional |
116 |
no other way to emulate URISC, because it relies too heavily |
interpretation is used. With some tricks, it will hopefully still |
117 |
on self-modifying code. |
give reasonable speed. The ARM and PowerPC |
118 |
<p> |
emulation modes use this kind of translation. |
|
<li><b>POWER/PowerPC</b><br> |
|
|
This emulation mode is very much unfinished, but still enabled by |
|
|
default. So far it uses plain interpretation, where an instruction |
|
|
is read from emulated memory, and interpreted one at a time. |
|
|
Slow. Not very interesting. |
|
|
<p> |
|
|
<li><b>x86</b><br> |
|
|
Although too unstable and non-working to be enabled by default, |
|
|
there is some code for emulating x86 machines. It simply reads |
|
|
one instruction at a time from emulated memory, and executes it. |
|
|
This is as slow as it gets. Not very interesting. |
|
119 |
</ul> |
</ul> |
120 |
|
|
121 |
|
|
123 |
|
|
124 |
|
|
125 |
|
|
|
|
|
126 |
<p><br> |
<p><br> |
127 |
<a name="net"></a> |
<a name="net"></a> |
128 |
<h3>Networking</h3> |
<h3>Networking</h3> |
320 |
files in both directions, but then you should be aware of the |
files in both directions, but then you should be aware of the |
321 |
fragmentation issue mentioned above. |
fragmentation issue mentioned above. |
322 |
|
|
|
<p>TODO: Write a section on how to connect multiple emulator instances. |
|
|
(Using the <tt>local_port</tt> and <tt>add_remote</tt> configuration file |
|
|
commands.) |
|
323 |
|
|
324 |
|
|
325 |
|
|
330 |
<a name="devices"></a> |
<a name="devices"></a> |
331 |
<h3>Emulation of hardware devices</h3> |
<h3>Emulation of hardware devices</h3> |
332 |
|
|
333 |
Each file in the <tt>device/</tt> directory is responsible for one |
Each file called <tt>dev_*.c</tt> in the <tt>src/device/</tt> directory is |
334 |
hardware device. These are used from <tt>src/machine.c</tt>, when |
responsible for one hardware device. These are used from |
335 |
initializing which hardware a particular machine model will be using, or |
<tt>src/machines/machine_*.c</tt>, when initializing which hardware a particular |
336 |
when adding devices to a machine using the <tt>device()</tt> command in |
machine model will be using, or when adding devices to a machine using the |
337 |
configuration files. |
<tt>device()</tt> command in configuration files. |
|
|
|
|
<p><font color="#ff0000">NOTE: The device registry subsystem is currently |
|
|
in a state of flux, as it is being redesigned.</font> |
|
338 |
|
|
339 |
<p>(I'll be using the name "<tt>foo</tt>" as the name of the device in all |
<p>(I'll be using the name "<tt>foo</tt>" as the name of the device in all |
340 |
these examples. This is pseudo code, it might need some modification to |
these examples. This is pseudo code, it might need some modification to |
347 |
<li>A <tt>devinit</tt> function in <tt>src/devices/dev_foo.c</tt>. It |
<li>A <tt>devinit</tt> function in <tt>src/devices/dev_foo.c</tt>. It |
348 |
would typically look something like this: |
would typically look something like this: |
349 |
<pre> |
<pre> |
350 |
/* |
DEVINIT(foo) |
|
* devinit_foo(): |
|
|
*/ |
|
|
int devinit_foo(struct devinit *devinit) |
|
351 |
{ |
{ |
352 |
struct foo_data *d = malloc(sizeof(struct foo_data)); |
struct foo_data *d = malloc(sizeof(struct foo_data)); |
353 |
|
|
355 |
fprintf(stderr, "out of memory\n"); |
fprintf(stderr, "out of memory\n"); |
356 |
exit(1); |
exit(1); |
357 |
} |
} |
358 |
memset(d, 0, sizeof(struct foon_data)); |
memset(d, 0, sizeof(struct foo_data)); |
359 |
|
|
360 |
/* |
/* |
361 |
* Set up stuff here, for example fill d with useful |
* Set up stuff here, for example fill d with useful |
367 |
|
|
368 |
memory_device_register(devinit->machine->memory, devinit->name, |
memory_device_register(devinit->machine->memory, devinit->name, |
369 |
devinit->addr, DEV_FOO_LENGTH, |
devinit->addr, DEV_FOO_LENGTH, |
370 |
dev_foo_access, (void *)d, MEM_DEFAULT, NULL); |
dev_foo_access, (void *)d, DM_DEFAULT, NULL); |
371 |
|
|
372 |
/* This should only be here if the device |
/* This should only be here if the device |
373 |
has a tick function: */ |
has a tick function: */ |
379 |
} |
} |
380 |
</pre><br> |
</pre><br> |
381 |
|
|
382 |
|
<p><tt>DEVINIT(foo)</tt> is defined as <tt>int devinit_foo(struct devinit *devinit)</tt>, |
383 |
|
and the <tt>devinit</tt> argument contains everything that the device driver's |
384 |
|
initialization function needs. |
385 |
|
|
386 |
|
<p> |
387 |
<li>At the top of <tt>dev_foo.c</tt>, the <tt>foo_data</tt> struct |
<li>At the top of <tt>dev_foo.c</tt>, the <tt>foo_data</tt> struct |
388 |
should be defined. |
should be defined. |
389 |
<pre> |
<pre> |
392 |
/* ... */ |
/* ... */ |
393 |
} |
} |
394 |
</pre><br> |
</pre><br> |
395 |
|
(There is an exception to this rule; ugly hacks which allow |
396 |
|
code in <tt>src/machine.c</tt> to use some structures makes it |
397 |
|
necessary to place the <tt>struct foo_data</tt> in |
398 |
|
<tt>src/include/devices.h</tt> instead of in <tt>dev_foo.c</tt> |
399 |
|
itself. This is useful for example for interrupt controllers.) |
400 |
|
<p> |
401 |
<li>If <tt>foo</tt> has a tick function (that is, something that needs to be |
<li>If <tt>foo</tt> has a tick function (that is, something that needs to be |
402 |
run at regular intervals) then <tt>FOO_TICKSHIFT</tt> and a tick |
run at regular intervals) then <tt>FOO_TICKSHIFT</tt> and a tick |
403 |
function need to be defined as well: |
function need to be defined as well: |
404 |
<pre> |
<pre> |
405 |
#define FOO_TICKSHIFT 10 |
#define FOO_TICKSHIFT 14 |
406 |
|
|
407 |
void dev_foo_tick(struct cpu *cpu, void *extra) |
void dev_foo_tick(struct cpu *cpu, void *extra) |
408 |
{ |
{ |
415 |
} |
} |
416 |
</pre><br> |
</pre><br> |
417 |
|
|
418 |
|
<li>Does this device belong to a standard bus? |
419 |
|
<ul> |
420 |
|
<li>If this device should be detectable as a PCI device, then |
421 |
|
glue code should be added to |
422 |
|
<tt>src/devices/bus_pci.c</tt>. |
423 |
|
<li>If this is a legacy ISA device which should be usable by |
424 |
|
any machine which has an ISA bus, then the device should |
425 |
|
be added to <tt>src/devices/bus_isa.c</tt>. |
426 |
|
</ul> |
427 |
|
<p> |
428 |
<li>And last but not least, the device should have an access function. |
<li>And last but not least, the device should have an access function. |
429 |
The access function is called whenever there is a load or store |
The access function is called whenever there is a load or store |
430 |
to an address which is in the device' memory mapped region. |
to an address which is in the device' memory mapped region. To |
431 |
<pre> |
simplify things a little, a macro <tt>DEVICE_ACCESS(x)</tt> |
432 |
int dev_foo_access(struct cpu *cpu, struct memory *mem, |
is expanded into<pre> |
433 |
|
int dev_x_access(struct cpu *cpu, struct memory *mem, |
434 |
uint64_t relative_addr, unsigned char *data, size_t len, |
uint64_t relative_addr, unsigned char *data, size_t len, |
435 |
int writeflag, void *extra) |
int writeflag, void *extra) |
436 |
|
</pre> The access function can look like this: |
437 |
|
<pre> |
438 |
|
DEVICE_ACCESS(foo) |
439 |
{ |
{ |
440 |
struct foo_data *d = extra; |
struct foo_data *d = extra; |
441 |
uint64_t idata = 0, odata = 0; |
uint64_t idata = 0, odata = 0; |
479 |
|
|
480 |
|
|
481 |
|
|
|
<p><br> |
|
|
<a name="regtest"></a> |
|
|
<h3>Regression tests</h3> |
|
|
|
|
|
In order to make sure that the emulator actually works like it is supposed |
|
|
to, it must be tested. For this purpose, there is a simple regression |
|
|
testing framework in the <tt>tests/</tt> directory. |
|
|
|
|
|
<p> |
|
|
<i>NOTE: The regression testing framework is basically just a skeleton so far. |
|
|
Regression tests are very good to have. However, the fact that complete |
|
|
operating systems can run in the emulator indicate that the emulation is |
|
|
probably not too incorrect. This makes it less of a priority to write |
|
|
regression tests.</i> |
|
|
|
|
|
<p> |
|
|
To run all the regression tests, type <tt>make regtest</tt>. Each assembly |
|
|
language file matching the pattern <tt>test_*.S</tt> will be compiled and |
|
|
linked into a 64-bit MIPS ELF (using a gcc cross compiler), and run in the |
|
|
emulator. If everything goes well, you should see something like this: |
|
|
|
|
|
<pre> |
|
|
$ make regtest |
|
|
cd tests; make run_tests; cd .. |
|
|
gcc33 -Wall -fomit-frame-pointer -fmove-all-movables -fpeephole -O2 |
|
|
-mcpu=ev5 -I/usr/X11R6/include -lm -L/usr/X11R6/lib -lX11 do_tests.c |
|
|
-o do_tests |
|
|
do_tests.c: In function `main': |
|
|
do_tests.c:173: warning: unused variable `s' |
|
|
/var/tmp//ccFOupvD.o: In function `do_tests': |
|
|
/var/tmp//ccFOupvD.o(.text+0x3a8): warning: tmpnam() possibly used |
|
|
unsafely; consider using mkstemp() |
|
|
mips64-unknown-elf-gcc -g -O3 -fno-builtin -fschedule-insns -mips64 |
|
|
-mabi=64 test_common.c -c -o test_common.o |
|
|
./do_tests "mips64-unknown-elf-gcc -g -O3 -fno-builtin -fschedule-insns |
|
|
-mips64 -mabi=64" "mips64-unknown-elf-as -mabi=64 -mips64" |
|
|
"mips64-unknown-elf-ld -Ttext 0xa800000000030000 -e main |
|
|
--oformat=elf64-bigmips" "../gxemul" |
|
|
|
|
|
Starting tests: |
|
|
test_addu.S (-a) |
|
|
test_addu.S (-a -b) |
|
|
test_clo_clz.S (-a) |
|
|
test_clo_clz.S (-a -b) |
|
|
.. |
|
|
test_unaligned.S (-a) |
|
|
test_unaligned.S (-a -b) |
|
|
|
|
|
Done. (12 tests done) |
|
|
PASS: 12 |
|
|
FAIL: 0 |
|
|
|
|
|
---------------- |
|
|
|
|
|
All tests OK |
|
|
|
|
|
---------------- |
|
|
</pre> |
|
|
|
|
|
<p> |
|
|
Each test writes output to stdout, and there is a <tt>test_*.good</tt> for |
|
|
each <tt>.S</tt> file which contains the wanted output. If the actual |
|
|
output matches the <tt>.good</tt> file, then the test passes, otherwise it |
|
|
fails. |
|
|
|
|
|
<p> |
|
|
Read <tt>tests/README</tt> for more information. |
|
|
|
|
|
|
|
|
|
|
482 |
|
|
483 |
</body> |
</body> |
484 |
</html> |
</html> |