Subversion Repositories HelenOS-historic

Rev

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

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