Subversion Repositories HelenOS-historic

Rev

Rev 1119 | Rev 1196 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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