Subversion Repositories HelenOS-historic

Rev

Rev 1769 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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