~galfy/helenos/bird-port-mainline

« back to all changes in this revision

Viewing changes to kernel/arch/ia64/src/interrupt.c

  • Committer: Martin Decky
  • Date: 2009-08-04 11:19:19 UTC
  • Revision ID: martin@uranus.dsrg.hide.ms.mff.cuni.cz-20090804111919-evyclddlr3v5lhmp
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2005 Jakub Jermar
 
3
 * Copyright (c) 2005 Jakub Vana
 
4
 * All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions
 
8
 * are met:
 
9
 *
 
10
 * - Redistributions of source code must retain the above copyright
 
11
 *   notice, this list of conditions and the following disclaimer.
 
12
 * - Redistributions in binary form must reproduce the above copyright
 
13
 *   notice, this list of conditions and the following disclaimer in the
 
14
 *   documentation and/or other materials provided with the distribution.
 
15
 * - The name of the author may not be used to endorse or promote products
 
16
 *   derived from this software without specific prior written permission.
 
17
 *
 
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 
19
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
20
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
21
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 
22
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
23
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
24
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
25
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
27
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
28
 */
 
29
 
 
30
/** @addtogroup ia64interrupt
 
31
 * @{
 
32
 */
 
33
/** @file
 
34
 */
 
35
 
 
36
#include <arch/interrupt.h>
 
37
#include <interrupt.h>
 
38
#include <ddi/irq.h>
 
39
#include <panic.h>
 
40
#include <print.h>
 
41
#include <debug.h>
 
42
#include <console/console.h>
 
43
#include <arch/types.h>
 
44
#include <arch/asm.h>
 
45
#include <arch/barrier.h>
 
46
#include <arch/register.h>
 
47
#include <arch.h>
 
48
#include <syscall/syscall.h>
 
49
#include <print.h>
 
50
#include <proc/scheduler.h>
 
51
#include <ipc/sysipc.h>
 
52
#include <ipc/irq.h>
 
53
#include <ipc/ipc.h>
 
54
#include <synch/spinlock.h>
 
55
#include <mm/tlb.h>
 
56
#include <symtab.h>
 
57
#include <putchar.h>
 
58
 
 
59
#define VECTORS_64_BUNDLE       20
 
60
#define VECTORS_16_BUNDLE       48
 
61
#define VECTORS_16_BUNDLE_START 0x5000
 
62
#define VECTOR_MAX              0x7f00
 
63
 
 
64
#define BUNDLE_SIZE             16
 
65
 
 
66
char *vector_names_64_bundle[VECTORS_64_BUNDLE] = {
 
67
        "VHPT Translation vector",
 
68
        "Instruction TLB vector",
 
69
        "Data TLB vector",
 
70
        "Alternate Instruction TLB vector",
 
71
        "Alternate Data TLB vector",
 
72
        "Data Nested TLB vector",
 
73
        "Instruction Key Miss vector",
 
74
        "Data Key Miss vector",
 
75
        "Dirty-Bit vector",
 
76
        "Instruction Access-Bit vector",
 
77
        "Data Access-Bit vector"
 
78
        "Break Instruction vector",
 
79
        "External Interrupt vector"
 
80
        "Reserved",
 
81
        "Reserved",
 
82
        "Reserved",
 
83
        "Reserved",
 
84
        "Reserved",
 
85
        "Reserved",
 
86
        "Reserved"
 
87
};
 
88
 
 
89
char *vector_names_16_bundle[VECTORS_16_BUNDLE] = {
 
90
        "Page Not Present vector",
 
91
        "Key Permission vector",
 
92
        "Instruction Access rights vector",
 
93
        "Data Access Rights vector",
 
94
        "General Exception vector",
 
95
        "Disabled FP-Register vector",
 
96
        "NaT Consumption vector",
 
97
        "Speculation vector",
 
98
        "Reserved",
 
99
        "Debug vector",
 
100
        "Unaligned Reference vector",
 
101
        "Unsupported Data Reference vector",
 
102
        "Floating-point Fault vector",
 
103
        "Floating-point Trap vector",
 
104
        "Lower-Privilege Transfer Trap vector",
 
105
        "Taken Branch Trap vector",
 
106
        "Single Step Trap vector",
 
107
        "Reserved",
 
108
        "Reserved",
 
109
        "Reserved",
 
110
        "Reserved",
 
111
        "Reserved",
 
112
        "Reserved",
 
113
        "Reserved",
 
114
        "Reserved",
 
115
        "IA-32 Exception vector",
 
116
        "IA-32 Intercept vector",
 
117
        "IA-32 Interrupt vector",
 
118
        "Reserved",
 
119
        "Reserved",
 
120
        "Reserved"
 
121
};
 
