Subversion Repositories HelenOS

Rev

Rev 2924 | Rev 3431 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2924 Rev 3424
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 <arch/mm/tlb.h>
37
#include <arch/mm/tlb.h>
38
#include <panic.h>
38
#include <panic.h>
39
#include <arch/cp0.h>
39
#include <arch/cp0.h>
40
#include <arch/types.h>
40
#include <arch/types.h>
41
#include <arch.h>
41
#include <arch.h>
42
#include <debug.h>
42
#include <debug.h>
43
#include <proc/thread.h>
43
#include <proc/thread.h>
44
#include <symtab.h>
44
#include <symtab.h>
45
#include <print.h>
45
#include <print.h>
46
#include <interrupt.h>
46
#include <interrupt.h>
47
#include <func.h>
47
#include <func.h>
48
#include <console/kconsole.h>
48
#include <console/kconsole.h>
49
#include <ddi/irq.h>
49
#include <ddi/irq.h>
50
#include <arch/debugger.h>
50
#include <arch/debugger.h>
51
 
51
 
52
static char * exctable[] = {
52
static char * exctable[] = {
53
    "Interrupt",
53
    "Interrupt",
54
    "TLB Modified",
54
    "TLB Modified",
55
    "TLB Invalid",
55
    "TLB Invalid",
56
    "TLB Invalid Store",
56
    "TLB Invalid Store",
57
    "Address Error - load/instr. fetch",
57
    "Address Error - load/instr. fetch",
58
    "Address Error - store",
58
    "Address Error - store",
59
    "Bus Error - fetch instruction",
59
    "Bus Error - fetch instruction",
60
    "Bus Error - data reference",
60
    "Bus Error - data reference",
61
    "Syscall",
61
    "Syscall",
62
    "BreakPoint",
62
    "BreakPoint",
63
    "Reserved Instruction",
63
    "Reserved Instruction",
64
    "Coprocessor Unusable",
64
    "Coprocessor Unusable",
65
    "Arithmetic Overflow",
65
    "Arithmetic Overflow",
66
    "Trap",
66
    "Trap",
67
    "Virtual Coherency - instruction",
67
    "Virtual Coherency - instruction",
68
    "Floating Point",
68
    "Floating Point",
69
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
69
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
70
    "WatchHi/WatchLo", /* 23 */
70
    "WatchHi/WatchLo", /* 23 */
71
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
71
    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
72
    "Virtual Coherency - data",
72
    "Virtual Coherency - data",
73
};
73
};
74
 
74
 
75
static void print_regdump(istate_t *istate)
75
static void print_regdump(istate_t *istate)
76
{
76
{
77
    char *pcsymbol = "";
77
    char *pcsymbol = "";
78
    char *rasymbol = "";
78
    char *rasymbol = "";
79
 
79
 
80
    char *s = get_symtab_entry(istate->epc);
80
    char *s = get_symtab_entry(istate->epc);
81
    if (s)
81
    if (s)
82
        pcsymbol = s;
82
        pcsymbol = s;
83
    s = get_symtab_entry(istate->ra);
83
    s = get_symtab_entry(istate->ra);
84
    if (s)
84
    if (s)
85
        rasymbol = s;
85
        rasymbol = s;
86
   
86
   
87
    printf("PC: %#x(%s) RA: %#x(%s), SP(%p)\n", istate->epc, pcsymbol, istate->ra, rasymbol, istate->sp);
87
    printf("PC: %#x(%s) RA: %#x(%s), SP(%p)\n", istate->epc, pcsymbol, istate->ra, rasymbol, istate->sp);
88
}
88
}
89
 
89
 
90
static void unhandled_exception(int n, istate_t *istate)
90
static void unhandled_exception(int n, istate_t *istate)
91
{
91
{
92
    fault_if_from_uspace(istate, "unhandled exception %s", exctable[n]);
92
    fault_if_from_uspace(istate, "unhandled exception %s", exctable[n]);
93
   
93
   
94
    print_regdump(istate);
94
    print_regdump(istate);
95
    panic("unhandled exception %s\n", exctable[n]);
95
    panic("unhandled exception %s\n", exctable[n]);
96
}
96
}
97
 
