exception.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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. {
  52. int i, j;
  53. for (i = 0; i < 32 / 4; i++)
  54. {
  55. for (j = 0; j < 4; j++)
  56. {
  57. int reg = 4 * i + j;
  58. rt_kprintf("%d: 0x%08x, ", reg, regs->regs[reg]);
  59. }
  60. rt_kprintf("\n");
  61. }
  62. }
  63. void tlb_refill_handler(void)
  64. {
  65. rt_kprintf("TLB-Miss Happens, EPC: 0x%08x\n", read_c0_epc());
  66. rt_hw_cpu_shutdown();
  67. }
  68. void cache_error_handler(void)
  69. {
  70. rt_kprintf("Cache Exception Happens, EPC: 0x%08x\n", read_c0_epc());
  71. rt_hw_cpu_shutdown();
  72. }
  73. static void unhandled_exception_handle(struct pt_regs *regs)
  74. {
  75. rt_kprintf("Unknown Exception, EPC: 0x%08x, CAUSE: 0x%08x\n", read_c0_epc(),
  76. read_c0_cause());
  77. rt_kprintf("ST0: 0x%08x ", regs->cp0_status);
  78. rt_kprintf("ErrorPC: 0x%08x\n", read_c0_errorepc());
  79. mips_dump_regs(regs);
  80. rt_hw_cpu_shutdown();
  81. }
  82. static void install_default_exception_handler(void)
  83. {
  84. rt_int32_t i;
  85. for (i = 0; i < RT_EXCEPTION_MAX; i++)
  86. sys_exception_handlers[i] =
  87. (exception_func_t)unhandled_exception_handle;
  88. }
  89. int rt_hw_exception_init(void)
  90. {
  91. rt_ubase_t ebase = (rt_ubase_t)&__ebase_entry;
  92. #ifdef ARCH_MIPS64
  93. ebase |= 0xffffffff00000000;
  94. #endif
  95. write_c0_ebase(ebase);
  96. clear_c0_status(ST0_BEV | ST0_ERL | ST0_EXL);
  97. clear_c0_status(ST0_IM | ST0_IE);
  98. set_c0_status(ST0_CU0);
  99. /* install the default exception handler */
  100. install_default_exception_handler();
  101. return RT_EOK;
  102. }
  103. void rt_general_exc_dispatch(struct pt_regs *regs)
  104. {
  105. rt_ubase_t cause, exccode;
  106. cause = read_c0_cause();
  107. exccode = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE;
  108. if (exccode == 0)
  109. {
  110. rt_ubase_t status, pending;
  111. status = read_c0_status();
  112. pending = (cause & CAUSEF_IP) & (status & ST0_IM);
  113. if (pending & CAUSEF_IP0)
  114. rt_do_mips_cpu_irq(0);
  115. if (pending & CAUSEF_IP1)
  116. rt_do_mips_cpu_irq(1);
  117. if (pending & CAUSEF_IP2)
  118. rt_do_mips_cpu_irq(2);
  119. if (pending & CAUSEF_IP3)
  120. rt_do_mips_cpu_irq(3);
  121. if (pending & CAUSEF_IP4)
  122. rt_do_mips_cpu_irq(4);
  123. if (pending & CAUSEF_IP5)
  124. rt_do_mips_cpu_irq(5);
  125. if (pending & CAUSEF_IP6)
  126. rt_do_mips_cpu_irq(6);
  127. if (pending & CAUSEF_IP7)
  128. rt_do_mips_cpu_irq(7);
  129. }
  130. else
  131. {
  132. if (sys_exception_handlers[exccode])
  133. sys_exception_handlers[exccode](regs);
  134. }
  135. }
  136. /* Mask means disable the interrupt */
  137. void mips_mask_cpu_irq(rt_uint32_t irq)
  138. {
  139. clear_c0_status(1 << (STATUSB_IP0 + irq));
  140. }
  141. /* Unmask means enable the interrupt */
  142. void mips_unmask_cpu_irq(rt_uint32_t irq)
  143. {
  144. set_c0_status(1 << (STATUSB_IP0 + irq));
  145. }
  146. /*@}*/