Subversion Repositories HelenOS

Rev

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

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