97
 
98
static void reserved_instr_exception(int n, istate_t *istate)
98
static void reserved_instr_exception(int n, istate_t *istate)
99
{
99
{
100
    if (*((uint32_t *)istate->epc) == 0x7c03e83b) {
100
    if (*((uint32_t *)istate->epc) == 0x7c03e83b) {
101
        ASSERT(THREAD);
101
        ASSERT(THREAD);
102
        istate->epc += 4;
102
        istate->epc += 4;
103
        istate->v1 = istate->k1;
103
        istate->v1 = istate->k1;
104
    } else
104
    } else
105
        unhandled_exception(n, istate);
105
        unhandled_exception(n, istate);
106
}
106
}
107
 
107
 
108
static void breakpoint_exception(int n, istate_t *istate)
108
static void breakpoint_exception(int n, istate_t *istate)
109
{
109
{
110
    if (istate_from_uspace(istate)) {
110
    if (istate_from_uspace(istate)) {
111
        /* userspace breakpoint */
111
        /* userspace breakpoint */
112
        udebug_breakpoint_event(0);
112
        udebug_breakpoint_event(0);
113
        return;
113
        return;
114
    }
114
    }
115
 
115
 
116
#ifdef CONFIG_DEBUG
116
#ifdef CONFIG_DEBUG
117
    debugger_bpoint(istate);
117
    debugger_bpoint(istate);
118
#else
118
#else
119
    /* it is necessary to not re-execute BREAK instruction after
119
    /* it is necessary to not re-execute BREAK instruction after
120
       returning from Exception handler
120
       returning from Exception handler
121
       (see page 138 in R4000 Manual for more information) */
121
       (see page 138 in R4000 Manual for more information) */
122
    istate->epc += 4;
122
    istate->epc += 4;
123
#endif
123
#endif
124
}
124
}
125
 
125
 
126
static void tlbmod_exception(int n, istate_t *istate)
126
static void tlbmod_exception(int n, istate_t *istate)
127
{
127
{
128
    tlb_modified(istate);
128
    tlb_modified(istate);
129
}
129
}
130
 
130
 
131
static void tlbinv_exception(int n, istate_t *istate)
131
static void tlbinv_exception(int n, istate_t *istate)
132
{
132
{
133
    tlb_invalid(istate);
133
    tlb_invalid(istate);
134
}
134
}
135
 
135
 
136
#ifdef CONFIG_FPU_LAZY
136
#ifdef CONFIG_FPU_LAZY
137
static void cpuns_exception(int n, istate_t *istate)
137
static void cpuns_exception(int n, istate_t *istate)
138
{
138
{
139
    if (cp0_cause_coperr(cp0_cause_read()) == fpu_cop_id)
139
    if (cp0_cause_coperr(cp0_cause_read()) == fpu_cop_id)
140
        scheduler_fpu_lazy_request();
140
        scheduler_fpu_lazy_request();
141
    else {
141
    else {
142
        fault_if_from_uspace(istate, "unhandled Coprocessor Unusable Exception");
142
        fault_if_from_uspace(istate, "unhandled Coprocessor Unusable Exception");
143
        panic("unhandled Coprocessor Unusable Exception\n");
143
        panic("unhandled Coprocessor Unusable Exception\n");
144
    }
144
    }
145
}
145
}
146
#endif
146
#endif
147
 
147
 
