arc_exception.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /* ------------------------------------------
  2. * Copyright (c) 2016, Synopsys, Inc. All rights reserved.
  3. * Redistribution and use in source and binary forms, with or without modification,
  4. * are permitted provided that the following conditions are met:
  5. * 1) Redistributions of source code must retain the above copyright notice, this
  6. * list of conditions and the following disclaimer.
  7. * 2) Redistributions in binary form must reproduce the above copyright notice,
  8. * this list of conditions and the following disclaimer in the documentation and/or
  9. * other materials provided with the distribution.
  10. * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
  11. * be used to endorse or promote products derived from this software without
  12. * specific prior written permission.
  13. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  14. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  17. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  20. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  22. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. *
  24. * \version 2016.05
  25. * \date 2014-07-15
  26. * \author Wayne Ren(Wei.Ren@synopsys.com)
  27. --------------------------------------------- */
  28. /**
  29. * \file
  30. * \ingroup ARC_HAL_EXCEPTION_CPU ARC_HAL_EXCEPTION_INTERRUPT
  31. * \brief C Implementation of exception and interrupt management
  32. */
  33. #include "inc/arc/arc_exception.h"
  34. #include "inc/arc/arc_cache.h"
  35. //#define DBG_LESS
  36. //#include "embARC_debug.h"
  37. /**
  38. * \addtogroup ARC_HAL_EXCEPTION_CPU
  39. * @{
  40. * \var exc_entry_table
  41. * \brief exception entry table
  42. *
  43. * install exception entry table to ARC_AUX_INT_VECT_BASE in startup.
  44. * According to ARCv2 ISA, vectors are fetched in instruction space and thus
  45. * may be present in ICCM, Instruction Cache, or
  46. * main memory accessed by instruction fetch logic.
  47. * So it is put into a specific section .vector.
  48. *
  49. * Please note that the exc_entry_table maybe cached in ARC. Some functions is
  50. * defined in .s files.
  51. *
  52. */
  53. /**
  54. * \ingroup ARC_HAL_EXCEPTION_CPU
  55. * \brief default cpu exception handler
  56. * \param p_excinf pointer to the exception frame
  57. */
  58. static void exc_handler_default(void *p_excinf)
  59. {
  60. // uint32_t excpt_cause_reg = 0;
  61. // uint32_t excpt_ret_reg = 0;
  62. // uint32_t exc_no = 0;
  63. // excpt_cause_reg = _arc_aux_read(AUX_ECR);
  64. // excpt_ret_reg = _arc_aux_read(AUX_ERRET);
  65. // exc_no = (excpt_cause_reg >> 16) & 0xff;
  66. Asm("kflag 1");
  67. }
  68. /**
  69. * \ingroup ARC_HAL_EXCEPTION_INTERRUPT
  70. * \brief default interrupt handler
  71. * \param[in] p_excinf information for interrupt handler
  72. */
  73. static void int_handler_default(void *p_excinf)
  74. {
  75. // uint32_t int_cause_reg = 0;
  76. // int_cause_reg = _arc_aux_read(AUX_IRQ_CAUSE);
  77. Asm("kflag 1");
  78. }
  79. __attribute__ ((aligned(1024), section(".vector")))
  80. EXC_ENTRY exc_entry_table[NUM_EXC_ALL] = {
  81. [0] = _arc_reset,
  82. [1 ... NUM_EXC_CPU-1] = exc_entry_cpu,
  83. [NUM_EXC_CPU ... NUM_EXC_ALL-1] = exc_entry_int
  84. };
  85. /**
  86. * \var exc_int_handler_table
  87. * \brief the cpu exception and interrupt exception handler table
  88. * called in exc_entry_default and exc_entry_int
  89. */
  90. EXC_HANDLER exc_int_handler_table[NUM_EXC_ALL] = {
  91. [0 ... NUM_EXC_CPU-1] = exc_handler_default,
  92. [NUM_EXC_CPU ... NUM_EXC_ALL-1] = int_handler_default
  93. };
  94. /**
  95. * \var exc_nest_count
  96. * \brief the counter for exc/int processing, =0 no int/exc
  97. * >1 in int/exc processing
  98. * @}
  99. */
  100. uint32_t exc_nest_count;
  101. typedef struct aux_irq_ctrl_field {
  102. /* note: little endian */
  103. uint32_t save_nr_gpr_pairs: 5; /** Indicates number of general-purpose register pairs saved, from 0 to 8/16 */
  104. uint32_t res: 4; /** Reserved */
  105. uint32_t save_blink: 1; /** Indicates whether to save and restore BLINK */
  106. uint32_t save_lp_regs: 1; /** Indicates whether to save and restore loop registers (LP_COUNT, LP_START, LP_END) */
  107. uint32_t save_u_to_u: 1; /** Indicates if user context is saved to user stack */
  108. uint32_t res2: 1; /** Reserved */
  109. uint32_t save_idx_regs: 1; /** Indicates whether to save and restore code-density registers (EI_BASE, JLI_BASE, LDI_BASE) */
  110. uint32_t res3: 18; /** Reserved */
  111. } aux_irq_ctrl_field_t;
  112. typedef union {
  113. aux_irq_ctrl_field_t bits;
  114. uint32_t value;
  115. } aux_irq_ctrl_t;
  116. /**
  117. * \ingroup ARC_HAL_EXCEPTION_CPU ARC_HAL_EXCEPTION_INTERRUPT
  118. * \brief intialize the exception and interrupt handling
  119. */
  120. void exc_int_init(void)
  121. {
  122. uint32_t i;
  123. uint32_t status;
  124. aux_irq_ctrl_t ictrl;
  125. ictrl.value = 0;
  126. #ifndef ARC_FEATURE_RF16
  127. ictrl.bits.save_nr_gpr_pairs = 6; /* r0 to r11 (r12 saved manually) */
  128. #else
  129. ictrl.bits.save_nr_gpr_pairs = 3; /* r0 to r3, r10, r11 */
  130. #endif
  131. ictrl.bits.save_blink = 1;
  132. ictrl.bits.save_lp_regs = 1; /* LP_COUNT, LP_START, LP_END */
  133. ictrl.bits.save_u_to_u = 0; /* user ctxt saved on kernel stack */
  134. ictrl.bits.save_idx_regs = 1; /* JLI, LDI, EI */
  135. status = arc_lock_save();
  136. for (i = NUM_EXC_CPU; i < NUM_EXC_ALL; i++) {
  137. /* interrupt level triggered, disabled, priority is the lowest */
  138. _arc_aux_write(AUX_IRQ_SELECT, i);
  139. _arc_aux_write(AUX_IRQ_ENABLE, 0);
  140. _arc_aux_write(AUX_IRQ_TRIGGER, 0);
  141. #if defined(ARC_FEATURE_SEC_PRESENT) && (SECURESHIELD_VERSION < 2)
  142. _arc_aux_write(AUX_IRQ_PRIORITY, (1 << AUX_IRQ_PRIORITY_BIT_S)|(INT_PRI_MAX - INT_PRI_MIN));
  143. #else
  144. _arc_aux_write(AUX_IRQ_PRIORITY, INT_PRI_MAX - INT_PRI_MIN);
  145. #endif
  146. }
  147. _arc_aux_write(AUX_IRQ_CTRL, ictrl.value);
  148. arc_unlock_restore(status);
  149. /** ipm should be set after cpu unlock restore to avoid reset of the status32 value */
  150. arc_int_ipm_set((INT_PRI_MAX - INT_PRI_MIN));
  151. }
  152. /**
  153. * \ingroup ARC_HAL_EXCEPTION_CPU
  154. * \brief install a CPU exception entry
  155. * \param[in] excno exception number
  156. * \param[in] entry the entry of exception to install
  157. */
  158. int32_t exc_entry_install(const uint32_t excno, EXC_ENTRY entry)
  159. {
  160. uint32_t status;
  161. EXC_ENTRY *table = (EXC_ENTRY *)_arc_aux_read(AUX_INT_VECT_BASE);
  162. if (excno < NUM_EXC_ALL && entry != NULL
  163. && table[excno] != entry) {
  164. status = cpu_lock_save();
  165. /* directly write to mem, as arc gets exception handler from mem not from cache */
  166. /* FIXME, here maybe icache is dirty, need to be invalidated */
  167. table[excno] = entry;
  168. if (_arc_aux_read(AUX_BCR_D_CACHE) > 0x2) {
  169. /* dcache is available */
  170. dcache_flush_line((uint32_t)&table[excno]);
  171. }
  172. if (_arc_aux_read(AUX_BCR_D_CACHE) > 0x2) {
  173. /* icache is available */
  174. icache_invalidate_line((uint32_t)&table[excno]);
  175. }
  176. cpu_unlock_restore(status);
  177. return 0;
  178. }
  179. return -1;
  180. }
  181. /**
  182. * \ingroup ARC_HAL_EXCEPTION_CPU
  183. * \brief get the installed CPU exception entry
  184. * \param[in] excno exception number
  185. * \return the installed CPU exception entry
  186. */
  187. EXC_ENTRY exc_entry_get(const uint32_t excno)
  188. {
  189. if (excno < NUM_EXC_ALL) {
  190. return exc_entry_table[excno];
  191. }
  192. return NULL;
  193. }
  194. /**
  195. * \ingroup ARC_HAL_EXCEPTION_CPU
  196. * \brief install an exception handler
  197. * \param[in] excno exception number
  198. * \param[in] handler the handler of exception to install
  199. */
  200. int32_t exc_handler_install(const uint32_t excno, EXC_HANDLER handler)
  201. {
  202. if (excno < NUM_EXC_ALL && handler != NULL) {
  203. exc_int_handler_table[excno] = handler;
  204. return 0;
  205. }
  206. return -1;
  207. }
  208. /**
  209. * \ingroup ARC_HAL_EXCEPTION_CPU
  210. * \brief get the installed exception handler
  211. * \param[in] excno exception number
  212. * \return the installed exception handler or NULL
  213. */
  214. EXC_HANDLER exc_handler_get(const uint32_t excno)
  215. {
  216. if (excno < NUM_EXC_ALL) {
  217. return exc_int_handler_table[excno];
  218. }
  219. return NULL;
  220. }
  221. #ifndef EMBARC_OVERRIDE_ARC_INTERRUPT_MANAGEMENT
  222. /**
  223. * \brief disable the specific interrupt
  224. *
  225. * \param[in] intno interrupt number
  226. */
  227. int32_t int_disable(const uint32_t intno)
  228. {
  229. if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
  230. arc_int_disable(intno);
  231. return 0;
  232. }
  233. return -1;
  234. }
  235. /**
  236. * \brief enable the specific int
  237. *
  238. * \param[in] intno interrupt number
  239. */
  240. int32_t int_enable(const uint32_t intno)
  241. {
  242. if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
  243. arc_int_enable(intno);
  244. return 0;
  245. }
  246. return -1;
  247. }
  248. /**
  249. * \brief check whether the specific int is enabled
  250. *
  251. * \param[in] intno interrupt number
  252. * \return 0 disabled, 1 enabled, < 0 error
  253. */
  254. int32_t int_enabled(const uint32_t intno)
  255. {
  256. if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
  257. _arc_aux_write(AUX_IRQ_SELECT, intno);
  258. return _arc_aux_read(AUX_IRQ_ENABLE);
  259. }
  260. return -1;
  261. }
  262. /**
  263. * \brief get the interrupt priority mask
  264. *
  265. * \returns interrupt priority mask, negative num
  266. */
  267. int32_t int_ipm_get(void)
  268. {
  269. return ((int32_t)arc_int_ipm_get() + INT_PRI_MIN);
  270. }
  271. /**
  272. * \brief set the interrupt priority mask
  273. *
  274. * \param[in] intpri interrupt priority
  275. */
  276. int32_t int_ipm_set(int32_t intpri)
  277. {
  278. if (intpri >= INT_PRI_MIN && intpri <= INT_PRI_MAX) {
  279. intpri = intpri - INT_PRI_MIN;
  280. arc_int_ipm_set(intpri);
  281. return 0;
  282. }
  283. return -1;
  284. }
  285. /**
  286. * \brief get current interrupt priority mask
  287. *
  288. * \param[in] intno interrupt number
  289. * \return <0 interrupt priority, 0 error
  290. */
  291. int32_t int_pri_get(const uint32_t intno)
  292. {
  293. if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
  294. return (int32_t)arc_int_pri_get(intno) + INT_PRI_MIN;
  295. }
  296. return 0;
  297. }
  298. /**
  299. * \brief set interrupt priority
  300. *
  301. * \param[in] intno interrupt number
  302. * \param[in] intpri interrupt priority
  303. * \return <0 error, 0 ok
  304. */
  305. int32_t int_pri_set(const uint32_t intno, int32_t intpri)
  306. {
  307. uint32_t status;
  308. if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
  309. status = cpu_lock_save();
  310. intpri = intpri - INT_PRI_MIN;
  311. arc_int_pri_set(intno,(uint32_t)intpri);
  312. cpu_unlock_restore(status);
  313. return 0;
  314. }
  315. return -1;
  316. }
  317. /**
  318. * \brief set interrupt secure or not secure
  319. * This function is valid in secureshield v2
  320. * \param[in] intno interrupt number
  321. * \param[in] secure, 0 for normal, >0 for secure
  322. * \return <0 error, 0 ok
  323. */
  324. int32_t int_secure_set(const uint32_t intno, uint32_t secure)
  325. {
  326. if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
  327. arc_int_secure_set(intno, secure);
  328. return 0;
  329. }
  330. return -1;
  331. }
  332. /**
  333. * \brief probe the pending status of interrupt
  334. *
  335. * \param[in] intno interrupt number
  336. *
  337. * \returns 1 pending, 0 no pending, -1 error
  338. */
  339. int32_t int_probe(const uint32_t intno)
  340. {
  341. if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
  342. return arc_int_probe(intno);
  343. }
  344. return -1;
  345. }
  346. /**
  347. * \brief trigger the interrupt in software
  348. *
  349. * \param[in] intno interrupt number
  350. * \return 0 ok, -1 error
  351. */
  352. int32_t int_sw_trigger(const uint32_t intno)
  353. {
  354. if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
  355. arc_int_sw_trigger(intno);
  356. return 0;
  357. }
  358. return -1;
  359. }
  360. /**
  361. * \brief config the interrupt level triggered or pulse triggered
  362. *
  363. * \param[in] intno interrupt number
  364. * \param[in] level, 0-level trigger, 1-pulse triggered
  365. * \return 0 ok, -1 error
  366. */
  367. int32_t int_level_config(const uint32_t intno, const uint32_t level)
  368. {
  369. if (intno >= NUM_EXC_CPU && intno < NUM_EXC_ALL) {
  370. arc_int_level_config(intno, level);
  371. return 0;
  372. }
  373. return -1;
  374. }
  375. /**
  376. * \brief lock cpu, disable interrupts
  377. */
  378. void cpu_lock(void)
  379. {
  380. arc_lock();
  381. }
  382. /**
  383. * \brief unlock cpu, enable interrupts to happen
  384. */
  385. void cpu_unlock(void)
  386. {
  387. arc_unlock();
  388. }
  389. /**
  390. * \brief lock cpu and return status
  391. *
  392. * \returns cpu status
  393. */
  394. uint32_t cpu_lock_save(void)
  395. {
  396. return arc_lock_save();
  397. }
  398. /**
  399. * \brief unlock cpu with the specific status
  400. *
  401. * \param[in] status cpu status saved by cpu_lock_save
  402. */
  403. void cpu_unlock_restore(const uint32_t status)
  404. {
  405. arc_unlock_restore(status);
  406. }
  407. /**
  408. * \ingroup ARC_HAL_EXCEPTION_INTERRUPT
  409. * \brief install an interrupt handler
  410. * \param[in] intno interrupt number
  411. * \param[in] handler interrupt handler to install
  412. */
  413. int32_t int_handler_install(const uint32_t intno, INT_HANDLER handler)
  414. {
  415. /*!< \todo parameter check ? */
  416. if (intno >= NUM_EXC_CPU) {
  417. return exc_handler_install(intno, handler);
  418. }
  419. return -1;
  420. }
  421. /**
  422. * \ingroup ARC_HAL_EXCEPTION_INTERRUPT
  423. * \brief get the installed an interrupt handler
  424. * \param[in] intno interrupt number
  425. * \return the installed interrupt handler or NULL
  426. */
  427. INT_HANDLER int_handler_get(const uint32_t intno)
  428. {
  429. if (intno >= NUM_EXC_CPU) {
  430. return exc_handler_get(intno);
  431. }
  432. return NULL;
  433. }
  434. #endif /* EMBARC_OVERRIDE_ARC_INTERRUPT_MANAGEMENT */