user_exceptions.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /*
  2. * Copyright 2015 Dius Computing Pty Ltd. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * - Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * - Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the
  13. * distribution.
  14. * - Neither the name of the copyright holders nor the names of
  15. * its contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  22. * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  23. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  25. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  27. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  29. * OF THE POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. * @author Johny Mattsson <jmattsson@dius.com.au>
  32. */
  33. #include "user_exceptions.h"
  34. #define LOAD_MASK 0x00f00fu
  35. #define L8UI_MATCH 0x000002u
  36. #define L16UI_MATCH 0x001002u
  37. #define L16SI_MATCH 0x009002u
  38. static exception_handler_fn load_store_handler;
  39. void load_non_32_wide_handler (struct exception_frame *ef, uint32_t cause)
  40. {
  41. /* If this is not EXCCAUSE_LOAD_STORE_ERROR you're doing it wrong! */
  42. (void)cause;
  43. uint32_t epc1 = ef->epc;
  44. uint32_t excvaddr;
  45. uint32_t insn;
  46. asm (
  47. "rsr %0, EXCVADDR;" /* read out the faulting address */
  48. "movi a4, ~3;" /* prepare a mask for the EPC */
  49. "and a4, a4, %2;" /* apply mask for 32bit aligned base */
  50. "l32i a5, a4, 0;" /* load part 1 */
  51. "l32i a6, a4, 4;" /* load part 2 */
  52. "ssa8l %2;" /* set up shift register for src op */
  53. "src %1, a6, a5;" /* right shift to get faulting instruction */
  54. :"=r"(excvaddr), "=r"(insn)
  55. :"r"(epc1)
  56. :"a4", "a5", "a6"
  57. );
  58. uint32_t valmask = 0;
  59. uint32_t what = insn & LOAD_MASK;
  60. if (what == L8UI_MATCH)
  61. valmask = 0xffu;
  62. else if (what == L16UI_MATCH || what == L16SI_MATCH)
  63. valmask = 0xffffu;
  64. else
  65. {
  66. die:
  67. /* Turns out we couldn't fix this, so try and chain to the handler
  68. * that was set. (This is typically a remote GDB break). If none
  69. * then trigger a system break instead and hang if the break doesn't
  70. * get handled. This is effectively what would happen if the default
  71. * handler was installed. */
  72. if (load_store_handler) {
  73. load_store_handler(ef, cause);
  74. return;
  75. }
  76. asm ("break 1, 1");
  77. while (1) {}
  78. }
  79. /* Load, shift and mask down to correct size */
  80. uint32_t val = (*(uint32_t *)(excvaddr & ~0x3));
  81. val >>= (excvaddr & 0x3) * 8;
  82. val &= valmask;
  83. /* Sign-extend for L16SI, if applicable */
  84. if (what == L16SI_MATCH && (val & 0x8000))
  85. val |= 0xffff0000;
  86. int regno = (insn & 0x0000f0u) >> 4;
  87. if (regno == 1)
  88. goto die; /* we can't support loading into a1, just die */
  89. else if (regno != 0)
  90. --regno; /* account for skipped a1 in exception_frame */
  91. ef->a_reg[regno] = val; /* carry out the load */
  92. ef->epc += 3; /* resume at following instruction */
  93. }
  94. /**
  95. * The SDK's user_main function installs a debugging handler regardless
  96. * of whether there's a proper handler installed for EXCCAUSE_LOAD_STORE_ERROR,
  97. * which of course breaks everything if we allow that to go through. As such,
  98. * we use the linker to wrap that call and stop the SDK from shooting itself in
  99. * its proverbial foot. We do save the EXCCAUSE_LOAD_STORE_ERROR handler so that
  100. * we can chain to it above.
  101. */
  102. exception_handler_fn TEXT_SECTION_ATTR
  103. __wrap__xtos_set_exception_handler (uint32_t cause, exception_handler_fn fn)
  104. {
  105. if (cause != EXCCAUSE_LOAD_STORE_ERROR)
  106. __real__xtos_set_exception_handler (cause, fn);
  107. else
  108. load_store_handler = fn;
  109. }