Subversion Repositories HelenOS

Rev

Rev 3343 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2005 Jakub Jermar
  3.  * Copyright (c) 2005 Jakub Vana
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  *
  10.  * - Redistributions of source code must retain the above copyright
  11.  *   notice, this list of conditions and the following disclaimer.
  12.  * - Redistributions in binary form must reproduce the above copyright
  13.  *   notice, this list of conditions and the following disclaimer in the
  14.  *   documentation and/or other materials provided with the distribution.
  15.  * - The name of the author may not be used to endorse or promote products
  16.  *   derived from this software without specific prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  19.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  22.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28.  */
  29.  
  30. /** @addtogroup ia64interrupt
  31.  * @{
  32.  */
  33. /** @file
  34.  */
  35.  
  36. #include <arch/interrupt.h>
  37. #include <interrupt.h>
  38. #include <ddi/irq.h>
  39. #include <panic.h>
  40. #include <print.h>
  41. #include <symtab.h>
  42. #include <debug.h>
  43. #include <console/console.h>
  44. #include <arch/types.h>
  45. #include <arch/asm.h>
  46. #include <arch/barrier.h>
  47. #include <arch/register.h>
  48. #include <arch.h>
  49. #include <syscall/syscall.h>
  50. #include <print.h>
  51. #include <proc/scheduler.h>
  52. #include <ipc/sysipc.h>
  53. #include <ipc/irq.h>
  54. #include <ipc/ipc.h>
  55. #include <synch/spinlock.h>
  56. #include <mm/tlb.h>
  57.  
  58. #define VECTORS_64_BUNDLE   20
  59. #define VECTORS_16_BUNDLE   48
  60. #define VECTORS_16_BUNDLE_START 0x5000
  61. #define VECTOR_MAX      0x7f00
  62.  
  63. #define BUNDLE_SIZE     16
  64.  
  65. char *vector_names_64_bundle[VECTORS_64_BUNDLE] = {
  66.     "VHPT Translation vector",
  67.     "Instruction TLB vector",
  68.     "Data TLB vector",
  69.     "Alternate Instruction TLB vector",
  70.     "Alternate Data TLB vector",
  71.     "Data Nested TLB vector",
  72.     "Instruction Key Miss vector",
  73.     "Data Key Miss vector",
  74.     "Dirty-Bit vector",
  75.     "Instruction Access-Bit vector",
  76.     "Data Access-Bit vector"
  77.     "Break Instruction vector",
  78.     "External Interrupt vector"
  79.     "Reserved",
  80.     "Reserved",
  81.     "Reserved",
  82.     "Reserved",
  83.     "Reserved",
  84.     "Reserved",
  85.     "Reserved"
  86. };
  87.  
  88. char *vector_names_16_bundle[VECTORS_16_BUNDLE] = {
  89.     "Page Not Present vector",
  90.     "Key Permission vector",
  91.     "Instruction Access rights vector",
  92.     "Data Access Rights vector",
  93.     "General Exception vector",
  94.     "Disabled FP-Register vector",
  95.     "NaT Consumption vector",
  96.     "Speculation vector",
  97.     "Reserved",
  98.     "Debug vector",
  99.     "Unaligned Reference vector",
  100.     "Unsupported Data Reference vector",
  101.     "Floating-point Fault vector",
  102.     "Floating-point Trap vector",
  103.     "Lower-Privilege Transfer Trap vector",
  104.     "Taken Branch Trap vector",
  105.     "Single Step Trap vector",
  106.     "Reserved",
  107.     "Reserved",
  108.     "Reserved",
  109.     "Reserved",
  110.     "Reserved",
  111.     "Reserved",
  112.     "Reserved",
  113.     "Reserved",
  114.     "IA-32 Exception vector",
  115.     "IA-32 Intercept vector",
  116.     "IA-32 Interrupt vector",
  117.     "Reserved",
  118.     "Reserved",
  119.     "Reserved"
  120. };
  121.  
  122. static char *vector_to_string(uint16_t vector);
  123. static void dump_interrupted_context(istate_t *istate);
  124.  
  125. char *vector_to_string(uint16_t vector)
  126. {
  127.     ASSERT(vector <= VECTOR_MAX);
  128.    
  129.     if (vector >= VECTORS_16_BUNDLE_START)
  130.         return vector_names_16_bundle[(vector -
  131.             VECTORS_16_BUNDLE_START) / (16 * BUNDLE_SIZE)];
  132.     else
  133.         return vector_names_64_bundle[vector / (64 * BUNDLE_SIZE)];
  134. }
  135.  
  136. void dump_interrupted_context(istate_t *istate)
  137. {
  138.     char *ifa, *iipa, *iip;
  139.  
  140.     ifa = get_symtab_entry(istate->cr_ifa);
  141.     iipa = get_symtab_entry(istate->cr_iipa);
  142.     iip = get_symtab_entry(istate->cr_iip);
  143.  
  144.     putchar('\n');
  145.     printf("Interrupted context dump:\n");
  146.     printf("ar.bsp=%p\tar.bspstore=%p\n", istate->ar_bsp,
  147.         istate->ar_bspstore);
  148.     printf("ar.rnat=%#018llx\tar.rsc=%#018llx\n", istate->ar_rnat,
  149.         istate->ar_rsc);
  150.     printf("ar.ifs=%#018llx\tar.pfs=%#018llx\n", istate->ar_ifs,
  151.         istate->ar_pfs);
  152.     printf("cr.isr=%#018llx\tcr.ipsr=%#018llx\t\n", istate->cr_isr.value,
  153.         istate->cr_ipsr);
  154.    
  155.     printf("cr.iip=%#018llx, #%d\t(%s)\n", istate->cr_iip,
  156.         istate->cr_isr.ei, iip);
  157.     printf("cr.iipa=%#018llx\t(%s)\n", istate->cr_iipa, iipa);
  158.     printf("cr.ifa=%#018llx\t(%s)\n", istate->cr_ifa, ifa);
  159. }
  160.  
  161. void general_exception(uint64_t vector, istate_t *istate)
  162. {
  163.     char *desc = "";
  164.  
  165.     switch (istate->cr_isr.ge_code) {
  166.     case GE_ILLEGALOP:
  167.         desc = "Illegal Operation fault";
  168.         break;
  169.     case GE_PRIVOP:
  170.         desc = "Privileged Operation fault";
  171.         break;
  172.     case GE_PRIVREG:
  173.         desc = "Privileged Register fault";
  174.         break;
  175.     case GE_RESREGFLD:
  176.         desc = "Reserved Register/Field fault";
  177.         break;
  178.     case GE_DISBLDISTRAN:
  179.         desc = "Disabled Instruction Set Transition fault";
  180.         break;
  181.     case GE_ILLEGALDEP:
  182.         desc = "Illegal Dependency fault";
  183.         break;
  184.     default:
  185.         desc = "unknown";
  186.         break;
  187.     }
  188.  
  189.     fault_if_from_uspace(istate, "General Exception (%s)", desc);
  190.  
  191.     dump_interrupted_context(istate);
  192.     panic("General Exception (%s)\n", desc);
  193. }
  194.  
  195. void disabled_fp_register(uint64_t vector, istate_t *istate)
  196. {
  197. #ifdef CONFIG_FPU_LAZY
  198.     scheduler_fpu_lazy_request();  
  199. #else
  200.     fault_if_from_uspace(istate, "Interruption: %#hx (%s)",
  201.         (uint16_t) vector, vector_to_string(vector));
  202.     dump_interrupted_context(istate);
  203.     panic("Interruption: %#hx (%s)\n", (uint16_t) vector,
  204.         vector_to_string(vector));
  205. #endif
  206. }
  207.  
  208. void nop_handler(uint64_t vector, istate_t *istate)
  209. {
  210. }
  211.  
  212. /** Handle syscall. */
  213. int break_instruction(uint64_t vector, istate_t *istate)
  214. {
  215.     /*
  216.      * Move to next instruction after BREAK.
  217.      */
  218.     if (istate->cr_ipsr.ri == 2) {
  219.         istate->cr_ipsr.ri = 0;
  220.         istate->cr_iip += 16;
  221.     } else {
  222.         istate->cr_ipsr.ri++;
  223.     }
  224.  
  225.     return syscall_handler(istate->in0, istate->in1, istate->in2,
  226.         istate->in3, istate->in4, istate->in5, istate->in6);
  227. }
  228.  
  229. void universal_handler(uint64_t vector, istate_t *istate)
  230. {
  231.     fault_if_from_uspace(istate, "Interruption: %#hx (%s)\n",
  232.         (uint16_t) vector, vector_to_string(vector));
  233.     dump_interrupted_context(istate);
  234.     panic("Interruption: %#hx (%s)\n", (uint16_t) vector,
  235.         vector_to_string(vector));
  236. }
  237.  
  238. static void end_of_local_irq(void)
  239. {
  240.     asm volatile ("mov cr.eoi=r0;;");
  241. }
  242.  
  243.  
  244. void external_interrupt(uint64_t vector, istate_t *istate)
  245. {
  246.     cr_ivr_t ivr;
  247.    
  248.     ivr.value = ivr_read();
  249.     srlz_d();
  250.  
  251.         switch (ivr.vector) {
  252.         case INTERRUPT_SPURIOUS:
  253. #ifdef CONFIG_DEBUG
  254.             printf("cpu%d: spurious interrupt\n", CPU->id);
  255. #endif
  256.             break;
  257.  
  258. #ifdef CONFIG_SMP
  259.         case VECTOR_TLB_SHOOTDOWN_IPI:
  260.             tlb_shootdown_ipi_recv();
  261.             end_of_local_irq();
  262.             break;
  263. #endif
  264.  
  265.         case INTERRUPT_TIMER:
  266.             {
  267.  
  268.                 irq_t *irq = irq_dispatch_and_lock(ivr.vector);
  269.                 if (irq) {
  270.                     irq->handler(irq, irq->arg);
  271.                     spinlock_unlock(&irq->lock);
  272.                 } else {
  273.                     panic("\nUnhandled Internal Timer Interrupt (%d)\n",ivr.vector);
  274.                 }
  275.             }  
  276.             break;
  277.                
  278.         default:
  279.             {
  280.  
  281.                 int ack=false;
  282.                 irq_t *irq = irq_dispatch_and_lock(ivr.vector);
  283.                 if (irq) {
  284.                     /*
  285.                      * The IRQ handler was found.
  286.                      */
  287.          
  288.                     if (irq->preack) {
  289.                         /* Send EOI before processing the interrupt */
  290.                         end_of_local_irq();
  291.                         ack=true;
  292.                     }
  293.                     irq->handler(irq, irq->arg);
  294.                     spinlock_unlock(&irq->lock);
  295.                 } else {
  296.                     /*
  297.                      * Unhandled interrupt.
  298.                      */
  299.                     end_of_local_irq();
  300.                     ack=true;
  301. #ifdef CONFIG_DEBUG
  302.                     printf("\nUnhandled External Interrupt Vector %d\n",ivr.vector);
  303. #endif
  304.                 }
  305.                 if(!ack) end_of_local_irq();
  306.  
  307.             }  
  308.  
  309.  
  310.             break;
  311.         }
  312. }
  313.  
  314. /** @}
  315.  */
  316.