Subversion Repositories HelenOS-historic

Rev

Rev 534 | Rev 593 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 534 Rev 590
Line 32... Line 32...
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>
-
 
38
#include <print.h>
-
 
39
#include <interrupt.h>
-
 
40
 
-
 
41
static char * exctable[] = {
-
 
42
    "Interrupt","TLB Modified","TLB Invalid","TLB Invalid Store",
-
 
43
        "Address Error - load/instr. fetch",
-
 
44
        "Address Error - store",
-
 
45
        "Bus Error - fetch instruction",
-
 
46
        "Bus Error - data reference",
-
 
47
        "Syscall",
-
 
48
        "BreakPoint",
-
 
49
        "Reserved Instruction",
-
 
50
        "Coprocessor Unusable",
-
 
51
        "Arithmetic Overflow",
-
 
52
        "Trap",
-
 
53
        "Virtual Coherency - instruction",
-
 
54
        "Floating Point",
-
 
55
        NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-
 
56
        "WatchHi/WatchLo", /* 23 */
-
 
57
        NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-
 
58
        "Virtual Coherency - data",
-
 
59
};
-
 
60
 
-
 
61
static void print_regdump(struct exception_regdump *pstate)
-
 
62
{
-
 
63
    char *pcsymbol = "";
-
 
64
    char *rasymbol = "";
-
 
65
 
-
 
66
    char *s = get_symtab_entry(pstate->epc);
-
 
67
    if (s)
-
 
68
        pcsymbol = s;
-
 
69
    s = get_symtab_entry(pstate->ra);
-
 
70
    if (s)
-
 
71
        rasymbol = s;
-
 
72
   
-
 
73
    printf("PC: %X(%s) RA: %X(%s)\n",pstate->epc,pcsymbol,
-
 
74
           pstate->ra,rasymbol);
-
 
75
}
-
 
76
 
-
 
77
static void unhandled_exception(int n, void *data)
-
 
78
{
-
 
79
    struct exception_regdump *pstate = (struct exception_regdump *)data;
-
 
80
 
-
 
81
    print_regdump(pstate);
-
 
82
    panic("unhandled exception %s\n", exctable[n]);
-
 
83
}
-
 
84
 
-
 
85
static void breakpoint_exception(int n, void *data)
-
 
86
{
-
 
87
    struct exception_regdump *pstate = (struct exception_regdump *)data;
-
 
88
    /* it is necessary to not re-execute BREAK instruction after
-
 
89
       returning from Exception handler
-
 
90
       (see page 138 in R4000 Manual for more information) */
-
 
91
    pstate->epc += 4;
-
 
92
}
-
 
93
 
-
 
94
static void tlbmod_exception(int n, void *data)
-
 
95
{
-
 
96
    struct exception_regdump *pstate = (struct exception_regdump *)data;
-
 
97
    tlb_modified(pstate);
-
 
98
}
-
 
99
 
-
 
100
static void tlbinv_exception(int n, void *data)
-
 
101
{
-
 
102
    struct exception_regdump *pstate = (struct exception_regdump *)data;
-
 
103
    tlb_invalid(pstate);
-
 
104
}
-
 
105
 
-
 
106
static void cpunsbl_exception(int n, void *data)
-
 
107
{
-
 
108
    if (cp0_cause_coperr(cp0_cause_read()) == fpu_cop_id)
-
 
109
        scheduler_fpu_lazy_request();
-
 
110
    else
-
 
111
        panic("unhandled Coprocessor Unusable Exception\n");
-
 
112
}
-
 
113
 
-
 
114
static void interrupt_exception(int n, void *pstate)
-
 
115
{
-
 
116
    __u32 cause;
-
 
117
    int i;
-
 
118
   
-
 
119
    /* decode interrupt number and process the interrupt */
-
 
120
    cause = (cp0_cause_read() >> 8) &0xff;
-
 
121
   
-
 
122
    for (i = 0; i < 8; i++)
-
 
123
        if (cause & (1 << i))
-
 
124
            exc_dispatch(i+INT_OFFSET, pstate);
-
 
125
}
-
 
126
 
37
 
127
 
