Ignore:
File:
1 edited

Legend:

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

    r04e3d9f rcd98e594  
    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
     
    5352#include <symtab.h>
    5453#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);
     54
     55static struct {
     56        const char *name;
     57        iroutine f;
     58} exc_table[IVT_ITEMS];
     59
     60SPINLOCK_INITIALIZE(exctbl_lock);
    6161
    6262/** 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)
     63 *
     64 * @param n Exception number
     65 * @param name Description
     66 * @param f Exception handler
     67 */
     68iroutine exc_register(int n, const char *name, iroutine f)
     69{
    7770        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;
     71       
     72        iroutine old;
     73       
     74        spinlock_lock(&exctbl_lock);
     75       
     76        old = exc_table[n].f;
     77        exc_table[n].f = f;
    8478        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);
     79       
     80        spinlock_unlock(&exctbl_lock);
    9081       
    9182        return old;
     
    9687 * Called directly from the assembler code.
    9788 * 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)
     89 */
     90void exc_dispatch(int n, istate_t *istate)
     91{
    10392        ASSERT(n < IVT_ITEMS);
    104 #endif
    105        
     93
    10694        /* Account user cycles */
    10795        if (THREAD) {
    108                 irq_spinlock_lock(&THREAD->lock, false);
     96                spinlock_lock(&THREAD->lock);
    10997                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        
     98                spinlock_unlock(&THREAD->lock);
     99        }
     100
    127101#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        
     102        if (THREAD) THREAD->udebug.uspace_state = istate;
     103#endif
     104       
     105        exc_table[n].f(n + IVT_FIRST, istate);
     106
    134107#ifdef CONFIG_UDEBUG
    135         if (THREAD)
    136                 THREAD->udebug.uspace_state = NULL;
    137 #endif
    138        
     108        if (THREAD) THREAD->udebug.uspace_state = NULL;
     109#endif
     110
    139111        /* This is a safe place to exit exiting thread */
    140         if ((THREAD) && (THREAD->interrupted) && (istate_from_uspace(istate)))
     112        if (THREAD && THREAD->interrupted && istate_from_uspace(istate))
    141113                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 */
     114
    152115        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("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 {
     116                spinlock_lock(&THREAD->lock);
     117                thread_update_accounting(false);
     118                spinlock_unlock(&THREAD->lock);
     119        }
     120}
     121
     122/** Default 'null' exception handler */
     123static void exc_undef(int n, istate_t *istate)
     124{
     125        fault_if_from_uspace(istate, "Unhandled exception %d.", n);
     126        panic("Unhandled exception %d.", n);
     127}
     128
     129/** Terminate thread and task if exception came from userspace. */
     130void fault_if_from_uspace(istate_t *istate, const char *fmt, ...)
     131{
     132        task_t *task = TASK;
     133        va_list args;
     134
    173135        if (!istate_from_uspace(istate))
    174136                return;
    175        
     137
    176138        printf("Task %s (%" PRIu64 ") killed due to an exception at "
    177             "program counter %p.\n", TASK->name, TASK->taskid,
     139            "program counter %p.\n", task->name, task->taskid,
    178140            istate_get_pc(istate));
    179        
     141
    180142        stack_trace_istate(istate);
    181        
     143
    182144        printf("Kill message: ");
    183        
    184         va_list args;
    185145        va_start(args, fmt);
    186146        vprintf(fmt, args);
    187147        va_end(args);
    188148        printf("\n");
    189        
     149
    190150        /*
    191151         * Userspace can subscribe for FAULT events to take action
     
    198158                event_notify_3(EVENT_FAULT, LOWER32(TASK->taskid),
    199159                    UPPER32(TASK->taskid), (unative_t) THREAD);
    200                
     160
    201161#ifdef CONFIG_UDEBUG
    202162                /* Wait for a debugging session. */
     
    204164#endif
    205165        }
    206        
    207         task_kill(TASK->taskid);
     166
     167        task_kill(task->taskid);
    208168        thread_exit();
    209169}
     
    211171#ifdef CONFIG_KCONSOLE
    212172
    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        
     173/** kconsole cmd - print all exceptions */
     174static int cmd_exc_print(cmd_arg_t *argv)
     175{
    231176#if (IVT_ITEMS > 0)
    232177        unsigned int i;
    233         unsigned int rows;
    234        
    235         irq_spinlock_lock(&exctbl_lock, true);
    236        
     178
     179        spinlock_lock(&exctbl_lock);
     180
    237181#ifdef __32_BITS__
    238         printf("[exc   ] [description       ] [count   ] [cycles  ]"
    239             " [handler ] [symbol\n");
    240         rows = 1;
    241 #endif
    242        
     182        printf("Exc Description          Handler    Symbol\n");
     183        printf("--- -------------------- ---------- --------\n");
     184#endif
     185
    243186#ifdef __64_BITS__
    244         printf("[exc   ] [description       ] [count   ] [cycles  ]"
    245             " [handler         ]\n");
    246         printf("         [symbol\n");
    247         rows = 2;
     187        printf("Exc Description          Handler            Symbol\n");
     188        printf("--- -------------------- ------------------ --------\n");
    248189#endif
    249190       
    250191        for (i = 0; i < IVT_ITEMS; i++) {
    251                 if ((!excs_all) && (!exc_table[i].hot))
    252                         continue;
     192                const char *symbol = symtab_fmt_name_lookup((unative_t) exc_table[i].f);
     193
     194#ifdef __32_BITS__
     195                printf("%-3u %-20s %10p %s\n", i + IVT_FIRST, exc_table[i].name,
     196                        exc_table[i].f, symbol);
     197#endif
     198
     199#ifdef __64_BITS__
     200                printf("%-3u %-20s %18p %s\n", i + IVT_FIRST, exc_table[i].name,
     201                        exc_table[i].f, symbol);
     202#endif
    253203               
    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
    285         }
    286        
    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) */
     204                if (((i + 1) % 20) == 0) {
     205                        printf(" -- Press any key to continue -- ");
     206                        spinlock_unlock(&exctbl_lock);
     207                        indev_pop_character(stdin);
     208                        spinlock_lock(&exctbl_lock);
     209                        printf("\n");
     210                }
     211        }
     212       
     213        spinlock_unlock(&exctbl_lock);
     214#endif
    293215       
    294216        return 1;
    295217}
    296218
    297 static cmd_arg_t exc_argv = {
    298         .type = ARG_TYPE_STRING_OPTIONAL,
    299         .buffer = flag_buf,
    300         .len = sizeof(flag_buf)
    301 };
    302219
    303220static cmd_info_t exc_info = {
    304221        .name = "exc",
    305         .description = "Print exception table (use -a for all exceptions).",
     222        .description = "Print exception table.",
    306223        .func = cmd_exc_print,
    307224        .help = NULL,
    308         .argc = 1,
    309         .argv = &exc_argv
     225        .argc = 0,
     226        .argv = NULL
    310227};
    311228
    312 #endif /* CONFIG_KCONSOLE */
    313 
    314 /** Initialize generic exception handling support
    315  *
    316  */
     229#endif
     230
     231/** Initialize generic exception handling support */
    317232void exc_init(void)
    318233{
    319         (void) exc_undef;
    320        
    321 #if (IVT_ITEMS > 0)
    322         unsigned int i;
    323        
     234        int i;
     235
    324236        for (i = 0; i < IVT_ITEMS; i++)
    325                 exc_register(i, "undef", false, (iroutine_t) exc_undef);
    326 #endif
    327        
     237                exc_register(i, "undef", (iroutine) exc_undef);
     238
    328239#ifdef CONFIG_KCONSOLE
    329240        cmd_initialize(&exc_info);
Note: See TracChangeset for help on using the changeset viewer.