Subversion Repositories HelenOS

Rev

Rev 1936 | Rev 2089 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1936 Rev 2071
1
/*
1
/*
2
 * Copyright (C) 2003-2004 Jakub Jermar
2
 * Copyright (c) 2003-2004 Jakub Jermar
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
7
 * are met:
7
 * are met:
8
 *
8
 *
9
 * - Redistributions of source code must retain the above copyright
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
15
 *   derived from this software without specific prior written permission.
16
 *
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
27
 */
28
 
28
 
29
/** @addtogroup mips32 
29
/** @addtogroup mips32 
30
 * @{
30
 * @{
31
 */
31
 */
32
/** @file
32
/** @file
33
 */
33
 */
34
 
34
 
35
#include <arch/exception.h>
35
#include <arch/exception.h>
36
#include <arch/interrupt.h>
36
#include <arch/interrupt.h>
37
#include <panic.h>
37
#include <panic.h>
38
#include <arch/cp0.h>
38
#include <arch/cp0.h>
39
#include <arch/types.h>
39
#include <arch/types.h>
40
#include <arch.h>
40
#include <arch.h>
41
#include <debug.h>
41
#include <debug.h>
42
#include <proc/thread.h>
42
#include <proc/thread.h>
43
#include <symtab.h>
43
#include <symtab.h>
44
#include <print.h>
44
#include <print.h>
45
#include <interrupt.h>
45
#include <interrupt.h>
46
#include <func.h>
46
#include <func.h>
47
#include <console/kconsole.h>
47
#include <console/kconsole.h>
48
#include <ddi/irq.h>
48
#include <ddi/irq.h>
49
#include <arch/debugger.h>
49
#include <arch/debugger.h>
50
 
50
 
51
static char * exctable[] = {
51
static char * exctable[] = {
52
    "Interrupt",
52
    "Interrupt",
53
    "TLB Modified",
53
    "TLB Modified",
54
    "TLB Invalid",
54
    "TLB Invalid",
55
    "TLB Invalid Store",
55
    "TLB Invalid Store",
56
    "Address Error - load/instr. fetch",
56
    "Address Error - load/instr. fetch",
57
    "Address Error - store",
57
    "Address Error - store",
58
    "Bus Error - fetch instruction",
58
    "Bus Error - fetch instruction",
59
    "Bus Error - data reference",
59
    "Bus Error - data reference",
60
    "Syscall",
60
    "Syscall",
61
    "BreakPoint",
61
    "BreakPoint",
62
    "Reserved Instruction",
62
    "Reserved Instruction",
63
    "Coprocessor Unusable",
63
    "Coprocessor Unusable",
64
    "Arithmetic Overflow",
64
    "Arithmetic Overflow",
65
    "Trap",
65
    "Trap",
66
    "Virtual Coherency - instruction",
66
    "Virtual Coherency - instruction",
67
    "Floating Point",
67
    "Floating Point",
68
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
68
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
69
    "WatchHi/WatchLo", /* 23 */
69
    "WatchHi/WatchLo", /* 23 */
70
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
70
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
71
    "Virtual Coherency - data",
71
    "Virtual Coherency - data",
72
};
72
};
73
 
73
 
74
static void print_regdump(istate_t *istate)
74
static void print_regdump(istate_t *istate)
75
{
75
{
76
    char *pcsymbol = "";
76
    char *pcsymbol = "";
77
    char *rasymbol = "";
77
    char *rasymbol = "";
78
 
78
 
79
    char *s = get_symtab_entry(istate->epc);
79
    char *s = get_symtab_entry(istate->epc);
80
    if (s)
80
    if (s)
81
        pcsymbol = s;
81
        pcsymbol = s;
82
    s = get_symtab_entry(istate->ra);
82
    s = get_symtab_entry(istate->ra);
83
    if (s)
83
    if (s)
84
        rasymbol = s;
84
        rasymbol = s;
85
   
85
   
86
    printf("PC: %#x(%s) RA: %#x(%s), SP(%p)\n", istate->epc, pcsymbol, istate->ra, rasymbol, istate->sp);
86
    printf("PC: %#x(%s) RA: %#x(%s), SP(%p)\n", istate->epc, pcsymbol, istate->ra, rasymbol, istate->sp);
87
}
87
}
88
 
