/[gxemul]/trunk/src/interrupt.c
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/src/interrupt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 8003 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

1 dpavlin 34 /*
2     * Copyright (C) 2006-2007 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 dpavlin 44 * $Id: interrupt.c,v 1.13 2007/08/29 20:36:49 debug Exp $
29 dpavlin 34 *
30     * The interrupt subsystem.
31     *
32 dpavlin 44 * Interrupts have a "path", e.g. "machine[0].cpu.5". A device which
33 dpavlin 34 * wishes to cause this interrupt needs to connect to it.
34     *
35     * The possible interrupt paths are registered by CPUs, interrupt controllers,
36     * etc., that have a way of receiving interrupt requests. The physical
37     * version of an interrupt path is usually a "pin" on the CPU, or similar.
38     *
39     * Once connected, the interrupt can be asserted or deasserted.
40     *
41     * For examples on how it is used, see the various devices in src/devices/.
42     */
43    
44     #include <stdio.h>
45     #include <stdlib.h>
46     #include <string.h>
47    
48     #include "interrupt.h"
49     #include "misc.h"
50    
51    
52 dpavlin 42 /* #define INTERRUPT_DEBUG */
53    
54    
55 dpavlin 34 struct interrupt_handler {
56     struct interrupt template;
57     int nr_of_exclusive_users;
58     int nr_of_nonexclusive_users;
59     };
60    
61    
62     static int nr_of_interrupt_handlers = 0;
63     static struct interrupt_handler *interrupt_handlers = NULL;
64    
65    
66     /*
67     * Dummy interrupt assert/deassert for "no interrupt" interrupts:
68     */
69     static void no_interrupt_assert(struct interrupt *i) { }
70     static void no_interrupt_deassert(struct interrupt *i) { }
71    
72    
73     /*
74     * interrupt_handler_register():
75     *
76     * Add an interrupt handler to the interrupt subsystem. The 'template'
77     * needs to have all members set.
78     *
79 dpavlin 44 * Name is of the form "machine[0].cpu[0].irq[3].isa[14]" etc.
80 dpavlin 34 *
81     * If there already is a handler with this name, the emulator aborts.
82     */
83     void interrupt_handler_register(struct interrupt *template)
84     {
85     int i;
86    
87 dpavlin 42 #ifdef INTERRUPT_DEBUG
88 dpavlin 34 printf("interrupt_handler_register(\"%s\")\n", template->name);
89     #endif
90    
91     /* See if the name is already registered: */
92     for (i=0; i<nr_of_interrupt_handlers; i++) {
93     if (strcmp(template->name,
94     interrupt_handlers[i].template.name) != 0)
95     continue;
96    
97     fatal("\ninterrupt_handler_register(): An interrupt handler"
98     " using the name '%s' is already registered.\n",
99     template->name);
100     exit(1);
101     }
102    
103     nr_of_interrupt_handlers ++;
104 dpavlin 42 CHECK_ALLOCATION(interrupt_handlers = realloc(interrupt_handlers,
105     nr_of_interrupt_handlers * sizeof(struct interrupt_handler)));
106 dpavlin 34
107     interrupt_handlers[nr_of_interrupt_handlers-1].template = *template;
108 dpavlin 42 CHECK_ALLOCATION(interrupt_handlers[nr_of_interrupt_handlers-1].
109     template.name = strdup(template->name));
110 dpavlin 34 }
111    
112    
113     /*
114     * interrupt_handler_remove():
115     *
116     * Remove an interrupt handler from the interrupt subsystem. If there are
117     * still connected users of this interrupt, then an error message is printed
118     * and the emulator aborts.
119     */
120     void interrupt_handler_remove(char *name)
121     {
122     int i;
123    
124 dpavlin 42 #ifdef INTERRUPT_DEBUG
125 dpavlin 34 printf("interrupt_handler_remove(\"%s\")\n", name);
126     #endif
127    
128     for (i=0; i<nr_of_interrupt_handlers; i++) {
129     if (strcmp(name, interrupt_handlers[i].template.name) != 0)
130     continue;
131    
132     /*
133     * Remove handler i, and return:
134     */
135     if (interrupt_handlers[i].nr_of_exclusive_users > 0 ||
136     interrupt_handlers[i].nr_of_nonexclusive_users > 0) {
137     fatal("interrupt_handler_remove(): Attempt to "
138     "remove interrupt handler '%s' which has %i "
139     "exclusive and %i non-exclusive users. Aborting.\n",
140     name, interrupt_handlers[i].nr_of_exclusive_users,
141     interrupt_handlers[i].nr_of_nonexclusive_users);
142     exit(1);
143     }
144    
145     if (i != nr_of_interrupt_handlers-1)
146     memcpy(&interrupt_handlers[i],
147     &interrupt_handlers[i + 1],
148     nr_of_interrupt_handlers - i - 1);
149    
150     nr_of_interrupt_handlers --;
151    
152     return;
153     }
154    
155     fatal("interrupt_handler_remove(): '%s' not found? Aborting.\n", name);
156     exit(1);
157     }
158    
159    
160     /*
161     * interrupt_handler_lookup():
162     *
163     * Scans the list of registered interrupt handlers for a given name. If the
164     * name is found, the template is filled with valid data, and 1 is returned.
165     * If the name is not found, 0 is returned.
166     */
167     int interrupt_handler_lookup(char *name, struct interrupt *template)
168     {
169     int i;
170    
171 dpavlin 42 #ifdef INTERRUPT_DEBUG
172 dpavlin 34 printf("interrupt_handler_lookup(\"%s\")\n", name);
173     #endif
174    
175     if (name[0] == '\0') {
176     /* No interrupt: */
177     memset(template, 0, sizeof(struct interrupt));
178     template->interrupt_assert = no_interrupt_assert;
179     template->interrupt_deassert = no_interrupt_deassert;
180     }
181    
182     for (i=0; i<nr_of_interrupt_handlers; i++) {
183     if (strcmp(name, interrupt_handlers[i].template.name) != 0)
184     continue;
185    
186     *template = interrupt_handlers[i].template;
187     return 1;
188     }
189    
190 dpavlin 42 /* The 'if' is an ugly hack to prevent a Compaq CC warning. */
191     if (i >= nr_of_interrupt_handlers) {
192     printf("interrupt_handler_lookup(\"%s\") failed. "
193     "Aborting.\n", name);
194     abort();
195     }
196 dpavlin 34
197     return 0;
198     }
199    
200    
201     /*
202     * interrupt_connect():
203     *
204     * Increases the exclusive or nonexclusive nr or users of an interrupt.
205     */
206     void interrupt_connect(struct interrupt *in, int exclusive)
207     {
208     int i;
209    
210 dpavlin 42 #ifdef INTERRUPT_DEBUG
211 dpavlin 34 printf("interrupt_connect(\"%s\")\n", in->name);
212     #endif
213    
214     if (in->name == NULL || in->name[0] == '\0')
215     return;
216    
217     for (i=0; i<nr_of_interrupt_handlers; i++) {
218     if (strcmp(in->name, interrupt_handlers[i].template.name) != 0)
219     continue;
220    
221     if (exclusive) {
222     interrupt_handlers[i].nr_of_exclusive_users ++;
223     if (interrupt_handlers[i].nr_of_exclusive_users > 1) {
224     fatal("Fatal error in interrupt_connect(): "
225     "more than 1 exclusive user. Dumping "
226     "core for backtrace.\n");
227     abort();
228     }
229     } else {
230     interrupt_handlers[i].nr_of_nonexclusive_users ++;
231     }
232    
233     return;
234     }
235    
236     fatal("Internal error in interrupt_connect(): name '%s' not "
237     "found? Dumping core for debugging.\n", in->name);
238     abort();
239     }
240    
241    
242     /*
243     * interrupt_disconnect():
244     *
245     * Decreases the exclusive or nonexclusive nr or users of an interrupt.
246     */
247     void interrupt_disconnect(struct interrupt *in, int exclusive)
248     {
249     int i;
250    
251     if (in->name == NULL || in->name[0] == '\0')
252     return;
253    
254     for (i=0; i<nr_of_interrupt_handlers; i++) {
255     if (strcmp(in->name, interrupt_handlers[i].template.name) != 0)
256     continue;
257    
258     if (exclusive) {
259     interrupt_handlers[i].nr_of_exclusive_users --;
260     if (interrupt_handlers[i].nr_of_exclusive_users < 0) {
261     fatal("Fatal error in interrupt_disconnect():"
262     "nr of exclusive users < 0?\n");
263     exit(1);
264     }
265     } else {
266     interrupt_handlers[i].nr_of_nonexclusive_users --;
267     if (interrupt_handlers[i].nr_of_nonexclusive_users<0) {
268     fatal("Fatal error in interrupt_disconnect():"
269     "nr of non-exclusive users < 0?\n");
270     exit(1);
271     }
272     }
273    
274     return;
275     }
276    
277     fatal("Internal error in interrupt_disconnect(): name '%s' not "
278     "found?\n", in->name);
279     exit(1);
280     }
281    
282    

  ViewVC Help
Powered by ViewVC 1.1.26