Changeset 6ac14a70 in mainline for kernel/arch/arm32/src/exception.c


Ignore:
Timestamp:
2009-07-28T12:47:31Z (15 years ago)
Author:
Vineeth Pillai <vineethrp@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5e73815
Parents:
7038f55
Message:

ARM port for development board integratorcp(ARM926EJ core module).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/arm32/src/exception.c

    r7038f55 r6ac14a70  
    4040#include <arch/mm/page_fault.h>
    4141#include <arch/barrier.h>
    42 #include <arch/drivers/gxemul.h>
     42#include <arch/machine.h>
    4343#include <print.h>
    4444#include <syscall/syscall.h>
     
    5858/** Size of memory block occupied by exception vectors. */
    5959#define EXC_VECTORS_SIZE     (EXC_VECTORS * 4)
    60 
    61 /** Switches to kernel stack and saves all registers there.
    62  *
    63  * Temporary exception stack is used to save a few registers
    64  * before stack switch takes place.
    65  *
    66  */
    67 inline static void setup_stack_and_save_regs()
    68 {
    69         asm volatile (
    70                 "ldr r13, =exc_stack\n"
    71                 "stmfd r13!, {r0}\n"
    72                 "mrs r0, spsr\n"
    73                 "and r0, r0, #0x1f\n"
    74                 "cmp r0, #0x10\n"
    75                 "bne 1f\n"
    76                
    77                 /* prev mode was usermode */
    78                 "ldmfd r13!, {r0}\n"
    79                 "ldr r13, =supervisor_sp\n"
    80                 "ldr r13, [r13]\n"
    81                 "stmfd r13!, {lr}\n"
    82                 "stmfd r13!, {r0-r12}\n"
    83                 "stmfd r13!, {r13, lr}^\n"
    84                 "mrs r0, spsr\n"
    85                 "stmfd r13!, {r0}\n"
    86                 "b 2f\n"
    87                
    88                 /* mode was not usermode */
    89                 "1:\n"
    90                         "stmfd r13!, {r1, r2, r3}\n"
    91                         "mrs r1, cpsr\n"
    92                         "mov r2, lr\n"
    93                         "bic r1, r1, #0x1f\n"
    94                         "orr r1, r1, r0\n"
    95                         "mrs r0, cpsr\n"
    96                         "msr cpsr_c, r1\n"
    97                        
    98                         "mov r3, r13\n"
    99                         "stmfd r13!, {r2}\n"
    100                         "mov r2, lr\n"
    101                         "stmfd r13!, {r4-r12}\n"
    102                         "mov r1, r13\n"
    103                        
    104                         /* the following two lines are for debugging */
    105                         "mov sp, #0\n"
    106                         "mov lr, #0\n"
    107                         "msr cpsr_c, r0\n"
    108                        
    109                         "ldmfd r13!, {r4, r5, r6, r7}\n"
    110                         "stmfd r1!, {r4, r5, r6}\n"
    111                         "stmfd r1!, {r7}\n"
    112                         "stmfd r1!, {r2}\n"
    113                         "stmfd r1!, {r3}\n"
    114                         "mrs r0, spsr\n"
    115                         "stmfd r1!, {r0}\n"
    116                         "mov r13, r1\n"
    117                        
    118                 "2:\n"
    119         );
    120 }
    121 
    122 /** Returns from exception mode.
    123  *
    124  * Previously saved state of registers (including control register)
    125  * is restored from the stack.
    126  */
    127 inline static void load_regs()
    128 {
    129         asm volatile(
    130                 "ldmfd r13!, {r0}               \n"
    131                 "msr spsr, r0                   \n"
    132                 "and r0, r0, #0x1f              \n"
    133                 "cmp r0, #0x10                  \n"
    134                 "bne 1f                         \n"
    135 
    136                 /* return to user mode */
    137                 "ldmfd r13!, {r13, lr}^         \n"
    138                 "b 2f                           \n"
    139 
    140                 /* return to non-user mode */
    141         "1:\n"
    142                 "ldmfd r13!, {r1, r2}           \n"
    143                 "mrs r3, cpsr                   \n"
    144                 "bic r3, r3, #0x1f              \n"
    145                 "orr r3, r3, r0                 \n"
    146                 "mrs r0, cpsr                   \n"
    147                 "msr cpsr_c, r3                 \n"
    148 
    149                 "mov r13, r1                    \n"
    150                 "mov lr, r2                     \n"
    151                 "msr cpsr_c, r0                 \n"
    152 
    153                 /* actual return */
    154         "2:\n"
    155                 "ldmfd r13, {r0-r12, pc}^\n"
    156         );
    157 }
    158 
    159 
    160 /** Switch CPU to mode in which interrupts are serviced (currently it
    161  * is Undefined mode).
    162  *
    163  * The default mode for interrupt servicing (Interrupt Mode)
    164  * can not be used because of nested interrupts (which can occur
    165  * because interrupts are enabled in higher levels of interrupt handler).
    166  */
    167 inline static void switch_to_irq_servicing_mode()
    168 {
    169         /* switch to Undefined mode */
    170         asm volatile(
    171                 /* save regs used during switching */
    172                 "stmfd sp!, {r0-r3}             \n"
    173 
    174                 /* save stack pointer and link register to r1, r2 */
    175                 "mov r1, sp                     \n"
    176                 "mov r2, lr                     \n"
    177 
    178                 /* mode switch */
    179                 "mrs r0, cpsr                   \n"
    180                 "bic r0, r0, #0x1f              \n"
    181                 "orr r0, r0, #0x1b              \n"
    182                 "msr cpsr_c, r0                 \n"
    183 
    184                 /* restore saved sp and lr */
    185                 "mov sp, r1                     \n"
    186                 "mov lr, r2                     \n"
    187 
    188                 /* restore original regs */
    189                 "ldmfd sp!, {r0-r3}             \n"
    190         );
    191 }
    192 
    193 /** Calls exception dispatch routine. */
    194 #define CALL_EXC_DISPATCH(exception) \
    195         asm volatile ( \
    196                 "mov r0, %[exc]\n" \
    197                 "mov r1, r13\n" \
    198                 "bl exc_dispatch\n" \
    199                 :: [exc] "i" (exception) \
    200         );\
    201 
    202 /** General exception handler.
    203  *
    204  *  Stores registers, dispatches the exception,
    205  *  and finally restores registers and returns from exception processing.
    206  *
    207  *  @param exception Exception number.
    208  */
    209 #define PROCESS_EXCEPTION(exception) \
    210         setup_stack_and_save_regs(); \
    211         CALL_EXC_DISPATCH(exception) \
    212         load_regs();
    21360
    21461/** Updates specified exception vector to jump to given handler.
     
    23380}
    23481
    235 /** Low-level Reset Exception handler. */
    236 static void reset_exception_entry(void)
    237 {
    238         PROCESS_EXCEPTION(EXC_RESET);
    239 }
    240 
    241 /** Low-level Software Interrupt Exception handler. */
    242 static void swi_exception_entry(void)
    243 {
    244         PROCESS_EXCEPTION(EXC_SWI);
    245 }
    246 
    247 /** Low-level Undefined Instruction Exception handler. */
    248 static void undef_instr_exception_entry(void)
    249 {
    250         PROCESS_EXCEPTION(EXC_UNDEF_INSTR);
    251 }
    252 
    253 /** Low-level Fast Interrupt Exception handler. */
    254 static void fiq_exception_entry(void)
    255 {
    256         PROCESS_EXCEPTION(EXC_FIQ);
    257 }
    258 
    259 /** Low-level Prefetch Abort Exception handler. */
    260 static void prefetch_abort_exception_entry(void)
    261 {
    262         asm volatile (
    263                 "sub lr, lr, #4"
    264         );
    265        
    266         PROCESS_EXCEPTION(EXC_PREFETCH_ABORT);
    267 }
    268 
    269 /** Low-level Data Abort Exception handler. */
    270 static void data_abort_exception_entry(void)
    271 {
    272         asm volatile (
    273                 "sub lr, lr, #8"
    274         );
    275        
    276         PROCESS_EXCEPTION(EXC_DATA_ABORT);
    277 }
    278 
    279 /** Low-level Interrupt Exception handler.
    280  *
    281  * CPU is switched to Undefined mode before further interrupt processing
    282  * because of possible occurence of nested interrupt exception, which
    283  * would overwrite (and thus spoil) stack pointer.
    284  */
    285 static void irq_exception_entry(void)
    286 {
    287         asm volatile (
    288                 "sub lr, lr, #4"
    289         );
    290        
    291         setup_stack_and_save_regs();
    292        
    293         switch_to_irq_servicing_mode();
    294        
    295         CALL_EXC_DISPATCH(EXC_IRQ)
    296 
    297         load_regs();
    298 }
    299 
    30082/** Software Interrupt handler.
    30183 *
     
    30688        istate->r0 = syscall_handler(istate->r0, istate->r1, istate->r2,
    30789            istate->r3, istate->r4, istate->r5, istate->r6);
    308 }
    309 
    310 /** Returns the mask of active interrupts. */
    311 static inline uint32_t gxemul_irqc_get_sources(void)
    312 {
    313         return *((uint32_t *) gxemul_irqc);
    314 }
    315 
    316 /** Interrupt Exception handler.
    317  *
    318  * Determines the sources of interrupt and calls their handlers.
    319  */
    320 static void irq_exception(int exc_no, istate_t *istate)
    321 {
    322         uint32_t sources = gxemul_irqc_get_sources();
    323         unsigned int i;
    324        
    325         for (i = 0; i < GXEMUL_IRQC_MAX_IRQ; i++) {
    326                 if (sources & (1 << i)) {
    327                         irq_t *irq = irq_dispatch_and_lock(i);
    328                         if (irq) {
    329                                 /* The IRQ handler was found. */
    330                                 irq->handler(irq);
    331                                 spinlock_unlock(&irq->lock);
    332                         } else {
    333                                 /* Spurious interrupt.*/
    334                                 printf("cpu%d: spurious interrupt (inum=%d)\n",
    335                                     CPU->id, i);
    336                         }
    337                 }
    338         }
    33990}
    34091
     
    385136#endif
    386137
     138/** Interrupt Exception handler.
     139 *
     140 * Determines the sources of interrupt and calls their handlers.
     141 */
     142static void irq_exception(int exc_no, istate_t *istate)
     143{
     144        machine_irq_exception(exc_no, istate);
     145}
     146
    387147/** Initializes exception handling.
    388148 *
Note: See TracChangeset for help on using the changeset viewer.