88
 
89
static void unhandled_exception(int n, istate_t *istate)
89
static void unhandled_exception(int n, istate_t *istate)
90
{
90
{
91
    fault_if_from_uspace(istate, "unhandled exception %s", exctable[n]);
91
    fault_if_from_uspace(istate, "unhandled exception %s", exctable[n]);
92
   
92
   
93
    print_regdump(istate);
93
    print_regdump(istate);
94
    panic("unhandled exception %s\n", exctable[n]);
94
    panic("unhandled exception %s\n", exctable[n]);
95
}
95
}
96
 
96
 
97
static void reserved_instr_exception(int n, istate_t *istate)
97
static void reserved_instr_exception(int n, istate_t *istate)
98
{
98
{
99
    if (*((uint32_t *)istate->epc) == 0x7c03e83b) {
99
    if (*((uint32_t *)istate->epc) == 0x7c03e83b) {
100
        ASSERT(THREAD);
100
        ASSERT(THREAD);
101
        istate->epc += 4;
101
        istate->epc += 4;
102
        istate->v1 = istate->k1;
102
        istate->v1 = istate->k1;
103
    } else
103
    } else
104
        unhandled_exception(n, istate);
104
        unhandled_exception(n, istate);
105
}
105
}
106
 
106
 
107
static void breakpoint_exception(int n, istate_t *istate)
107
static void breakpoint_exception(int n, istate_t *istate)
108
{
108
{
109
#ifdef CONFIG_DEBUG
109
#ifdef CONFIG_DEBUG
110
    debugger_bpoint(istate);
110
    debugger_bpoint(istate);
111
#else
111
#else
112
    /* it is necessary to not re-execute BREAK instruction after
112
    /* it is necessary to not re-execute BREAK instruction after
113
       returning from Exception handler
113
       returning from Exception handler
114
       (see page 138 in R4000 Manual for more information) */
114
       (see page 138 in R4000 Manual for more information) */
115
    istate->epc += 4;
115
    istate->epc += 4;
116
#endif
116
#endif
117
}
117
}
118
 
118
 
119
static void tlbmod_exception(int n, istate_t *istate)
119
static void tlbmod_exception(int n, istate_t *istate)
120
{
120
{
121
    tlb_modified(istate);
121
    tlb_modified(istate);
122
}
122
}
123
 
123
 
124
static void tlbinv_exception(int n, istate_t *istate)
124
static void tlbinv_exception(int n, istate_t *istate)
125
{
125
{
126
    tlb_invalid(istate);
126
    tlb_invalid(istate);
127
}
127
}
128
 
128
 
129
#ifdef CONFIG_FPU_LAZY
129
#ifdef CONFIG_FPU_LAZY
130
static void cpuns_exception(int n, istate_t *istate)
130
static void cpuns_exception(int n, istate_t *istate)
131
{
131
{
132
    if (cp0_cause_coperr(cp0_cause_read()) == fpu_cop_id)
132
    if (cp0_cause_coperr(cp0_cause_read()) == fpu_cop_id)
133
        scheduler_fpu_lazy_request();
133
        scheduler_fpu_lazy_request();
134
    else {
134
    else {
135
        fault_if_from_uspace(istate, "unhandled Coprocessor Unusable Exception");
135
        fault_if_from_uspace(istate, "unhandled Coprocessor Unusable Exception");
136
        panic("unhandled Coprocessor Unusable Exception\n");
136
        panic("unhandled Coprocessor Unusable Exception\n");
137
    }
137
    }
138
}
138
}
139
#endif
139
#endif
140
 
140
 
