Subversion Repositories HelenOS-historic

Rev

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

Rev 610 Rev 614
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
#include <arch/exception.h>
29
#include <arch/exception.h>
30
#include <arch/interrupt.h>
30
#include <arch/interrupt.h>
31
#include <panic.h>
31
#include <panic.h>
32
#include <arch/cp0.h>
32
#include <arch/cp0.h>
33
#include <arch/types.h>
33
#include <arch/types.h>
34
#include <arch.h>
34
#include <arch.h>
35
#include <debug.h>
35
#include <debug.h>
36
#include <proc/thread.h>
36
#include <proc/thread.h>
37
#include <symtab.h>
37
#include <symtab.h>
38
#include <print.h>
38
#include <print.h>
39
#include <interrupt.h>
39
#include <interrupt.h>
40
#include <func.h>
40
#include <func.h>
41
#include <console/kconsole.h>
41
#include <console/kconsole.h>
-
 
42
#include <arch/debugger.h>
42
 
43
 
43
static char * exctable[] = {
44
static char * exctable[] = {
44
    "Interrupt","TLB Modified","TLB Invalid","TLB Invalid Store",
45
    "Interrupt","TLB Modified","TLB Invalid","TLB Invalid Store",
45
        "Address Error - load/instr. fetch",
46
        "Address Error - load/instr. fetch",
46
        "Address Error - store",
47
        "Address Error - store",
47
        "Bus Error - fetch instruction",
48
        "Bus Error - fetch instruction",
48
        "Bus Error - data reference",
49
        "Bus Error - data reference",
49
        "Syscall",
50
        "Syscall",
50
        "BreakPoint",
51
        "BreakPoint",
51
        "Reserved Instruction",
52
        "Reserved Instruction",
52
        "Coprocessor Unusable",
53
        "Coprocessor Unusable",
53
        "Arithmetic Overflow",
54
        "Arithmetic Overflow",
54
        "Trap",
55
        "Trap",
55
        "Virtual Coherency - instruction",
56
        "Virtual Coherency - instruction",
56
        "Floating Point",
57
        "Floating Point",
57
        NULL, NULL, NULL, NULL, NULL, NULL, NULL,
58
        NULL, NULL, NULL, NULL, NULL, NULL, NULL,
58
        "WatchHi/WatchLo", /* 23 */
59
        "WatchHi/WatchLo", /* 23 */
59
        NULL, NULL, NULL, NULL, NULL, NULL, NULL,
60
        NULL, NULL, NULL, NULL, NULL, NULL, NULL,
60
        "Virtual Coherency - data",
61
        "Virtual Coherency - data",
61
};
62
};
62
 
63
 
63
static void print_regdump(struct exception_regdump *pstate)
64
static void print_regdump(struct exception_regdump *pstate)
64
{
65
{
65
    char *pcsymbol = "";
66
    char *pcsymbol = "";
66
    char *rasymbol = "";
67
    char *rasymbol = "";
67
 
68
 
68
    char *s = get_symtab_entry(pstate->epc);
69
    char *s = get_symtab_entry(pstate->epc);
69
    if (s)
70
    if (s)
70
        pcsymbol = s;
71
        pcsymbol = s;
71
    s = get_symtab_entry(pstate->ra);
72
    s = get_symtab_entry(pstate->ra);
72
    if (s)
73
    if (s)
73
        rasymbol = s;
74
        rasymbol = s;
74
   
75
   
75
    printf("PC: %X(%s) RA: %X(%s)\n",pstate->epc,pcsymbol,
76
    printf("PC: %X(%s) RA: %X(%s)\n",pstate->epc,pcsymbol,
76
           pstate->ra,rasymbol);
77
           pstate->ra,rasymbol);
77
}
78
}
78
 
79
 
79
static void unhandled_exception(int n, void *data)
80
static void unhandled_exception(int n, void *data)
80
{
81
{
81
    struct exception_regdump *pstate = (struct exception_regdump *)data;
82
    struct exception_regdump *pstate = (struct exception_regdump *)data;
82
 
83
 
83
    print_regdump(pstate);
84
    print_regdump(pstate);
84
    panic("unhandled exception %s\n", exctable[n]);
85
    panic("unhandled exception %s\n", exctable[n]);
85
}
86
}
86
 
