Ignore:
File:
1 edited

Legend:

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

    r5bcf1f9 r44b7783  
    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
     
    4544#include <console/console.h>
    4645#include <console/cmd.h>
    47 #include <synch/mutex.h>
    48 #include <time/delay.h>
    49 #include <macros.h>
    5046#include <panic.h>
    5147#include <print.h>
    5248#include <symtab.h>
    53 #include <proc/thread.h>
    54 #include <arch/cycle.h>
    55 #include <str.h>
    56 #include <trace.h>
    5749
    58 exc_table_t exc_table[IVT_ITEMS];
    59 IRQ_SPINLOCK_INITIALIZE(exctbl_lock);
     50static struct {
     51        const char *name;
     52        iroutine f;
     53} exc_table[IVT_ITEMS];
     54
     55SPINLOCK_INITIALIZE(exctbl_lock);
    6056
    6157/** Register exception handler
    62  *
    63  * @param n       Exception number.
    64  * @param name    Description.
    65  * @param hot     Whether the exception is actually handled
    66  *                in any meaningful way.
    67  * @param handler New exception handler.
    68  *
    69  * @return Previously registered exception handler.
    70  *
     58 *
     59 * @param n Exception number
     60 * @param name Description
     61 * @param f Exception handler
    7162 */
    72 iroutine_t exc_register(unsigned int n, const char *name, bool hot,
    73     iroutine_t handler)
     63iroutine exc_register(int n, const char *name, iroutine f)
    7464{
    75 #if (IVT_ITEMS > 0)
    7665        ASSERT(n < IVT_ITEMS);
    77 #endif
    7866       
    79         irq_spinlock_lock(&exctbl_lock, true);
     67        iroutine old;
    8068       
    81         iroutine_t old = exc_table[n].handler;
    82         exc_table[n].handler = handler;
     69        spinlock_lock(&exctbl_lock);
     70       
     71        old = exc_table[n].f;
     72        exc_table[n].f = f;
    8373        exc_table[n].name = name;
    84         exc_table[n].hot = hot;
    85         exc_table[n].cycles = 0;
    86         exc_table[n].count = 0;
    8774       
    88         irq_spinlock_unlock(&exctbl_lock, true);
     75        spinlock_unlock(&exctbl_lock);
    8976       
    9077        return old;
     
    9582 * Called directly from the assembler code.
    9683 * CPU is interrupts_disable()'d.
    97  *
    9884 */
    99 NO_TRACE void exc_dispatch(unsigned int n, istate_t *istate)
     85void exc_dispatch(int n, istate_t *istate)
    10086{
    101 #if (IVT_ITEMS > 0)
    10287        ASSERT(n < IVT_ITEMS);
     88
     89#ifdef CONFIG_UDEBUG
     90        if (THREAD) THREAD->udebug.uspace_state = istate;
    10391#endif
    10492       
    105         /* Account user cycles */
    106         if (THREAD) {
    107                 irq_spinlock_lock(&THREAD->lock, false);
    108                 thread_update_accounting(true);
    109                 irq_spinlock_unlock(&THREAD->lock, false);
    110         }
    111        
    112         /* Account CPU usage if it has waked up from sleep */
    113         if (CPU) {
    114                 irq_spinlock_lock(&CPU->lock, false);
    115                 if (CPU->idle) {
    116                         uint64_t now = get_cycle();
    117                         CPU->idle_cycles += now - CPU->last_cycle;
    118                         CPU->last_cycle = now;
    119                         CPU->idle = false;
    120                 }
    121                 irq_spinlock_unlock(&CPU->lock, false);
    122         }
    123        
    124         uint64_t begin_cycle = get_cycle();
    125        
     93        exc_table[n].f(n + IVT_FIRST, istate);
     94
    12695#ifdef CONFIG_UDEBUG
    127         if (THREAD)
    128                 THREAD->udebug.uspace_state = istate;
     96        if (THREAD) THREAD->udebug.uspace_state = NULL;
    12997#endif
    130        
    131         exc_table[n].handler(n + IVT_FIRST, istate);
    132        
    133 #ifdef CONFIG_UDEBUG
    134         if (THREAD)
    135                 THREAD->udebug.uspace_state = NULL;
    136 #endif
    137        
     98
    13899        /* This is a safe place to exit exiting thread */
    139         if ((THREAD) && (THREAD->interrupted) && (istate_from_uspace(istate)))
     100        if (THREAD && THREAD->interrupted && istate_from_uspace(istate))
    140101                thread_exit();
    141        
    142         /* Account exception handling */
    143         uint64_t end_cycle = get_cycle();
    144        
    145         irq_spinlock_lock(&exctbl_lock, false);
    146         exc_table[n].cycles += end_cycle - begin_cycle;
    147         exc_table[n].count++;
    148         irq_spinlock_unlock(&exctbl_lock, false);
    149        
    150         /* Do not charge THREAD for exception cycles */
    151         if (THREAD) {
    152                 irq_spinlock_lock(&THREAD->lock, false);
    153                 THREAD->last_cycle = end_cycle;
    154                 irq_spinlock_unlock(&THREAD->lock, false);
    155         }
    156102}
    157103
    158 /** Default 'null' exception handler
    159  *
    160  */
    161 NO_TRACE static void exc_undef(unsigned int n, istate_t *istate)
     104/** Default 'null' exception handler */
     105static void exc_undef(int n, istate_t *istate)
    162106{
    163         fault_if_from_uspace(istate, "Unhandled exception %u.", n);
    164         panic_badtrap(istate, n, "Unhandled exception %u.", n);
    165 }
    166 
    167 /** Terminate thread and task if exception came from userspace.
    168  *
    169  */
    170 NO_TRACE void fault_if_from_uspace(istate_t *istate, const char *fmt, ...)
    171 {
    172         if (!istate_from_uspace(istate))
    173                 return;
    174        
    175         printf("Task %s (%" PRIu64 ") killed due to an exception at "
    176             "program counter %p.\n", TASK->name, TASK->taskid,
    177             (void *) istate_get_pc(istate));
    178        
    179         stack_trace_istate(istate);
    180        
    181         printf("Kill message: ");
    182        
    183         va_list args;
    184         va_start(args, fmt);
    185         vprintf(fmt, args);
    186         va_end(args);
    187         printf("\n");
    188        
    189         task_kill_self(true);
    190 }
    191 
    192 /** Get istate structure of a thread.
    193  *
    194  * Get pointer to the istate structure at the bottom of the kernel stack.
    195  *
    196  * This function can be called in interrupt or user context. In interrupt
    197  * context the istate structure is created by the low-level exception
    198  * handler. In user context the istate structure is created by the
    199  * low-level syscall handler.
    200  */
    201 istate_t *istate_get(thread_t *thread)
    202 {
    203         /*
    204          * The istate structure should be right at the bottom of the kernel
    205          * stack.
    206          */
    207         return (istate_t *) ((uint8_t *) thread->kstack + THREAD_STACK_SIZE -
    208             sizeof(istate_t));
     107        fault_if_from_uspace(istate, "Unhandled exception %d.", n);
     108        panic("Unhandled exception %d.", n);
    209109}
    210110
    211111#ifdef CONFIG_KCONSOLE
    212112
    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)
     113/** kconsole cmd - print all exceptions */
     114static int cmd_exc_print(cmd_arg_t *argv)
    219115{
    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        
    231116#if (IVT_ITEMS > 0)
    232117        unsigned int i;
    233         unsigned int rows;
    234        
    235         irq_spinlock_lock(&exctbl_lock, true);
    236        
     118        char *symbol;
     119
     120        spinlock_lock(&exctbl_lock);
     121
    237122#ifdef __32_BITS__
    238         printf("[exc   ] [description       ] [count   ] [cycles  ]"
    239             " [handler ] [symbol\n");
    240         rows = 1;
     123        printf("Exc Description          Handler    Symbol\n");
     124        printf("--- -------------------- ---------- --------\n");
    241125#endif
    242        
     126
    243127#ifdef __64_BITS__
    244         printf("[exc   ] [description       ] [count   ] [cycles  ]"
    245             " [handler         ]\n");
    246         printf("         [symbol\n");
    247         rows = 2;
     128        printf("Exc Description          Handler            Symbol\n");
     129        printf("--- -------------------- ------------------ --------\n");
    248130#endif
    249131       
    250132        for (i = 0; i < IVT_ITEMS; i++) {
    251                 if ((!excs_all) && (!exc_table[i].hot))
    252                         continue;
    253                
    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((sysarg_t) exc_table[i].handler);
    266                
     133                symbol = symtab_fmt_name_lookup((unative_t) exc_table[i].f);
     134
    267135#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));
     136                printf("%-3u %-20s %10p %s\n", i + IVT_FIRST, exc_table[i].name,
     137                        exc_table[i].f, symbol);
     138#endif
     139
     140#ifdef __64_BITS__
     141                printf("%-3u %-20s %18p %s\n", i + IVT_FIRST, exc_table[i].name,
     142                        exc_table[i].f, symbol);
    274143#endif
    275144               
    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
     145                if (((i + 1) % 20) == 0) {
     146                        printf(" -- Press any key to continue -- ");
     147                        spinlock_unlock(&exctbl_lock);
     148                        indev_pop_character(stdin);
     149                        spinlock_lock(&exctbl_lock);
     150                        printf("\n");
     151                }
    285152        }
    286153       
    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) */
     154        spinlock_unlock(&exctbl_lock);
     155#endif
    293156       
    294157        return 1;
    295158}
    296159
    297 static cmd_arg_t exc_argv = {
    298         .type = ARG_TYPE_STRING_OPTIONAL,
    299         .buffer = flag_buf,
    300         .len = sizeof(flag_buf)
    301 };
    302160
    303161static cmd_info_t exc_info = {
    304162        .name = "exc",
    305         .description = "Print exception table (use -a for all exceptions).",
     163        .description = "Print exception table.",
    306164        .func = cmd_exc_print,
    307165        .help = NULL,
    308         .argc = 1,
    309         .argv = &exc_argv
     166        .argc = 0,
     167        .argv = NULL
    310168};
    311169
    312 #endif /* CONFIG_KCONSOLE */
     170#endif
    313171
    314 /** Initialize generic exception handling support
    315  *
    316  */
     172/** Initialize generic exception handling support */
    317173void exc_init(void)
    318174{
    319         (void) exc_undef;
    320        
    321 #if (IVT_ITEMS > 0)
    322         unsigned int i;
    323        
     175        int i;
     176
    324177        for (i = 0; i < IVT_ITEMS; i++)
    325                 exc_register(i, "undef", false, (iroutine_t) exc_undef);
    326 #endif
    327        
     178                exc_register(i, "undef", (iroutine) exc_undef);
     179
    328180#ifdef CONFIG_KCONSOLE
    329181        cmd_initialize(&exc_info);
Note: See TracChangeset for help on using the changeset viewer.