/[gxemul]/trunk/doc/technical.html
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk/doc/technical.html

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (hide annotations)
Mon Oct 8 16:18:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/html
File size: 21775 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.772 2005/06/04 12:02:16 debug Exp $
20050428	Disabling the "-fmove-all-movables" option in the configure
		script, because it causes the compile to fail on OpenBSD/sgi.
20050502	Minor updates.
20050503	Removing the WRT54G mode (it was bogus anyway), and adding a
		comment about Windows NT for MIPS in doc/experiments.html.
		Minor updates to the x86 instruction decoding.
20050504	Adding some more x86 instructions.
		Adding support for reading files from ISO9660 CDROMs (including
		gzipped files). It's an ugly hack, but it seems to work.
		Various other minor updates (dev_vga.c, pc_bios.c etc).
20050505	Some more x86-related updates.
		Beginning (what I hope will be) a major code cleanup phase.
		"bootris" (an x86 bootsector) runs :-)
20050506	Adding some more x86 instructions.
20050507	tmpnam => mkstemp.
		Working on a hack to allow VGA charcells to be shown even when
		not running with X11.
		Adding more x86 instructions.
20050508	x86 32-bit SIB addressing fix, and more instructions.
20050509	Adding more x86 instructions.
20050510	Minor documentation updates, and other updates (x86 stuff etc.)
20050511	More x86-related updates.
20050513	Various updates, mostly x86-related. (Trying to fix flag 
		calculation, factoring out the ugly shift/rotate code, and
		some other things.)
20050514	Adding support for loading some old i386 a.out executables.
		Finally beginning the cleanup of machine/PROM/bios dependant
		info.
		Some minor documentation updates.
		Trying to clean up ARCBIOS stuff a little.
20050515	Trying to make it possible to actually use more than one disk
		type per machine (floppy, ide, scsi).
		Trying to clean up the kbd vs PROM console stuff. (For PC and
		ARC emulation modes, mostly.)
		Beginning to add an 8259 interrupt controller, and connecting
		it to the x86 emulation.
20050516	The first x86 interrupts seem to work (keyboard stuff).
		Adding a 8253/8254 programmable interval timer skeleton.
		FreeDOS now reaches a command prompt and can be interacted
		with.
20050517	After some bugfixes, MS-DOS also (sometimes) reaches a
		command prompt now.
		Trying to fix the pckbc to work with MS-DOS' keyb.com, but no
		success yet.
20050518	Adding a simple 32-bit x86 MMU skeleton.
20050519	Some more work on the x86 stuff. (Beginning the work on paging,
		and various other fixes).
20050520	More updates. Working on dev_vga (4-bit graphics modes), adding
		40 columns support to the PC bios emulation.
		Trying to add support for resizing windows when switching
		between graphics modes.
20050521	Many more x86-related updates.
20050522	Correcting the initial stack pointer's sign-extension for
		ARCBIOS emulation (thanks to Alec Voropay for noticing the
		error).
		Continuing on the cleanup (ARCBIOS etc).
		dev_vga updates.
20050523	More x86 updates: trying to add some support for protected mode
		interrupts (via gate descriptors) and many other fixes.
		More ARCBIOS cleanup.
		Adding a device flag which indicates that reads cause no
		side-effects. (Useful for the "dump" command in the debugger,
		and other things.)
		Adding support for directly starting up x86 ELFs, skipping the
		bootloader stage. (Most ELFs, however, are not suitable for
		this.)
20050524	Adding simple 32-bit x86 TSS task switching, but no privilege
		level support yet.
		More work on dev_vga. A small "Copper bars" demo works. :-)
		Adding support for Trap Flag (single-step exceptions), at least
		in real mode, and various other x86-related fixes.
20050525	Adding a new disk image prefix (gH;S;) which can be used to
		override the default nr of heads and sectors per track.
20050527	Various bug fixes, more work on the x86 mode (stack change on
		interrupts between different priv.levels), and some minor
		documentation updates.
20050528	Various fixes (x86 stuff).
20050529	More x86 fixes. An OpenBSD/i386 bootfloppy reaches userland
		and can be interacted with (although there are problems with
		key repetition). NetBSD/i386 triggers a serious CISC-related
		problem: instruction fetches across page boundaries, where
		the later part isn't actually part of the instruction.
