Subversion Repositories HelenOS

Rev

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

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