87
 
87
static void breakpoint_exception(int n, void *data)
88
static void breakpoint_exception(int n, void *data)
88
{
89
{
89
    struct exception_regdump *pstate = (struct exception_regdump *)data;
90
    struct exception_regdump *pstate = (struct exception_regdump *)data;
90
    char *symbol = get_symtab_entry(pstate->epc);
-
 
91
 
-
 
92
#ifdef CONFIG_DEBUG 
-
 
93
    printf("***Breakpoint %p in %s.\n", pstate->epc, symbol);
-
 
94
    printf("***Type 'exit' to exit kconsole.\n");
-
 
95
    /* Umm..we should rather set some 'debugstate' here */
-
 
96
    haltstate = 1;
-
 
97
    kconsole("debug");
-
 
98
    haltstate = 0;
-
 
99
#endif
-
 
100
 
91
 
-
 
92
#ifdef CONFIG_DEBUG
-
 
93
    debugger_bpoint(pstate);
-
 
94
#else
101
    /* it is necessary to not re-execute BREAK instruction after
95
    /* it is necessary to not re-execute BREAK instruction after
102
       returning from Exception handler
96
       returning from Exception handler
103
       (see page 138 in R4000 Manual for more information) */
97
       (see page 138 in R4000 Manual for more information) */
104
    pstate->epc += 4;
98
    pstate->epc += 4;
-
 
99
#endif
105
}
100
}
106
 
101
 
107
static void tlbmod_exception(int n, void *data)
102
static void tlbmod_exception(int n, void *data)
108
{
103
{
109
    struct exception_regdump *pstate = (struct exception_regdump *)data;
104
    struct exception_regdump *pstate = (struct exception_regdump *)data;
110
    tlb_modified(pstate);
105
    tlb_modified(pstate);
111
}
106
}
112
 
107
 
113
static void tlbinv_exception(int n, void *data)
108
static void tlbinv_exception(int n, void *data)
114
{
109
{
115
    struct exception_regdump *pstate = (struct exception_regdump *)data;
110
    struct exception_regdump *pstate = (struct exception_regdump *)data;
116
    tlb_invalid(pstate);
111
    tlb_invalid(pstate);
117
}
112
}
118
 
113
 
119
static void cpuns_exception(int n, void *data)
114
static void cpuns_exception(int n, void *data)
120
{
115
{
121
    if (cp0_cause_coperr(cp0_cause_read()) == fpu_cop_id)
116
    if (cp0_cause_coperr(cp0_cause_read()) == fpu_cop_id)
122
        scheduler_fpu_lazy_request();
117
        scheduler_fpu_lazy_request();
123
    else
118
    else
124
        panic("unhandled Coprocessor Unusable Exception\n");
119
        panic("unhandled Coprocessor Unusable Exception\n");
125
}
120
}
126
 
121
 
127
static void interrupt_exception(int n, void *pstate)
122
static void interrupt_exception(int n, void *pstate)
128
{
123
{
129
    __u32 cause;
124
    __u32 cause;
130
    int i;
125
    int i;
131
   
126
   
132
    /* decode interrupt number and process the interrupt */
127
    /* decode interrupt number and process the interrupt */
133
    cause = (cp0_cause_read() >> 8) &0xff;
128
    cause = (cp0_cause_read() >> 8) &0xff;
134
   
129
   
135
    for (i = 0; i < 8; i++)
130
    for (i = 0; i < 8; i++)
136
        if (cause & (1 << i))
131
        if (cause & (1 << i))
137
            exc_dispatch(i+INT_OFFSET, pstate);
132
            exc_dispatch(i+INT_OFFSET, pstate);
138
}
133
}
139
 
134
 
140
 
135
 
