exception.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * Copyright (c) 2006-2019, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-12-04 Jiaxun Yang Initial version
  9. */
  10. #include <rtthread.h>
  11. #include <rthw.h>
  12. #include "exception.h"
  13. #include "mips_regs.h"
  14. /**
  15. * @addtogroup MIPS
  16. */
  17. /*@{*/
  18. extern rt_ubase_t __ebase_entry;
  19. rt_ubase_t rt_interrupt_from_thread;
  20. rt_ubase_t rt_interrupt_to_thread;
  21. rt_ubase_t rt_thread_switch_interrupt_flag;
  22. rt_base_t rt_hw_interrupt_disable(void)
  23. {
  24. rt_base_t status = read_c0_status();
  25. clear_c0_status(ST0_IE);
  26. return status;
  27. }
  28. void rt_hw_interrupt_enable(rt_base_t level)
  29. {
  30. write_c0_status(level);
  31. }
  32. /**
  33. * exception handle table
  34. */
  35. #define RT_EXCEPTION_MAX 31
  36. exception_func_t sys_exception_handlers[RT_EXCEPTION_MAX];
  37. /**
  38. * setup the exception handle
  39. */
  40. exception_func_t rt_set_except_vector(int n, exception_func_t func)
  41. {
  42. exception_func_t old_handler = sys_exception_handlers[n];
  43. if ((n == 0) || (n > RT_EXCEPTION_MAX) || (!func))
  44. {
  45. return 0;
  46. }
  47. sys_exception_handlers[n] = func;
  48. return old_handler;
  49. }
  50. void mips_dump_regs(struct pt_regs *regs) {
  51. int i, j;
  52. for(i = 0; i < 32 / 4; i++) {
  53. for(j = 0; j < 4; j++) {
  54. int reg = 4 * i + j;
  55. rt_kprintf("%d: 0x%08x, ", reg, regs->regs[reg]);
  56. }
  57. rt_kprintf("\n");
  58. }
  59. }
  60. void tlb_refill_handler(void)
  61. {
  62. rt_kprintf("TLB-Miss Happens, EPC: 0x%08x\n", read_c0_epc());
  63. rt_hw_cpu_shutdown();
  64. }
  65. void cache_error_handler(void)
  66. {
  67. rt_kprintf("Cache Exception Happens, EPC: 0x%08x\n", read_c0_epc());
  68. rt_hw_cpu_shutdown();
  69. }
  70. static void unhandled_exception_handle(struct pt_regs *regs)
  71. {
  72. rt_kprintf("Unknown Exception, EPC: 0x%08x, CAUSE: 0x%08x\n", read_c0_epc(), read_c0_cause());
  73. rt_kprintf("ST0: 0x%08x ",regs->cp0_status);
  74. rt_kprintf("ErrorPC: 0x%08x\n",read_c0_errorepc());
  75. mips_dump_regs(regs);
  76. rt_hw_cpu_shutdown();
  77. }
  78. static void install_default_exception_handler(void)
  79. {
  80. rt_int32_t i;
  81. for (i=0; i<RT_EXCEPTION_MAX; i++)
  82. sys_exception_handlers[i] = (exception_func_t)unhandled_exception_handle;
  83. }
  84. int rt_hw_exception_init(void)
  85. {
  86. rt_ubase_t ebase = (rt_ubase_t)&__ebase_entry;
  87. #ifdef ARCH_MIPS64
  88. ebase |= 0xffffffff00000000;
  89. #endif
  90. write_c0_ebase(ebase);
  91. clear_c0_status(ST0_BEV | ST0_ERL | ST0_EXL);
  92. clear_c0_status(ST0_IM | ST0_IE);
  93. set_c0_status(ST0_CU0);
  94. /* install the default exception handler */
  95. install_default_exception_handler();
  96. return RT_EOK;
  97. }
  98. void rt_general_exc_dispatch(struct pt_regs *regs)
  99. {
  100. rt_ubase_t exccode = 0;
  101. if (exccode == 0) {
  102. rt_ubase_t status, pending;
  103. status = read_c0_status();
  104. pending = (CAUSEF_IP) & (status & ST0_IM);
  105. if (pending & CAUSEF_IP0)
  106. rt_do_mips_cpu_irq(0);
  107. if (pending & CAUSEF_IP1)
  108. rt_do_mips_cpu_irq(1);
  109. if (pending & CAUSEF_IP2)
  110. rt_do_mips_cpu_irq(2);
  111. if (pending & CAUSEF_IP3)
  112. rt_do_mips_cpu_irq(3);
  113. if (pending & CAUSEF_IP4)
  114. rt_do_mips_cpu_irq(4);
  115. if (pending & CAUSEF_IP5)
  116. rt_do_mips_cpu_irq(5);
  117. if (pending & CAUSEF_IP6)
  118. rt_do_mips_cpu_irq(6);
  119. if (pending & CAUSEF_IP7)
  120. rt_do_mips_cpu_irq(7);
  121. } else {
  122. if (sys_exception_handlers[exccode])
  123. sys_exception_handlers[exccode](regs);
  124. }
  125. }
  126. /* Mask means disable the interrupt */
  127. void mips_mask_cpu_irq(rt_uint32_t irq)
  128. {
  129. clear_c0_status(1 << (STATUSB_IP0 + irq));
  130. }
  131. /* Unmask means enable the interrupt */
  132. void mips_unmask_cpu_irq(rt_uint32_t irq)
  133. {
  134. set_c0_status(1 << (STATUSB_IP0 + irq));
  135. }
  136. /*@}*/