122
 
 
123
static char *vector_to_string(uint16_t vector);
 
124
static void dump_interrupted_context(istate_t *istate);
 
125
 
 
126
char *vector_to_string(uint16_t vector)
 
127
{
 
128
        ASSERT(vector <= VECTOR_MAX);
 
129
        
 
130
        if (vector >= VECTORS_16_BUNDLE_START)
 
131
                return vector_names_16_bundle[(vector -
 
132
                    VECTORS_16_BUNDLE_START) / (16 * BUNDLE_SIZE)];
 
133
        else
 
134
                return vector_names_64_bundle[vector / (64 * BUNDLE_SIZE)];
 
135
}
 
136
 
 
137
void dump_interrupted_context(istate_t *istate)
 
138
{
 
139
        char *ifa, *iipa, *iip;
 
140
 
 
141
        ifa = symtab_fmt_name_lookup(istate->cr_ifa);
 
142
        iipa = symtab_fmt_name_lookup(istate->cr_iipa);
 
143
        iip = symtab_fmt_name_lookup(istate->cr_iip);
 
144
 
 
145
        putchar('\n');
 
146
        printf("Interrupted context dump:\n");
 
147
        printf("ar.bsp=%p\tar.bspstore=%p\n", istate->ar_bsp,
 
148
            istate->ar_bspstore);
 
149
        printf("ar.rnat=%#018llx\tar.rsc=%#018llx\n", istate->ar_rnat,
 
150
            istate->ar_rsc);
 
151
        printf("ar.ifs=%#018llx\tar.pfs=%#018llx\n", istate->ar_ifs,
 
152
            istate->ar_pfs);
 
153
        printf("cr.isr=%#018llx\tcr.ipsr=%#018llx\t\n", istate->cr_isr.value,
 
154
            istate->cr_ipsr);
 
155
        
 
156
        printf("cr.iip=%#018llx, #%d\t(%s)\n", istate->cr_iip,
 
157
            istate->cr_isr.ei, iip);
 
158
        printf("cr.iipa=%#018llx\t(%s)\n", istate->cr_iipa, iipa);
 
159
        printf("cr.ifa=%#018llx\t(%s)\n", istate->cr_ifa, ifa);
 
160
}
 
161
 
 
162
void general_exception(uint64_t vector, istate_t *istate)
 
163
{
 
164
        char *desc = "";
 
165
 
 
166
        switch (istate->cr_isr.ge_code) {
 
167
        case GE_ILLEGALOP:
 
168
                desc = "Illegal Operation fault";
 
169
                break;
 
170
        case GE_PRIVOP:
 
171
                desc = "Privileged Operation fault";
 
172
                break;
 
173
        case GE_PRIVREG:
 
174
                desc = "Privileged Register fault";
 
175
                break;
 
176
        case GE_RESREGFLD:
 
177
                desc = "Reserved Register/Field fault";
 
178
                break;
 
179
        case GE_DISBLDISTRAN:
 
180
                desc = "Disabled Instruction Set Transition fault";
 
181
                break;
 
182
        case GE_ILLEGALDEP:
 
183
                desc = "Illegal Dependency fault";
 
184
                break;
 
185
        default:
 
186
                desc = "unknown";
 
187
                break;
 
188
        }
 
189
 
 
190
        fault_if_from_uspace(istate, "General Exception (%s).", desc);
 
191
 
 
192
        dump_interrupted_context(istate);
 
193
        panic("General Exception (%s).", desc);
 
194
}
 
195
 
 
196
void disabled_fp_register(uint64_t vector, istate_t *istate)
 