141
void exception(struct exception_regdump *pstate)
136
void exception(struct exception_regdump *pstate)
142
{
137
{
143
    int cause;
138
    int cause;
144
    int excno;
139
    int excno;
145
 
140
 
146
    ASSERT(CPU != NULL);
141
    ASSERT(CPU != NULL);
147
 
142
 
148
    /*
143
    /*
149
     * NOTE ON OPERATION ORDERING
144
     * NOTE ON OPERATION ORDERING
150
     *
145
     *
151
     * On entry, interrupts_disable() must be called before
146
     * On entry, interrupts_disable() must be called before
152
     * exception bit is cleared.
147
     * exception bit is cleared.
153
     */
148
     */
154
 
149
 
155
    interrupts_disable();
150
    interrupts_disable();
156
    cp0_status_write(cp0_status_read() & ~ (cp0_status_exl_exception_bit |
151
    cp0_status_write(cp0_status_read() & ~ (cp0_status_exl_exception_bit |
157
                        cp0_status_um_bit));
152
                        cp0_status_um_bit));
158
 
153
 
159
    /* Save pstate so that the threads can access it */
154
    /* Save pstate so that the threads can access it */
160
    /* If THREAD->pstate is set, this is nested exception,
155
    /* If THREAD->pstate is set, this is nested exception,
161
     * do not rewrite it
156
     * do not rewrite it
162
     */
157
     */
163
    if (THREAD && !THREAD->pstate)
158
    if (THREAD && !THREAD->pstate)
164
        THREAD->pstate = pstate;
159
        THREAD->pstate = pstate;
165
 
160
 
166
    cause = cp0_cause_read();
161
    cause = cp0_cause_read();
167
    excno = cp0_cause_excno(cause);
162
    excno = cp0_cause_excno(cause);
168
    /* Dispatch exception */
163
    /* Dispatch exception */
169
    exc_dispatch(excno, pstate);
164
    exc_dispatch(excno, pstate);
170
 
165
 
171
    /* Set to NULL, so that we can still support nested
166
    /* Set to NULL, so that we can still support nested
172
     * exceptions
167
     * exceptions
173
     * TODO: We should probably set EXL bit before this command,
168
     * TODO: We should probably set EXL bit before this command,
174
     * nesting. On the other hand, if some exception occurs between
169
     * nesting. On the other hand, if some exception occurs between
175
     * here and ERET, it won't set anything on the pstate anyway.
170
     * here and ERET, it won't set anything on the pstate anyway.
176
     */
171
     */
177
    if (THREAD)
172
    if (THREAD)
178
        THREAD->pstate = NULL;
173
        THREAD->pstate = NULL;
179
}
174
}
180
 
175
 
181
void exception_init(void)
176
void exception_init(void)
182
{
177
{
183
    int i;
178
    int i;
184
 
179
 
185
    /* Clear exception table */
180
    /* Clear exception table */
186
    for (i=0;i < IVT_ITEMS; i++)
181
    for (i=0;i < IVT_ITEMS; i++)
187
        exc_register(i, "undef", unhandled_exception);
182
        exc_register(i, "undef", unhandled_exception);
188
    exc_register(EXC_Bp, "bkpoint", breakpoint_exception);
183
    exc_register(EXC_Bp, "bkpoint", breakpoint_exception);
189
    exc_register(EXC_Mod, "tlb_mod", tlbmod_exception);
184
    exc_register(EXC_Mod, "tlb_mod", tlbmod_exception);
190
    exc_register(EXC_TLBL, "tlbinvl", tlbinv_exception);
185
    exc_register(EXC_TLBL, "tlbinvl", tlbinv_exception);
191
    exc_register(EXC_TLBS, "tlbinvl", tlbinv_exception);
186
    exc_register(EXC_TLBS, "tlbinvl", tlbinv_exception);
192
    exc_register(EXC_Int, "interrupt", interrupt_exception);
187
    exc_register(EXC_Int, "interrupt", interrupt_exception);
193
#ifdef CONFIG_FPU_LAZY
188
#ifdef CONFIG_FPU_LAZY
194
    exc_register(EXC_CpU, "cpunus", cpuns_exception);
189
    exc_register(EXC_CpU, "cpunus", cpuns_exception);
195
#endif
190
#endif
196
}
191
}
197
 
192