148
static void interrupt_exception(int n, istate_t *istate)
148
static void interrupt_exception(int n, istate_t *istate)
149
{
149
{
150
    uint32_t cause;
150
    uint32_t cause;
151
    int i;
151
    int i;
152
   
152
   
153
    /* decode interrupt number and process the interrupt */
153
    /* decode interrupt number and process the interrupt */
154
    cause = (cp0_cause_read() >> 8) &0xff;
154
    cause = (cp0_cause_read() >> 8) &0xff;
155
   
155
   
156
    for (i = 0; i < 8; i++) {
156
    for (i = 0; i < 8; i++) {
157
        if (cause & (1 << i)) {
157
        if (cause & (1 << i)) {
158
            irq_t *irq = irq_dispatch_and_lock(i);
158
            irq_t *irq = irq_dispatch_and_lock(i);
159
            if (irq) {
159
            if (irq) {
160
                /*
160
                /*
161
                 * The IRQ handler was found.
161
                 * The IRQ handler was found.
162
                 */
162
                 */
163
                irq->handler(irq, irq->arg);
163
                irq->handler(irq, irq->arg);
164
                spinlock_unlock(&irq->lock);
164
                spinlock_unlock(&irq->lock);
165
            } else {
165
            } else {
166
                /*
166
                /*
167
                 * Spurious interrupt.
167
                 * Spurious interrupt.
168
                 */
168
                 */
169
#ifdef CONFIG_DEBUG
169
#ifdef CONFIG_DEBUG
170
                printf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, i);
170
                printf("cpu%u: spurious interrupt (inum=%d)\n", CPU->id, i);
171
#endif
171
#endif
172
            }
172
            }
173
        }
173
        }
174
    }
174
    }
175
}
175
}
176
 
176
 
177
/** Handle syscall userspace call */
177
/** Handle syscall userspace call */
178
static void syscall_exception(int n, istate_t *istate)
178
static void syscall_exception(int n, istate_t *istate)
179
{
179
{
180
    panic("Syscall is handled through shortcut");
180
    panic("Syscall is handled through shortcut");
181
}
181
}
182
 
182
 
183
void exception_init(void)
183
void exception_init(void)
184
{
184
{
185
    int i;
185
    int i;
186
 
186
 
187
    /* Clear exception table */
187
    /* Clear exception table */
188
    for (i = 0; i < IVT_ITEMS; i++)
188
    for (i = 0; i < IVT_ITEMS; i++)
189
        exc_register(i, "undef", (iroutine) unhandled_exception);
189
        exc_register(i, "undef", (iroutine) unhandled_exception);
190
   
190
   
191
    exc_register(EXC_Bp, "bkpoint", (iroutine) breakpoint_exception);
191
    exc_register(EXC_Bp, "bkpoint", (iroutine) breakpoint_exception);
192
    exc_register(EXC_RI, "resinstr", (iroutine) reserved_instr_exception);
192
    exc_register(EXC_RI, "resinstr", (iroutine) reserved_instr_exception);
193
    exc_register(EXC_Mod, "tlb_mod", (iroutine) tlbmod_exception);
193
    exc_register(EXC_Mod, "tlb_mod", (iroutine) tlbmod_exception);
194
    exc_register(EXC_TLBL, "tlbinvl", (iroutine) tlbinv_exception);
194
    exc_register(EXC_TLBL, "tlbinvl", (iroutine) tlbinv_exception);
195
    exc_register(EXC_TLBS, "tlbinvl", (iroutine) tlbinv_exception);
195
    exc_register(EXC_TLBS, "tlbinvl", (iroutine) tlbinv_exception);
196
    exc_register(EXC_Int, "interrupt", (iroutine) interrupt_exception);
196
    exc_register(EXC_Int, "interrupt", (iroutine) interrupt_exception);
197
#ifdef CONFIG_FPU_LAZY
197
#ifdef CONFIG_FPU_LAZY
198
    exc_register(EXC_CpU, "cpunus", (iroutine) cpuns_exception);
198
    exc_register(EXC_CpU, "cpunus", (iroutine) cpuns_exception);
199
#endif
199
#endif
200
    exc_register(EXC_Sys, "syscall", (iroutine) syscall_exception);
200
    exc_register(EXC_Sys, "syscall", (iroutine) syscall_exception);
201
}
201
}
202
 
202
 
203
/** @}
203
/** @}
204
 */
204
 */
205
 
205