Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/interrupt/interrupt.c

    r7e752b2 r0d21b53  
    3232/**
    3333 * @file
    34  * @brief Interrupt redirector.
     34 * @brief       Interrupt redirector.
    3535 *
    3636 * This file provides means of registering interrupt handlers
    3737 * by kernel functions and calling the handlers when interrupts
    3838 * occur.
    39  *
    4039 */
    4140
     
    5251#include <print.h>
    5352#include <symtab.h>
    54 #include <proc/thread.h>
    55 #include <arch/cycle.h>
    56 #include <str.h>
    57 #include <trace.h>
    58 
    59 exc_table_t exc_table[IVT_ITEMS];
    60 IRQ_SPINLOCK_INITIALIZE(exctbl_lock);
     53
     54static struct {
     55        const char *name;
     56        iroutine f;
     57} exc_table[IVT_ITEMS];
     58
     59SPINLOCK_INITIALIZE(exctbl_lock);
    6160
    6261/** Register exception handler
    63  *
    64  * @param n       Exception number.
    65  * @param name    Description.
    66  * @param hot     Whether the exception is actually handled
    67  *                in any meaningful way.
    68  * @param handler New exception handler.
    69  *
    70  * @return Previously registered exception handler.
    71  *
    72  */
    73 iroutine_t exc_register(unsigned int n, const char *name, bool hot,
    74     iroutine_t handler)
    75 {
    76 #if (IVT_ITEMS > 0)
     62 *
     63 * @param n Exception number
     64 * @param name Description
     65 * @param f Exception handler
     66 */
     67iroutine exc_register(int n, const char *name, iroutine f)
     68{
    7769        ASSERT(n < IVT_ITEMS);
    78 #endif
    79        
    80         irq_spinlock_lock(&exctbl_lock, true);
    81        
    82         iroutine_t old = exc_table[n].handler;
    83         exc_table[n].handler = handler;
     70       
     71        iroutine old;
     72       
     73        spinlock_lock(&exctbl_lock);
     74       
     75        old = exc_table[n].f;
     76        exc_table[n].f = f;
    8477        exc_table[n].name = name;
    85         exc_table[n].hot = hot;
    86         exc_table[n].cycles = 0;
    87         exc_table[n].count = 0;
    88        
    89         irq_spinlock_unlock(&exctbl_lock, true);
     78       
     79        spinlock_unlock(&exctbl_lock);
    9080       
    9181        return old;
     
    9686 * Called directly from the assembler code.
    9787 * CPU is interrupts_disable()'d.
    98  *
    99  */
    100 NO_TRACE void exc_dispatch(unsigned int n, istate_t *istate)
    101 {
    102 #if (IVT_ITEMS > 0)
     88 */
     89void exc_dispatch(int n, istate_t *istate)
     90{
    10391        ASSERT(n < IVT_ITEMS);
    104 #endif
    105        
    106         /* Account user cycles */
    107         if (THREAD) {
    108                 irq_spinlock_lock(&THREAD->lock, false);
    109                 thread_update_accounting(true);
    110                 irq_spinlock_unlock(&THREAD->lock, false);
    111         }
    112        
    113         /* Account CPU usage if it has waked up from sleep */
    114         if (CPU) {
    115                 irq_spinlock_lock(&CPU->lock, false);
    116                 if (CPU->idle) {
    117                         uint64_t now = get_cycle();
    118                         CPU->idle_cycles += now - CPU->last_cycle;
    119                         CPU->last_cycle = now;
    120                         CPU->idle = false;
    121                 }
    122                 irq_spinlock_unlock(&CPU->lock, false);
    123         }
    124        
    125         uint64_t begin_cycle = get_cycle();
    126        
     92
    12793#ifdef CONFIG_UDEBUG
    128         if (THREAD)
    129                 THREAD->udebug.uspace_state = istate;
    130 #endif
    131        
    132         exc_table[n].handler(n + IVT_FIRST, istate);
    133        
     94        if (THREAD) THREAD->udebug.uspace_state = istate;
     95#endif
     96       
     97        exc_table[n].f(n + IVT_FIRST, istate);
     98
    13499#ifdef CONFIG_UDEBUG
    135         if (THREAD)
    136                 THREAD->udebug.uspace_state = NULL;
    137 #endif
    138        
     100        if (THREAD) THREAD->udebug.uspace_state = NULL;
     101#endif
     102
    139103        /* This is a safe place to exit exiting thread */
    140         if ((THREAD) && (THREAD->interrupted) && (istate_from_uspace(istate)))
     104        if (THREAD && THREAD->interrupted && istate_from_uspace(istate))
    141105                thread_exit();
    142        
    143         /* Account exception handling */
    144         uint64_t end_cycle = get_cycle();
    145        
    146         irq_spinlock_lock(&exctbl_lock, false);
    147         exc_table[n].cycles += end_cycle - begin_cycle;
    148         exc_table[n].count++;
    149         irq_spinlock_unlock(&exctbl_lock, false);
    150        
    151         /* Do not charge THREAD for exception cycles */
    152         if (THREAD) {
    153                 irq_spinlock_lock(&THREAD->lock, false);
    154                 THREAD->last_cycle = end_cycle;
    155                 irq_spinlock_unlock(&THREAD->lock, false);
    156         }
    157 }
    158 
    159 /** Default 'null' exception handler
    160  *
    161  */
    162 NO_TRACE static void exc_undef(unsigned int n, istate_t *istate)
    163 {
    164         fault_if_from_uspace(istate, "Unhandled exception %u.", n);
    165         panic_badtrap(istate, n, "Unhandled exception %u.", n);
    166 }
    167 
    168 /** Terminate thread and task if exception came from userspace.
    169  *
    170  */
    171 NO_TRACE void fault_if_from_uspace(istate_t *istate, const char *fmt, ...)
    172 {
     106}
     107
     108/** Default 'null' exception handler */
     109static void exc_undef(int n, istate_t *istate)
     110{
     111        fault_if_from_uspace(istate, "Unhandled exception %d.", n);
     112        panic("Unhandled exception %d.", n);
     113}
     114
     115/** Terminate thread and task if exception came from userspace. */
     116void fault_if_from_uspace(istate_t *istate, char *fmt, ...)
     117{
     118        task_t *task = TASK;
     119        va_list args;
     120
    173121        if (!istate_from_uspace(istate))
    174122                return;
    175        
     123
    176124        printf("Task %s (%" PRIu64 ") killed due to an exception at "
    177             "program counter %p.\n", TASK->name, TASK->taskid,
    178             (void *) istate_get_pc(istate));
    179        
     125            "program counter %p.\n", task->name, task->taskid,
     126            istate_get_pc(istate));
     127
    180128        stack_trace_istate(istate);
    181        
     129
    182130        printf("Kill message: ");
    183        
    184         va_list args;
    185131        va_start(args, fmt);
    186132        vprintf(fmt, args);
    187133        va_end(args);
    188134        printf("\n");
    189        
     135
    190136        /*
    191137         * Userspace can subscribe for FAULT events to take action
     
    198144                event_notify_3(EVENT_FAULT, LOWER32(TASK->taskid),
    199145                    UPPER32(TASK->taskid), (unative_t) THREAD);
    200                
     146
    201147#ifdef CONFIG_UDEBUG
    202148                /* Wait for a debugging session. */
     
    204150#endif
    205151        }
    206        
    207         task_kill(TASK->taskid);
     152
     153        task_kill(task->taskid);
    208154        thread_exit();
    209155}
     
    211157#ifdef CONFIG_KCONSOLE
    212158
    213 static char flag_buf[MAX_CMDLINE + 1];
    214 
    215 /** Print all exceptions
    216  *
    217  */
    218 NO_TRACE static int cmd_exc_print(cmd_arg_t *argv)
    219 {
    220         bool excs_all;
    221        
    222         if (str_cmp(flag_buf, "-a") == 0)
    223                 excs_all = true;
    224         else if (str_cmp(flag_buf, "") == 0)
    225                 excs_all = false;
    226         else {
    227                 printf("Unknown argument \"%s\".\n", flag_buf);
    228                 return 1;
    229         }
    230        
     159/** kconsole cmd - print all exceptions */
     160static int cmd_exc_print(cmd_arg_t *argv)
     161{
    231162#if (IVT_ITEMS > 0)
    232163        unsigned int i;
    233         unsigned int rows;
    234        
    235         irq_spinlock_lock(&exctbl_lock, true);
    236        
     164        char *symbol;
     165
     166        spinlock_lock(&exctbl_lock);
     167
    237168#ifdef __32_BITS__
    238         printf("[exc   ] [description       ] [count   ] [cycles  ]"
    239             " [handler ] [symbol\n");
    240         rows = 1;
    241 #endif
    242        
     169        printf("Exc Description          Handler    Symbol\n");
     170        printf("--- -------------------- ---------- --------\n");
     171#endif
     172
    243173#ifdef __64_BITS__
    244         printf("[exc   ] [description       ] [count   ] [cycles  ]"
    245             " [handler         ]\n");
    246         printf("         [symbol\n");
    247         rows = 2;
     174        printf("Exc Description          Handler            Symbol\n");
     175        printf("--- -------------------- ------------------ --------\n");
    248176#endif
    249177       
    250178        for (i = 0; i < IVT_ITEMS; i++) {
    251                 if ((!excs_all) && (!exc_table[i].hot))
    252                         continue;
     179                symbol = symtab_fmt_name_lookup((unative_t) exc_table[i].f);
     180
     181#ifdef __32_BITS__
     182                printf("%-3u %-20s %10p %s\n", i + IVT_FIRST, exc_table[i].name,
     183                        exc_table[i].f, symbol);
     184#endif
     185
     186#ifdef __64_BITS__
     187                printf("%-3u %-20s %18p %s\n", i + IVT_FIRST, exc_table[i].name,
     188                        exc_table[i].f, symbol);
     189#endif
    253190               
    254                 uint64_t count;
    255                 char count_suffix;
    256                
    257                 order_suffix(exc_table[i].count, &count, &count_suffix);
    258                
    259                 uint64_t cycles;
    260                 char cycles_suffix;
    261                
    262                 order_suffix(exc_table[i].cycles, &cycles, &cycles_suffix);
    263                
    264                 const char *symbol =
    265                     symtab_fmt_name_lookup((unative_t) exc_table[i].handler);
    266                
    267 #ifdef __32_BITS__
    268                 printf("%-8u %-20s %9" PRIu64 "%c %9" PRIu64 "%c %10p %s\n",
    269                     i + IVT_FIRST, exc_table[i].name, count, count_suffix,
    270                     cycles, cycles_suffix, exc_table[i].handler, symbol);
    271                
    272                 PAGING(rows, 1, irq_spinlock_unlock(&exctbl_lock, true),
    273                     irq_spinlock_lock(&exctbl_lock, true));
    274 #endif
    275                
    276 #ifdef __64_BITS__
    277                 printf("%-8u %-20s %9" PRIu64 "%c %9" PRIu64 "%c %18p\n",
    278                     i + IVT_FIRST, exc_table[i].name, count, count_suffix,
    279                     cycles, cycles_suffix, exc_table[i].handler);
    280                 printf("         %s\n", symbol);
    281                
    282                 PAGING(rows, 2, irq_spinlock_unlock(&exctbl_lock, true),
    283                     irq_spinlock_lock(&exctbl_lock, true));
    284 #endif
     191                if (((i + 1) % 20) == 0) {
     192                        printf(" -- Press any key to continue -- ");
     193                        spinlock_unlock(&exctbl_lock);
     194                        indev_pop_character(stdin);
     195                        spinlock_lock(&exctbl_lock);
     196                        printf("\n");
     197                }
    285198        }
    286199       
    287         irq_spinlock_unlock(&exctbl_lock, true);
    288 #else /* (IVT_ITEMS > 0) */
    289        
    290         printf("No exception table%s.\n", excs_all ? " (showing all exceptions)" : "");
    291        
    292 #endif /* (IVT_ITEMS > 0) */
     200        spinlock_unlock(&exctbl_lock);
     201#endif
    293202       
    294203        return 1;
    295204}
    296205
    297 static cmd_arg_t exc_argv = {
    298         .type = ARG_TYPE_STRING_OPTIONAL,
    299         .buffer = flag_buf,
    300         .len = sizeof(flag_buf)
    301 };
    302206
    303207static cmd_info_t exc_info = {
    304208        .name = "exc",
    305         .description = "Print exception table (use -a for all exceptions).",
     209        .description = "Print exception table.",
    306210        .func = cmd_exc_print,
    307211        .help = NULL,
    308         .argc = 1,
    309         .argv = &exc_argv
     212        .argc = 0,
     213        .argv = NULL
    310214};
    311215
    312 #endif /* CONFIG_KCONSOLE */
    313 
    314 /** Initialize generic exception handling support
    315  *
    316  */
     216#endif
     217
     218/** Initialize generic exception handling support */
    317219void exc_init(void)
    318220{
    319         (void) exc_undef;
    320        
    321 #if (IVT_ITEMS > 0)
    322         unsigned int i;
    323        
     221        int i;
     222
    324223        for (i = 0; i < IVT_ITEMS; i++)
    325                 exc_register(i, "undef", false, (iroutine_t) exc_undef);
    326 #endif
    327        
     224                exc_register(i, "undef", (iroutine) exc_undef);
     225
    328226#ifdef CONFIG_KCONSOLE
    329227        cmd_initialize(&exc_info);
Note: See TracChangeset for help on using the changeset viewer.