Subversion Repositories HelenOS-historic

Rev

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

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