Subversion Repositories HelenOS

Rev

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

Rev 2179 Rev 2235
Line 1... Line 1...
1
    /*
1
/*
2
 * Copyright (c) 2007 Petr Stepan
2
 * Copyright (c) 2007 Petr Stepan
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
Line 34... Line 34...
34
 */
34
 */
35
 
35
 
36
#include <arch/exception.h>
36
#include <arch/exception.h>
37
#include "aux_print/printf.h"
37
#include "aux_print/printf.h"
38
#include <arch/memstr.h>
38
#include <arch/memstr.h>
-
 
39
#include <arch/regutils.h>
-
 
40
#include <interrupt.h>
-
 
41
 
39
 
42
 
40
#define PREFETCH_OFFSET     0x8
43
#define PREFETCH_OFFSET     0x8
41
#define BRANCH_OPCODE       0xea000000
44
#define BRANCH_OPCODE       0xea000000
-
 
45
#define LDR_OPCODE      0xe59ff000
42
#define VALID_BRANCH_MASK   0xff000000
46
#define VALID_BRANCH_MASK   0xff000000
-
 
47
#define EXC_VECTORS_SIZE    0x20
-
 
48
#define EXC_VECTORS     0x8
43
 
49
 
-
 
50
/* GXEmul interrupt controller macros
44
/** Updates specified exception vector to jump to given handler.
51
TODO might go to drivers/ together with servicing functions
45
*/
52
*/
46
static void install_handler (unsigned* handler, unsigned* vector) {
53
/* IRQ Controller device is added in a special premium gxemul
-
 
54
 * edition at www.ms.mff.cuni.cz/~stepp3am/mygxemul-0.4.4.1.tar.gz
-
 
55
 * :)
-
 
56
 */
-
 
57
#define IRQ_CONTROLLER_CAUSE    0x0000000016000000
-
 
58
#define IRQ_CONTROLLER_MAX_IRQ  8
-
 
59
 
-
 
60
/* IRQs */
-
 
61
#define CONSOLE_IRQ     2
47
    volatile unsigned vec;
62
#define TIMER_IRQ       4
-
 
63
 
48
   
64
 
49
    /* calculate relative distance */
65
#define SAVE_REGS_TO_STACK          \
50
    vec = ((unsigned)handler - (unsigned)vector - PREFETCH_OFFSET);
66
    asm("stmfd sp!, {r0-r12, sp, lr}");     \
-
 
67
    asm("mrs r14, spsr");           \
-
 
68
    asm("stmfd sp!, {r14}");
51
   
69
 
-
 
70
#define CALL_EXC_DISPATCH(exception)        \
-
 
71
    asm("mov r0, %0" : : "i" (exception));  \
52
    /* word offset */
72
    asm("mov r1, sp");          \
-
 
73
    asm("bl exc_dispatch");     
-
 
74
 
-
 
75
/**Loads registers from the stack and resets SPSR before exitting exception
53
    vec >>= 2;
76
 * handler.
-
 
77
 */
-
 
78
#define LOAD_REGS_FROM_STACK            \
-
 
79
    asm("ldmfd sp!, {r14}");        \
-
 
80
    asm("msr spsr, r14");           \
-
 
81
    asm("ldmfd sp!, {r0-r12, sp, pc}^");
54
   
82
   
-
 
83
/** General exception handler.
55
    /* check if haven't jumped beyond 32 MB */
84
 *  Stores registers, dispatches the exception,
-
 
85
 *  and finally restores registers and returns from exception processing.
-
 
86
 */
-
 
87
#define PROCESS_EXCEPTION(exception)        \
-
 
88
    SAVE_REGS_TO_STACK          \
56
    if ((vec & VALID_BRANCH_MASK) != 0) {
89
    CALL_EXC_DISPATCH(exception)        \
-
 
90
    LOAD_REGS_FROM_STACK            
-
 
91
 
57
        /*panic("exception handler beyond 32MB.");*/
92
/** Updates specified exception vector to jump to given handler.
-
 
93
 * Addresses of handlers are stored in memory following exception vectors.
58
        return;
94
 */
-
 
95
static void install_handler (unsigned handler_addr, unsigned* vector)
-
 
96
{
-
 
97
    /* relative address (related to exc. vector) of the word
-
 
98
     * where handler's address is stored
59
    }
99
    */
-
 
100
    volatile uint32_t handler_address_ptr = EXC_VECTORS_SIZE - PREFETCH_OFFSET;
60
   
101
   
61
    /* make it branch instruction */
102
    /* make it LDR instruction and store at exception vector */
62
    vec |= BRANCH_OPCODE;
103
    *vector = handler_address_ptr | LDR_OPCODE;
63
    *vector = vec;
-
 
64
   
104
   
-
 
105
    /* store handler's address */
-
 
106
    *(vector + EXC_VECTORS) = handler_addr;
-
 
107
}
-
 
108
 
-
 
109
static void reset_exception_entry()
-
 
110
{
-
 
111
    PROCESS_EXCEPTION(EXC_RESET);
-
 
112
}
-
 
113
 
-
 
114
/** Low-level Software Interrupt Exception handler */
-
 
115
static void swi_exception_entry()
-
 
116
{
-
 
117
    PROCESS_EXCEPTION(EXC_SWI);
-
 
118
}
-
 
119
 
65
    aux_printf("installed  handler to %p, to vector %p\n.", handler, vector);
120
/** Low-level Undefined Instruction Exception handler */
-
 
121
static void undef_instr_exception_entry()
-
 
122
{
-
 
123
    PROCESS_EXCEPTION(EXC_UNDEF_INSTR);
-
 
124
}
-
 
125
 
-
 
126
/** Low-level Fast Interrupt Exception handler */
-
 
127
static void fiq_exception_entry()
-
 
128
{
-
 
129
    PROCESS_EXCEPTION(EXC_FIQ);
66
}
130
}
67
 
131
 
-
 
132
/** Low-level Prefetch Abort Exception handler */
-
 
133
static void prefetch_abort_exception_entry()
-
 
134
{
-
 
135
    asm("sub lr, lr, #4");
-
 
136
    PROCESS_EXCEPTION(EXC_PREFETCH_ABORT);
-
 
137
}
-
 
138
 
68
/* TODO add other exception handlers */
139
/** Low-level Data Abort Exception handler */
69
static void dummy_exception(){
140
static void data_abort_exception_entry()
-
 
141
{
70
    asm("bkpt");
142
    asm("sub lr, lr, #8");
-
 
143
    PROCESS_EXCEPTION(EXC_DATA_ABORT);
71
}
144
}
72
 
145
 
-
 
146
 
73
/** IRQ Exception handler */
147
/** Low-level Interrupt Exception handler */
74
static void irq_exception(){
148
static void irq_exception_entry()
-
 
149
{
75
    asm("bkpt");
150
    asm("sub lr, lr, #4");
-
 
151
    PROCESS_EXCEPTION(EXC_IRQ);
-
 
152
}
-
 
153
 
-
 
154
 
-
 
155
/** Interrupt Exception handler.
-
 
156
 * Determines the sources of interrupt, and calls their handlers.
-
 
157
 */
-
 
158
static void irq_exception(int exc_no, istate_t* istate)
-
 
159
{
-
 
160
    /* TODO this will call interrupt dispatching routine
-
 
161
     *
-
 
162
     */
-
 
163
 
-
 
164
    uint32_t sources = *(uint32_t*) IRQ_CONTROLLER_CAUSE;
-
 
165
    int i = 0;
-
 
166
    int noirq = 1;
-
 
167
    for (; i < IRQ_CONTROLLER_MAX_IRQ; i++) {
-
 
168
        if (sources & (1 << i)) {
-
 
169
            noirq = 0;
-
 
170
            if (i == CONSOLE_IRQ) {
-
 
171
                char readchar = *(char*)0x10000000;
-
 
172
                if (readchar == 0) {
-
 
173
                    aux_puts("?");
-
 
174
                }
-
 
175
                else {
-
 
176
                    aux_printf("%c", readchar);
-
 
177
                }
-
 
178
               
-
 
179
            }
-
 
180
            else if (i == TIMER_IRQ) {
-
 
181
                aux_printf("\n.\n");
-
 
182
                /* acknowledge  */
-
 
183
                *(uint32_t*)0x15000110 = 0;
-
 
184
            }
-
 
185
        }
-
 
186
    }
-
 
187
 
-
 
188
    if (noirq)
-
 
189
        aux_puts("IRQ exception without source\n");
76
}
190
}
77
 
191
 
78
/** Fills exception vectors with appropriate exception handlers.
192
/** Fills exception vectors with appropriate exception handlers.
79
*/
193
*/
80
void install_exception_handlers(void) {
194
void install_exception_handlers(void)
-
 
195
{
81
    install_handler((unsigned*)dummy_exception, (unsigned*)EXC_RESET_VEC);
196
    install_handler((unsigned)reset_exception_entry,
-
 
197
             (unsigned*)EXC_RESET_VEC);
-
 
198
   
82
    install_handler((unsigned*)dummy_exception, (unsigned*)EXC_UNDEF_INSTR_VEC);
199
    install_handler((unsigned)undef_instr_exception_entry,
-
 
200
             (unsigned*)EXC_UNDEF_INSTR_VEC);
-
 
201
   
83
    install_handler((unsigned*)dummy_exception, (unsigned*)EXC_SWI_VEC);
202
    install_handler((unsigned)swi_exception_entry,
-
 
203
             (unsigned*)EXC_SWI_VEC);
-
 
204
   
84
    install_handler((unsigned*)dummy_exception, (unsigned*)EXC_PREFETCH_ABORT_VEC);
205
    install_handler((unsigned)prefetch_abort_exception_entry,
-
 
206
             (unsigned*)EXC_PREFETCH_ABORT_VEC);
-
 
207
   
85
    install_handler((unsigned*)dummy_exception, (unsigned*)EXC_DATA_ABORT_VEC);
208
    install_handler((unsigned)data_abort_exception_entry,
-
 
209
             (unsigned*)EXC_DATA_ABORT_VEC);
-
 
210
   
86
    install_handler((unsigned*)irq_exception,   (unsigned*)EXC_IRQ_VEC);
211
    install_handler((unsigned)irq_exception_entry,  
-
 
212
             (unsigned*)EXC_IRQ_VEC);
-
 
213
   
87
    install_handler((unsigned*)dummy_exception, (unsigned*)EXC_FIQ_VEC);
214
    install_handler((unsigned)fiq_exception_entry,
-
 
215
             (unsigned*)EXC_FIQ_VEC);
88
}
216
}
89
 
217
 
90
/** Registers exceptions and their handlers to kernel exception dispatcher. */
218
/** Registers exceptions and their handlers to kernel exception dispatcher. */
91
void exception_init(void){
219
void exception_init(void)
-
 
220
{
-
 
221
    exc_register(EXC_IRQ, "interrupt", (iroutine) irq_exception);
92
    /* TODO */
222
    /* TODO add next */
-
 
223
}
-
 
224
 
-
 
225
/* TODO change soon, temporary hack. */
-
 
226
void setup_exception_stacks()
-
 
227
{
-
 
228
    /* switch to particular mode and set "sp" there */
-
 
229
    uint32_t cspr = current_status_reg_read();
-
 
230
    current_status_reg_control_write(
-
 
231
            (cspr & ~STATUS_REG_MODE_MASK) | IRQ_MODE
-
 
232
    );
-
 
233
    asm("ldr sp, =irq_stack");
-
 
234
    current_status_reg_control_write( cspr);
93
}
235
}
94
 
236
 
95
/** @}
237
/** @}
96
 */
238
 */