38
void exception(struct exception_regdump *pstate)
128
void exception(struct exception_regdump *pstate)
39
{
129
{
40
    int cause;
130
    int cause;
41
    int excno;
131
    int excno;
Line 61... Line 151...
61
    if (THREAD && !THREAD->pstate)
151
    if (THREAD && !THREAD->pstate)
62
        THREAD->pstate = pstate;
152
        THREAD->pstate = pstate;
63
 
153
 
64
    cause = cp0_cause_read();
154
    cause = cp0_cause_read();
65
    excno = cp0_cause_excno(cause);
155
    excno = cp0_cause_excno(cause);
66
    /* decode exception number and process the exception */
-
 
67
    switch (excno) {
156
    /* Dispatch exception */
68
        case EXC_Int:
-
 
69
            interrupt(pstate);
157
    exc_dispatch(excno, pstate);
70
            break;
-
 
71
        case EXC_TLBL:
-
 
72
        case EXC_TLBS:
-
 
73
            tlb_invalid(pstate);
-
 
74
            break;
-
 
75
        case EXC_CpU:
-
 
76
#ifdef CONFIG_FPU_LAZY     
-
 
77
            if (cp0_cause_coperr(cause) == fpu_cop_id)
-
 
78
                scheduler_fpu_lazy_request();
-
 
79
            else
-
 
80
#endif
-
 
81
                panic("unhandled Coprocessor Unusable Exception\n");
-
 
82
            break;
-
 
83
        case EXC_Mod:
-
 
84
            tlb_modified(pstate);
-
 
85
            break;
-
 
86
        case EXC_AdEL:
-
 
87
            panic("unhandled Address Error Exception - load or instruction fetch\n");
-
 
88
            break;
-
 
89
        case EXC_AdES:
-
 
90
            panic("unhandled Address Error Exception - store\n");
-
 
91
            break;
-
 
92
        case EXC_IBE:
-
 
93
            panic("unhandled Bus Error Exception - fetch instruction\n");
-
 
94
            break;
-
 
95
        case EXC_DBE:
-
 
96
            panic("unhandled Bus Error Exception - data reference: load or store\n");
-
 
97
            break;
-
 
98
        case EXC_Bp:
-
 
99
            /* it is necessary to not re-execute BREAK instruction after returning from Exception handler
-
 
100
               (see page 138 in R4000 Manual for more information) */
-
 
101
            epc_shift = 4;
-
 
102
            break;
-
 
103
        case EXC_RI:
-
 
104
            panic("unhandled Reserved Instruction Exception\n");
-
 
105
            break;
-
 
106
        case EXC_Ov:
-
 
107
            panic("unhandled Arithmetic Overflow Exception\n");
-
 
108
            break;
-
 
109
        case EXC_Tr:
-
 
110
            panic("unhandled Trap Exception\n");
-
 
111
            break;
-
 
112
        case EXC_VCEI:
-
 
113
            panic("unhandled Virtual Coherency Exception - instruction\n");
-
 
114
            break;
-
 
115
        case EXC_FPE:
-
 
116
            panic("unhandled Floating-Point Exception\n");
-
 
117
            break;
-
 
118
        case EXC_WATCH:
-
 
119
            panic("unhandled reference to WatchHi/WatchLo address\n");
-
 
120
            break;
-
 
121
        case EXC_VCED:
-
 
122
            panic("unhandled Virtual Coherency Exception - data\n");
-
 
123
            break;
-
 
124
        default:
-
 
125
            panic("unhandled exception %d\n", excno);
-
 
126
    }
-
 
127
   
158
 
128
    pstate->epc += epc_shift;
-
 
129
    /* Set to NULL, so that we can still support nested
159
    /* Set to NULL, so that we can still support nested
130
     * exceptions
160
     * exceptions
131
     * TODO: We should probably set EXL bit before this command,
161
     * TODO: We should probably set EXL bit before this command,
132
     * nesting. On the other hand, if some exception occurs between
162
     * nesting. On the other hand, if some exception occurs between
133
     * here and ERET, it won't set anything on the pstate anyway.
163
     * here and ERET, it won't set anything on the pstate anyway.
134
     */
164
     */
135
    if (THREAD)
165
    if (THREAD)
136
        THREAD->pstate = NULL;
166
        THREAD->pstate = NULL;
137
}
167
}
-
 
168
 
-
 
169
void exception_init(void)
-
 
170
{
-
 
171
    int i;
-
 
172
 
-
 
173
    /* Clear exception table */
-
 
174
    for (i=0;i < IVT_ITEMS; i++)
-
 
175
        exc_register(i, "undef", unhandled_exception);
-
 
176
    exc_register(EXC_Bp, "bkpoint", breakpoint_exception);
-
 
177
    exc_register(EXC_Mod, "tlb_mod", tlbmod_exception);
-
 
178
    exc_register(EXC_TLBL, "tlbinvl", tlbinv_exception);
-
 
179
    exc_register(EXC_TLBS, "tlbinvl", tlbinv_exception);
-
 
180
    exc_register(EXC_Int, "interrupt", interrupt_exception);
-
 
181
#ifdef CONFIG_FPU_LAZY
-
 
182
    exc_register(EXC_CpU, "cpunus", cpun_exception);
-
 
183
#endif
-
 
184
}