141
static void interrupt_exception(int n, istate_t *istate)
141
static void interrupt_exception(int n, istate_t *istate)
142
{
142
{
143
    uint32_t cause;
143
    uint32_t cause;
144
    int i;
144
    int i;
145
   
145
   
146
    /* decode interrupt number and process the interrupt */
146
    /* decode interrupt number and process the interrupt */
147
    cause = (cp0_cause_read() >> 8) &0xff;
147
    cause = (cp0_cause_read() >> 8) &0xff;
148
   
148
   
149
    for (i = 0; i < 8; i++) {
149
    for (i = 0; i < 8; i++) {
150
        if (cause & (1 << i)) {
150
        if (cause & (1 << i)) {
151
            irq_t *irq = irq_dispatch_and_lock(i);
151
            irq_t *irq = irq_dispatch_and_lock(i);
152
            if (irq) {
152
            if (irq) {
153
                /*
153
                /*
154
                 * The IRQ handler was found.
154
                 * The IRQ handler was found.
155
                 */
155
                 */
156
                irq->handler(irq, irq->arg);
156
                irq->handler(irq, irq->arg);
157
                spinlock_unlock(&irq->lock);
157
                spinlock_unlock(&irq->lock);
158
            } else {
158
            } else {
159
                /*
159
                /*
160
                 * Spurious interrupt.
160
                 * Spurious interrupt.
161
                 */
161
                 */
162
#ifdef CONFIG_DEBUG
162
#ifdef CONFIG_DEBUG
163
                printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, i);
163
                printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, i);
164
#endif
164
#endif
165
            }
165
            }
166
        }
166
        }
167
    }
167
    }
168
}
168
}
169
 
169
 
170
/** Handle syscall userspace call */
170
/** Handle syscall userspace call */
171
static void syscall_exception(int n, istate_t *istate)
171
static void syscall_exception(int n, istate_t *istate)
172
{
172
{
173
    panic("Syscall is handled through shortcut");
173
    panic("Syscall is handled through shortcut");
174
}
174
}
175
 
175
 
176
void exception_init(void)
176
void exception_init(void)
177
{
177
{
178
    int i;
178
    int i;
179
 
179
 
180
    /* Clear exception table */
180
    /* Clear exception table */
181
    for (i = 0; i < IVT_ITEMS; i++)
181
    for (i = 0; i < IVT_ITEMS; i++)
182
        exc_register(i, "undef", (iroutine) unhandled_exception);
182
        exc_register(i, "undef", (iroutine) unhandled_exception);
183
   
183
   
184
    exc_register(EXC_Bp, "bkpoint", (iroutine) breakpoint_exception);
184
    exc_register(EXC_Bp, "bkpoint", (iroutine) breakpoint_exception);
185
    exc_register(EXC_RI, "resinstr", (iroutine) reserved_instr_exception);
185
    exc_register(EXC_RI, "resinstr", (iroutine) reserved_instr_exception);
186
    exc_register(EXC_Mod, "tlb_mod", (iroutine) tlbmod_exception);
186
    exc_register(EXC_Mod, "tlb_mod", (iroutine) tlbmod_exception);
187
    exc_register(EXC_TLBL, "tlbinvl", (iroutine) tlbinv_exception);
187
    exc_register(EXC_TLBL, "tlbinvl", (iroutine) tlbinv_exception);
188
    exc_register(EXC_TLBS, "tlbinvl", (iroutine) tlbinv_exception);
188
    exc_register(EXC_TLBS, "tlbinvl", (iroutine) tlbinv_exception);
189
    exc_register(EXC_Int, "interrupt", (iroutine) interrupt_exception);
189
    exc_register(EXC_Int, "interrupt", (iroutine) interrupt_exception);
190
#ifdef CONFIG_FPU_LAZY
190
#ifdef CONFIG_FPU_LAZY
191
    exc_register(EXC_CpU, "cpunus", (iroutine) cpuns_exception);
191
    exc_register(EXC_CpU, "cpunus", (iroutine) cpuns_exception);
192
#endif
192
#endif
193
    exc_register(EXC_Sys, "syscall", (iroutine) syscall_exception);
193
    exc_register(EXC_Sys, "syscall", (iroutine) syscall_exception);
194
}
194
}
195
 
195
 
196
/** @}
196
/** @}
197
 */
197
 */
198
 
198