20050530	Various minor updates. (Documentation updates, etc.)
20050531	Adding some experimental code (experiments/new_test_*) which
		could be useful for dynamic (but not binary) translation in
		the future.
20050602	Adding a dummy ARM skeleton.
		Fixing the pckbc key repetition problem (by adding release
		scancodes for all keypresses).
20050603	Minor updates for the next release.
20050604	Release testing. Minor updates.

==============  RELEASE 0.3.3  ==============

20050604	There'll probably be a 0.3.3.1 release soon, with some very
		very tiny updates.


1 dpavlin 2 <html>
2     <head><title>GXemul documentation: Technical details</title>
3     </head>
4 dpavlin 4 <body bgcolor="#f8f8f8" text="#000000" link="#4040f0" vlink="#404040" alink="#ff0000">
5     <table border=0 width=100% bgcolor="#d0d0d0"><tr>
6     <td width=100% align=center valign=center><table border=0 width=100%><tr>
7     <td align="left" valign=center bgcolor="#d0efff"><font color="#6060e0" size="6">
8     <b>GXemul documentation:</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
9     <font color="#000000" size="6"><b>Technical details</b>
10     </font></td></tr></table></td></tr></table><p>
11 dpavlin 2 <!-- The first 10 lines are cut away by the homepage updating script. -->
12    
13    
14     <!--
15    
16 dpavlin 6 $Id: technical.html,v 1.50 2005/05/14 18:31:16 debug Exp $
17 dpavlin 2
18     Copyright (C) 2004-2005 Anders Gavare. All rights reserved.
19    
20     Redistribution and use in source and binary forms, with or without
21     modification, are permitted provided that the following conditions are met:
22    
23     1. Redistributions of source code must retain the above copyright
24     notice, this list of conditions and the following disclaimer.
25     2. Redistributions in binary form must reproduce the above copyright
26     notice, this list of conditions and the following disclaimer in the
27     documentation and/or other materials provided with the distribution.
28     3. The name of the author may not be used to endorse or promote products
29     derived from this software without specific prior written permission.
30    
31     THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
32     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34     ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
35     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41     SUCH DAMAGE.
42    
43     -->
44    
45    
46     <a href="./">Back to the index</a>
47    
48     <p><br>
49     <h2>Technical details</h2>
50    
51     <p>
52     This page describes some of the internals of GXemul.
53    
54     <p>
55 dpavlin 6 <font color="#e00000"><b>NOTE: This page is probably not
56     very up-to-date by now.</b></font>
57    
58     <p>
59 dpavlin 2 <ul>
60     <li><a href="#overview">Overview</a>
61     <li><a href="#speed">Speed</a>
62     <li><a href="#net">Networking</a>
63     <li><a href="#devices">Emulation of hardware devices</a>
64     <li><a href="#regtest">Regression tests</a>
65     </ul>
66    
67    
68    
69    
70     <p><br>
71     <a name="overview"></a>
72     <h3>Overview</h3>
73    
74     In simple terms, GXemul is just a simple fetch-and-execute
75     loop; an instruction is fetched from memory, and executed.
76    
77     <p>
78     In reality, a lot of things need to be handled. Before each instruction is
79     executed, the emulator checks to see if any interrupts are asserted which
80     are not masked away. If so, then an INT exception is generated. Exceptions
81     cause the program counter to be set to a specific value, and some of the
82     system coprocessor's registers to be set to values signifying what kind of
83     exception it was (an interrupt exception in this case).
84    
85     <p>
86     Reading instructions from memory is done through a TLB, a translation
87     lookaside buffer. The TLB on MIPS is software controlled, which means that
88     the program running inside the emulator (for example an operating system
89     kernel) has to take care of manually updating the TLB. Some memory
90     addresses are translated into physical addresses directly, some are
91     translated into valid physical addresses via the TLB, and some memory
92     references are not valid. Invalid memory references cause exceptions.
93    
94     <p>
95     After an instruction has been read from memory, the emulator checks which
96     opcode it contains and executes the instruction. Executing an instruction
97     usually involves reading some register and writing some register, or perhaps a
98     load from memory (or a store to memory). The program counter is increased
99     for every instruction.
100    
101     <p>
102     Some memory references point to physical addresses which are not in the
103     normal RAM address space. They may point to hardware devices. If that is
104     the case, then loads and stores are converted into calls to a device
105     access function. The device access function is then responsible for
106     handling these reads and writes. For example, a graphical framebuffer
107     device may put a pixel on the screen when a value is written to it, or a
108     serial controller device may output a character to stdout when written to.
109    
110    
111    
112    
113     <p><br>
114     <a name="speed"></a>
115     <h3>Speed</h3>
116    
117     There are two modes in which the emulator can run, <b>a</b>) a straight forward
118     loop which fetches one instruction from emulated RAM and executes it
119     (described in the previous section), and <b>b</b>)
120     using dynamic binary translation.
121    
122     <p>
123     Mode <b>a</b> is very slow. On a 2.8 GHz Intel Xeon host the resulting
124     emulated machine is rougly equal to a 7 MHz R3000 (or a 3.5 MHz R4000).
125     The actual performance varies a lot, maybe between 5 and 10 million
126     instructions per second, depending on workload.
127    
128     <p>
129     Mode <b>b</b> ("bintrans") is still to be considered experimental, but
130     gives higher performance than mode <b>a</b>. It translates MIPS machine
131     code into machine code that can be executed on the host machine
132     on-the-fly. The translation itself obviously takes some time, but this is
133     usually made up for by the fact that the translated code chunks are
134     executed multiple times.
135 dpavlin 6 To run the emulator with binary translation enabled, just add
136     <tt><b>-b</b></tt> to the command line.
137 dpavlin 2
138     <p>
139     Only small pieces of MIPS machine code are translated, usually the size of
140     a function, or less. There is no "intermediate representation" code, so
141     all translations are done directly from MIPS to host machine code.
142    
143     <p>
144     The default bintrans cache size is 16 MB, but you can change this by adding
145 dpavlin 6 <tt>-DDEFAULT_BINTRANS_SIZE_IN_MB=<i>xx</i></tt> to your CFLAGS environment
146     variable before running the configure script, or by using the
147     <tt>bintrans_size()</tt> configuration file option when running the emulator.
148 dpavlin 2
149     <p>
150     By default, an emulated OS running under DECstation emulation which listens to
151     interrupts from the mc146818 clock will get interrupts that are close to the
152     host's clock. That is, if the emulated OS says it wants 100 interrupts per
153     second, it will get approximately 100 interrupts per real second.
154    
155     <p>
156 dpavlin 6 There is however a <tt><b>-I</b></tt> option, which sets the number of
157     emulated cycles per seconds to a fixed value. Let's say you wish to make the
158     emulated OS think it is running on a 40 MHz DECstation, and not a 7 MHz one,
159     then you can add <tt><b>-I 40000000</b></tt> to the command line. This will not
160     make the emulation faster, of course. It might even make it seem slower; for
161     example, if NetBSD/pmax waits 2 seconds for SCSI devices to settle during
162     bootup, those 2 seconds will take 2*40000000 cycles (which will take more
163     time than 2*7000000).
164 dpavlin 2
165     <p>
166 dpavlin 6 The <b><tt>-I</tt></b> option is also necessary if you want to run
167     deterministic experiments, if a mc146818 (or similar) device is present.
168 dpavlin 2
169     <p>
170     Some emulators make claims such as "x times slowdown," but in the case of
171     GXemul, the host is often not a MIPS-based machine, and hence comparing
172     one MIPS instruction to a host instruction doesn't work. Performance depends on
173     a lot of factors, including (but not limited to) host architecture, host speed,
174     which compiler and compiler flags were used to build GXemul, what the
175     workload is, and so on. For example, if an emulated operating system tries
176     to read a block from disk, from its point of view the read was instantaneous
177     (no waiting). So 1 MIPS in an emulated OS might have taken more than one
178     million instructions on a real machine. Because of this, imho it is best
179     to measure performance as the actual (real-world) time it takes to perform
180     a task with the emulator.
181    
182    
183    
184    
185     <p><br>
186     <a name="net"></a>
187     <h3>Networking</h3>
188    
189     Running an entire operating system under emulation is very interesting in
190     itself, but for several reasons, running a modern OS without access to
191     TCP/IP networking is a bit akward. Hence, I feel the need to implement TCP/IP
192     (networking) support in the emulator.
193    
194     <p>
195     As far as I have understood it, there seems to be two different ways to go:
196    
197     <ol>
198     <li>Forward ethernet packets from the emulated ethernet controller to
199     the host machine's ethernet controller, and capture incoming
200     packets on the host's controller, giving them back to the
201     emulated OS. Characteristics are:
202     <ul>
203     <li>Requires <i>direct</i> access to the host's NIC, which
204     means on most platforms that the emulator cannot be
205     run as a normal user!
206     <li>Reduced portability, as not every host operating system
207     uses the same programming interface for dealing with
208     hardware ethernet controllers directly.
209     <li>When run on a switched network, it might be problematic to
210     connect from the emulated OS to the OS running on the
211     host, as packets sent out on the host's NIC are not
212     received by itself. (?)
213 dpavlin 6 <li>All specific networking protocols will be handled by the
214     physical network.
215 dpavlin 2 </ul>
216     <p>
217     or
218     <p>
219     <li>Whenever the emulated ethernet controller wishes to send a packet,
220     the emulator looks at the packet and creates a response. Packets
221     that can have an immediate response never go outside the emulator,
222     other packet types have to be converted into suitable other
223     connection types (UDP, TCP, etc). Characteristics:
224     <ul>
225     <li>Each packet type sent out on the emulated NIC must be handled.
226     This means that I have to do a lot of coding.
227     (I like this, because it gives me an opportunity to
228     learn about networking protocols.)
229     <li>By not relying on access to the host's NIC directly,
230     portability is maintained. (It would be sad if the networking
231     portion of a portable emulator isn't as portable as the
232     rest of the emulator.)
233     <li>The emulator can be run as a normal user process, does
234     not require root privilegies.
235     <li>Connecting from the emulated OS to the host's OS should
236     not be problematic.
237     <li>The emulated OS will experience the network just as a single
238     machine behind a NAT gateway/firewall would. The emulated
239     OS is thus automatically protected from the outside world.
240     </ul>
241     </ol>
242    
243 dpavlin 6 <p>
244     Some emulators/simulators use the first approach, while others use the
245     second. I think that SIMH and QEMU are examples of emulators using the
246     first and second approach, respectively.
247 dpavlin 2
248     <p>
249     Since I have choosen the second kind of implementation, I have to write
250     support explicitly for any kind of network protocol that should be
251     supported. As of 2004-07-09, the following has been implemented and seems
252     to work under at least NetBSD/pmax and OpenBSD/pmax under DECstation 5000/200
253     emulation (-E dec -e 3max):
254    
255     <p>
256     <ul>
257     <li>ARP requests sent out from the emulated NIC are interpreted,
258     and converted to ARP responses. (This is used by the emulated OS
259     to find out the MAC address of the gateway.)
260     <li>ICMP echo requests (that is the kind of packet produced by the
261 dpavlin 6 <b><tt>ping</tt></b> program) are interpreted and converted to ICMP echo
262 dpavlin 2 replies, <i>regardless of the IP address</i>. This means that
263     running ping from within the emulated OS will <i>always</i>
264     receive a response. The ping packets never leave the emulated
265     environment.
266     <li>UDP packets are interpreted and passed along to the outside world.
267     If the emulator receives an UDP packet from the outside world, it
268     is converted into an UDP packet for the emulated OS. (This is not
269     implemented very well yet, but seems to be enough for nameserver
270     lookups, tftp file transfers, and NFS mounts using UDP.)
271     <li>TCP packets are interpreted one at a time, similar to how UDP
272     packets are handled (but more state is kept for each connection).
273     <font color="#ff0000">NOTE: Much of the TCP handling code is very
274     ugly and hardcoded.</font>
275 dpavlin 6 <!--
276 dpavlin 2 <li>RARP is not implemented yet. (I haven't needed it so far.)
277 dpavlin 6 -->
278 dpavlin 2 </ul>
279    
280 dpavlin 6 <p>
281 dpavlin 2 The gateway machine, which is the only "other" machine that the emulated
282     OS sees on its emulated network, works as a NAT-style firewall/gateway. It
283 dpavlin 6 usually has a fixed IPv4 address of <tt>10.0.0.254</tt>. An OS running in
284     the emulator would usually have an address of the form <tt>10.x.x.x</tt>;
285     a typical choice would be <tt>10.0.0.1</tt>.
286 dpavlin 2
287     <p>
288 dpavlin 6 Inside emulated NetBSD/pmax or OpenBSD/pmax, running the following
289     commands should configure the emulated NIC:
290 dpavlin 2 <pre>
291     # <b>ifconfig le0 10.0.0.1</b>
292     # <b>route add default 10.0.0.254</b>
293     add net default: gateway 10.0.0.254
294     </pre>
295    
296 dpavlin 6 <p>
297 dpavlin 2 If you want nameserver lookups to work, you need a valid /etc/resolv.conf
298     as well:
299     <pre>
300     # <b>echo nameserver 129.16.1.3 > /etc/resolv.conf</b>
301     </pre>
302 dpavlin 6 (But replace <tt>129.16.1.3</tt> with the actual real-world IP address of
303     your nearest nameserver.)
304    
305 dpavlin 2 <p>
306     Now, host lookups should work:
307     <pre>
308     # <b>host -a www.netbsd.org</b>
309     Trying null domain
310     rcode = 0 (Success), ancount=2
311     The following answer is not authoritative:
312     The following answer is not verified as authentic by the server:
313     www.netbsd.org 86400 IN AAAA 2001:4f8:4:7:290:27ff:feab:19a7
314     www.netbsd.org 86400 IN A 204.152.184.116
315     For authoritative answers, see:
316     netbsd.org 83627 IN NS uucp-gw-2.pa.dec.com
317     netbsd.org 83627 IN NS ns.netbsd.org
318     netbsd.org 83627 IN NS adns1.berkeley.edu
319     netbsd.org 83627 IN NS adns2.berkeley.edu
320     netbsd.org 83627 IN NS uucp-gw-1.pa.dec.com
321     Additional information:
322     ns.netbsd.org 83627 IN A 204.152.184.164
323     uucp-gw-1.pa.dec.com 172799 IN A 204.123.2.18
324     uucp-gw-2.pa.dec.com 172799 IN A 204.123.2.19
325     </pre>
326    
327 dpavlin 6 <p>
328     At this point, UDP and TCP should (mostly) work.
329 dpavlin 2
330 dpavlin 6 <p>
331     Here is an example of how to configure a server machine and an emulated
332     client machine for sharing files via NFS:
333 dpavlin 2
334 dpavlin 6 <p>
335     (This is very useful if you want to share entire directory trees
336     between the emulated environment and another machine. These instruction
337     will work for FreeBSD, if you are running something else, use your
338     imagination to modify them.)
339 dpavlin 2
340     <p>
341     <ul>
342     <li>On the server, add a line to your /etc/exports file, exporting
343     the files you wish to use in the emulator:<pre>
344     <b>/tftpboot -mapall=nobody -ro 123.11.22.33</b>
345     </pre>
346     where 123.11.22.33 is the IP address of the machine running the
347     emulator process, as seen from the outside world.
348     <p>
349     <li>Then start up the programs needed to serve NFS via UDP. Note the
350     -n argument to mountd. This is needed to tell mountd to accept
351     connections from unprivileged ports (because the emulator does
352     not need to run as root).<pre>
353     # <b>portmap</b>
354     # <b>nfsd -u</b> &lt;--- u for UDP
355     # <b>mountd -n</b>
356     </pre>
357     <li>In the guest OS in the emulator, once you have ethernet and IPv4
358     configured so that you can use UDP, mounting the filesystem
359     should now be possible: (this example is for NetBSD/pmax
360     or OpenBSD/pmax)<pre>
361     # <b>mount -o ro,-r=1024,-w=1024,-U,-3 my.server.com:/tftpboot /mnt</b>
362     or
363     # <b>mount my.server.com:/tftpboot /mnt</b>
364     </pre>
365     If you don't supply the read and write sizes, there is a risk
366     that the default values are too large. The emulator currently
367     does not handle fragmentation/defragmentation of <i>outgoing</i>
368     packets, so going above the ethernet frame size (1518) is a very
369     bad idea. Incoming packets (reading from nfs) should work, though,
370     for example during an NFS install.
371     </ul>
372    
373     The example above uses read-only mounts. That is enough for things like
374     letting NetBSD/pmax or OpenBSD/pmax install via NFS, without the need for
375     a CDROM ISO image. You can use a read-write mount if you wish to share
376     files in both directions, but then you should be aware of the
377     fragmentation issue mentioned above.
378    
379    
380    
381    
382    
383     <p><br>
384     <a name="devices"></a>
385     <h3>Emulation of hardware devices</h3>
386    
387     Each file in the device/ directory is responsible for one hardware device.
388     These are used from src/machine.c, when initializing which hardware a
389     particular machine model will be using, or when adding devices to a
390     machine using the <b>device()</b> command in configuration files.
391    
392     <p>
393     <font color="#ff0000">NOTE: 2005-02-26: I'm currently rewriting the
394     device registry subsystem.</font>
395    
396     <p>
397     (I'll be using the name 'foo' as the name of the device in all these
398     examples. This is pseudo code, it might need some modification to
399     actually compile and run.)
400    
401     <p>
402     Each device should have the following:
403    
404     <p>
405     <ul>
406     <li>A devinit function in dev_foo.c. It would typically look
407     something like this:
408     <pre>
409     /*
410     * devinit_foo():
411     */
412     int devinit_foo(struct devinit *devinit)
413     {
414     struct foo_data *d = malloc(sizeof(struct foo_data));
415    
416     if (d == NULL) {
417     fprintf(stderr, "out of memory\n");
418     exit(1);
419     }
420     memset(d, 0, sizeof(struct foon_data));
421    
422     /*
423     * Set up stuff here, for example fill d with useful
424     * data. devinit contains settings like address, irq_nr,
425     * and other things.
426     *
427     * ...
428     */
429    
430     memory_device_register(devinit->machine->memory, devinit->name,
431     devinit->addr, DEV_FOO_LENGTH,
432     dev_foo_access, (void *)d, MEM_DEFAULT, NULL);
433    
434     /* This should only be here if the device
435     has a tick function: */
436     machine_add_tickfunction(machine, dev_foo_tick, d,
437     FOO_TICKSHIFT);
438    
439     /* Return 1 if the device was successfully added. */
440     return 1;
441     }
442     </pre><br>
443    
444     <li>At the top of dev_foo.c, the foo_data struct should be defined.
445     <pre>
446     struct foo_data {
447     int irq_nr;
448     /* ... */
449     }
450     </pre><br>
451    
452     <li>If foo has a tick function (that is, something that needs to be
453     run at regular intervals) then FOO_TICKSHIFT and a tick function
454     need to be defined as well:
455     <pre>
456     #define FOO_TICKSHIFT 10
457    
458     void dev_foo_tick(struct cpu *cpu, void *extra)
459     {
460     struct foo_data *d = (struct foo_data *) extra;
461    
462     if (.....)
463     cpu_interrupt(cpu, d->irq_nr);
464     else
465     cpu_interrupt_ack(cpu, d->irq_nr);
466     }
467     </pre><br>
468    
469     <li>And last but not least, the device should have an access function.
470     The access function is called whenever there is a load or store
471     to an address which is in the device' memory mapped region.
472     <pre>
473     int dev_foo_access(struct cpu *cpu, struct memory *mem,
474     uint64_t relative_addr, unsigned char *data, size_t len,
475     int writeflag, void *extra)
476     {
477     struct foo_data *d = extra;
478     uint64_t idata = 0, odata = 0;
479    
480     idata = memory_readmax64(cpu, data, len);
481     switch (relative_addr) {
482     /* .... */
483     }
484    
485     if (writeflag == MEM_READ)
486     memory_writemax64(cpu, data, len, odata);
487    
488     /* Perhaps interrupts need to be asserted or
489     deasserted: */
490     dev_foo_tick(cpu, extra);
491    
492     /* Return successfully. */
493     return 1;
494     }
495     </pre><br>
496     </ul>
497    
498     <p>
499 dpavlin 6 The return value of the access function has until 2004-07-02 been a
500 dpavlin 2 true/false value; 1 for success, or 0 for device access failure. A device
501     access failure (on MIPS) will result in a DBE exception.
502    
503     <p>
504     Some devices are converted to support arbitrary memory latency
505     values. The return value is the number of cycles that the read or
506     write access took. A value of 1 means one cycle, a value of 10 means 10
507     cycles. Negative values are used for device access failures, and the
508     absolute value of the value is then the number of cycles; a value of -5
509     means that the access failed, and took 5 cycles.
510    
511     <p>
512     To be compatible with pre-20040702 devices, a return value of 0 is treated
513 dpavlin 6 by the caller (in <tt>src/memory_rw.c</tt>) as a value of -1.
514 dpavlin 2
515    
516    
517    
518    
519     <p><br>
520     <a name="regtest"></a>
521     <h3>Regression tests</h3>
522    
523     In order to make sure that the emulator actually works like it is supposed
524     to, it must be tested. For this purpose, there is a simple regression
525 dpavlin 6 testing framework in the <tt>tests/</tt> directory.
526 dpavlin 2
527     <p>
528     <i>NOTE: The regression testing framework is basically just a skeleton so far.
529     Regression tests are very good to have. However, the fact that complete
530     operating systems can run in the emulator indicate that the emulation is
531     probably not too incorrect. This makes it less of a priority to write
532     regression tests.</i>
533    
534     <p>
535 dpavlin 6 To run all the regression tests, type <tt>make regtest</tt>. Each assembly
536     language file matching the pattern <tt>test_*.S</tt> will be compiled and
537 dpavlin 2 linked into a 64-bit MIPS ELF (using a gcc cross compiler), and run in the
538     emulator. If everything goes well, you should see something like this:
539    
540     <pre>
541     $ make regtest
542     cd tests; make run_tests; cd ..
543     gcc33 -Wall -fomit-frame-pointer -fmove-all-movables -fpeephole -O2
544     -mcpu=ev5 -I/usr/X11R6/include -lm -L/usr/X11R6/lib -lX11 do_tests.c
545     -o do_tests
546     do_tests.c: In function `main':
547     do_tests.c:173: warning: unused variable `s'
548     /var/tmp//ccFOupvD.o: In function `do_tests':
549     /var/tmp//ccFOupvD.o(.text+0x3a8): warning: tmpnam() possibly used
550     unsafely; consider using mkstemp()
551     mips64-unknown-elf-gcc -g -O3 -fno-builtin -fschedule-insns -mips64
552     -mabi=64 test_common.c -c -o test_common.o
553     ./do_tests "mips64-unknown-elf-gcc -g -O3 -fno-builtin -fschedule-insns
554     -mips64 -mabi=64" "mips64-unknown-elf-as -mabi=64 -mips64"
555     "mips64-unknown-elf-ld -Ttext 0xa800000000030000 -e main
556     --oformat=elf64-bigmips" "../gxemul"
557    
558     Starting tests:
559     test_addu.S (-a)
560     test_addu.S (-a -b)
561     test_clo_clz.S (-a)
562     test_clo_clz.S (-a -b)
563     ..
564     test_unaligned.S (-a)
565     test_unaligned.S (-a -b)
566    
567     Done. (12 tests done)
568     PASS: 12
569     FAIL: 0
570    
571     ----------------
572    
573     All tests OK
574    
575     ----------------
576     </pre>
577    
578     <p>
579 dpavlin 6 Each test writes output to stdout, and there is a <tt>test_*.good</tt> for
580     each <tt>.S</tt> file which contains the wanted output. If the actual
581     output matches the <tt>.good</tt> file, then the test passes, otherwise it
582     fails.
583 dpavlin 2
584     <p>
585 dpavlin 6 Read <tt>tests/README</tt> for more information.
586 dpavlin 2
587    
588    
589    
590     </body>
591     </html>

  ViewVC Help
Powered by ViewVC 1.1.26