interrupts.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2016-17 Microsemi Corporation.
  4. * Padmarao Begari, Microsemi Corporation <padmarao.begari@microsemi.com>
  5. *
  6. * Copyright (C) 2017 Andes Technology Corporation
  7. * Rick Chen, Andes Technology Corporation <rick@andestech.com>
  8. *
  9. * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
  10. */
  11. #include <common.h>
  12. #include <efi_loader.h>
  13. #include <hang.h>
  14. #include <irq_func.h>
  15. #include <asm/global_data.h>
  16. #include <asm/ptrace.h>
  17. #include <asm/system.h>
  18. #include <asm/encoding.h>
  19. DECLARE_GLOBAL_DATA_PTR;
  20. static void show_efi_loaded_images(uintptr_t epc)
  21. {
  22. efi_print_image_infos((void *)epc);
  23. }
  24. static void show_regs(struct pt_regs *regs)
  25. {
  26. #ifdef CONFIG_SHOW_REGS
  27. printf("\nSP: " REG_FMT " GP: " REG_FMT " TP: " REG_FMT "\n",
  28. regs->sp, regs->gp, regs->tp);
  29. printf("T0: " REG_FMT " T1: " REG_FMT " T2: " REG_FMT "\n",
  30. regs->t0, regs->t1, regs->t2);
  31. printf("S0: " REG_FMT " S1: " REG_FMT " A0: " REG_FMT "\n",
  32. regs->s0, regs->s1, regs->a0);
  33. printf("A1: " REG_FMT " A2: " REG_FMT " A3: " REG_FMT "\n",
  34. regs->a1, regs->a2, regs->a3);
  35. printf("A4: " REG_FMT " A5: " REG_FMT " A6: " REG_FMT "\n",
  36. regs->a4, regs->a5, regs->a6);
  37. printf("A7: " REG_FMT " S2: " REG_FMT " S3: " REG_FMT "\n",
  38. regs->a7, regs->s2, regs->s3);
  39. printf("S4: " REG_FMT " S5: " REG_FMT " S6: " REG_FMT "\n",
  40. regs->s4, regs->s5, regs->s6);
  41. printf("S7: " REG_FMT " S8: " REG_FMT " S9: " REG_FMT "\n",
  42. regs->s7, regs->s8, regs->s9);
  43. printf("S10: " REG_FMT " S11: " REG_FMT " T3: " REG_FMT "\n",
  44. regs->s10, regs->s11, regs->t3);
  45. printf("T4: " REG_FMT " T5: " REG_FMT " T6: " REG_FMT "\n",
  46. regs->t4, regs->t5, regs->t6);
  47. #endif
  48. }
  49. /**
  50. * instr_len() - get instruction length
  51. *
  52. * @i: low 16 bits of the instruction
  53. * Return: number of u16 in instruction
  54. */
  55. static int instr_len(u16 i)
  56. {
  57. if ((i & 0x03) != 0x03)
  58. return 1;
  59. /* Instructions with more than 32 bits are not yet specified */
  60. return 2;
  61. }
  62. /**
  63. * show_code() - display code leading to exception
  64. *
  65. * @epc: program counter
  66. */
  67. static void show_code(ulong epc)
  68. {
  69. u16 *pos = (u16 *)(epc & ~1UL);
  70. int i, len = instr_len(*pos);
  71. printf("\nCode: ");
  72. for (i = -8; i; ++i)
  73. printf("%04x ", pos[i]);
  74. printf("(");
  75. for (i = 0; i < len; ++i)
  76. printf("%04x%s", pos[i], i + 1 == len ? ")\n" : " ");
  77. }
  78. static void _exit_trap(ulong code, ulong epc, ulong tval, struct pt_regs *regs)
  79. {
  80. static const char * const exception_code[] = {
  81. "Instruction address misaligned",
  82. "Instruction access fault",
  83. "Illegal instruction",
  84. "Breakpoint",
  85. "Load address misaligned",
  86. "Load access fault",
  87. "Store/AMO address misaligned",
  88. "Store/AMO access fault",
  89. "Environment call from U-mode",
  90. "Environment call from S-mode",
  91. "Reserved",
  92. "Environment call from M-mode",
  93. "Instruction page fault",
  94. "Load page fault",
  95. "Reserved",
  96. "Store/AMO page fault",
  97. };
  98. if (code < ARRAY_SIZE(exception_code))
  99. printf("Unhandled exception: %s\n", exception_code[code]);
  100. else
  101. printf("Unhandled exception code: %ld\n", code);
  102. printf("EPC: " REG_FMT " RA: " REG_FMT " TVAL: " REG_FMT "\n",
  103. epc, regs->ra, tval);
  104. /* Print relocation adjustments, but only if gd is initialized */
  105. if (gd && gd->flags & GD_FLG_RELOC)
  106. printf("EPC: " REG_FMT " RA: " REG_FMT " reloc adjusted\n",
  107. epc - gd->reloc_off, regs->ra - gd->reloc_off);
  108. show_regs(regs);
  109. show_code(epc);
  110. show_efi_loaded_images(epc);
  111. panic("\n");
  112. }
  113. int interrupt_init(void)
  114. {
  115. return 0;
  116. }
  117. /*
  118. * enable interrupts
  119. */
  120. void enable_interrupts(void)
  121. {
  122. }
  123. /*
  124. * disable interrupts
  125. */
  126. int disable_interrupts(void)
  127. {
  128. return 0;
  129. }
  130. ulong handle_trap(ulong cause, ulong epc, ulong tval, struct pt_regs *regs)
  131. {
  132. ulong is_irq, irq;
  133. /* An UEFI application may have changed gd. Restore U-Boot's gd. */
  134. efi_restore_gd();
  135. is_irq = (cause & MCAUSE_INT);
  136. irq = (cause & ~MCAUSE_INT);
  137. if (is_irq) {
  138. switch (irq) {
  139. case IRQ_M_EXT:
  140. case IRQ_S_EXT:
  141. external_interrupt(0); /* handle external interrupt */
  142. break;
  143. case IRQ_M_TIMER:
  144. case IRQ_S_TIMER:
  145. timer_interrupt(0); /* handle timer interrupt */
  146. break;
  147. default:
  148. _exit_trap(cause, epc, tval, regs);
  149. break;
  150. };
  151. } else {
  152. _exit_trap(cause, epc, tval, regs);
  153. }
  154. return epc;
  155. }
  156. /*
  157. *Entry Point for PLIC Interrupt Handler
  158. */
  159. __attribute__((weak)) void external_interrupt(struct pt_regs *regs)
  160. {
  161. }
  162. __attribute__((weak)) void timer_interrupt(struct pt_regs *regs)
  163. {
  164. }