197
{
 
198
#ifdef CONFIG_FPU_LAZY
 
199
        scheduler_fpu_lazy_request();
 
200
#else
 
201
        fault_if_from_uspace(istate, "Interruption: %#hx (%s).",
 
202
            (uint16_t) vector, vector_to_string(vector));
 
203
        dump_interrupted_context(istate);
 
204
        panic("Interruption: %#hx (%s).", (uint16_t) vector,
 
205
            vector_to_string(vector));
 
206
#endif
 
207
}
 
208
 
 
209
void nop_handler(uint64_t vector, istate_t *istate)
 
210
{
 
211
}
 
212
 
 
213
/** Handle syscall. */
 
214
int break_instruction(uint64_t vector, istate_t *istate)
 
215
{
 
216
        /*
 
217
         * Move to next instruction after BREAK.
 
218
         */
 
219
        if (istate->cr_ipsr.ri == 2) {
 
220
                istate->cr_ipsr.ri = 0;
 
221
                istate->cr_iip += 16;
 
222
        } else {
 
223
                istate->cr_ipsr.ri++;
 
224
        }
 
225
 
 
226
        return syscall_handler(istate->in0, istate->in1, istate->in2,
 
227
            istate->in3, istate->in4, istate->in5, istate->in6);
 
228
}
 
229
 
 
230
void universal_handler(uint64_t vector, istate_t *istate)
 
231
{
 
232
        fault_if_from_uspace(istate, "Interruption: %#hx (%s).",
 
233
            (uint16_t) vector, vector_to_string(vector));
 
234
        dump_interrupted_context(istate);
 
235
        panic("Interruption: %#hx (%s).", (uint16_t) vector,
 
236
            vector_to_string(vector));
 
237
}
 
238
 
 
239
static void end_of_local_irq(void)
 
240
{
 
241
        asm volatile ("mov cr.eoi=r0;;");
 
242
}
 
243
 
 
244
 
 
245
void external_interrupt(uint64_t vector, istate_t *istate)
 
246
{
 
247
        cr_ivr_t ivr;
 
248
        irq_t *irq;
 
249
        
 
250
        ivr.value = ivr_read();
 
251
        srlz_d();
 
252
 
 
253
        switch (ivr.vector) {
 
254
        case INTERRUPT_SPURIOUS:
 
255
#ifdef CONFIG_DEBUG
 
256
                printf("cpu%d: spurious interrupt\n", CPU->id);
 
257
#endif
 
258
                break;
 
259
 
 
260
#ifdef CONFIG_SMP
 
261
        case VECTOR_TLB_SHOOTDOWN_IPI:
 
262
                tlb_shootdown_ipi_recv();
 
263
                end_of_local_irq();
 
264
                break;
 
265
#endif
 
266
 
 
267
        case INTERRUPT_TIMER:
 
268
                irq = irq_dispatch_and_lock(ivr.vector);
 
269
                if (irq) {
 
270
                        irq->handler(irq);
 
271
                        spinlock_unlock(&irq->lock);
 
272
                } else {
 
273
                        panic("Unhandled Internal Timer Interrupt (%d).",
 
274
                            ivr.vector);
 
275
                }
 
276
                break;
 
277
        default:
 
278
                irq = irq_dispatch_and_lock(ivr.vector);
 
279
                if (irq) {
 
280
                        /*
 
281
                         * The IRQ handler was found.
 
282
                         */
 
283
                        if (irq->preack) {
 
284
                                /* Send EOI before processing the interrupt */
 
285
                                end_of_local_irq();
 
286
                        }
 
287
                        irq->handler(irq);
 
288
                        if (!irq->preack)
 
289
                                end_of_local_irq();
 
290
                        spinlock_unlock(&irq->lock);
 
291
                } else {
 
292
                        /*
 
293
                         * Unhandled interrupt.
 
294
                         */
 
295
                        end_of_local_irq();
 
296
#ifdef CONFIG_DEBUG
 
297
                        printf("\nUnhandled External Interrupt Vector %d\n",
 
298
                            ivr.vector);
 
299
#endif
 
300
                }
 
301
                break;
 
302
        }
 
303
}
 
304
 
 
305
void trap_virtual_enable_irqs(uint16_t irqmask)
 
306
{
 
307
}
 
308
 
 
309
/** @}
 
310
 */