entry.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * linux/arch/m32r/kernel/entry.S
  4. *
  5. * Copyright (c) 2001, 2002 Hirokazu Takata, Hitoshi Yamamoto, H. Kondo
  6. * Copyright (c) 2003 Hitoshi Yamamoto
  7. * Copyright (c) 2004 Hirokazu Takata <takata at linux-m32r.org>
  8. *
  9. * Taken from i386 version.
  10. * Copyright (C) 1991, 1992 Linus Torvalds
  11. */
  12. /*
  13. * entry.S contains the system-call and fault low-level handling routines.
  14. * This also contains the timer-interrupt handler, as well as all interrupts
  15. * and faults that can result in a task-switch.
  16. *
  17. * NOTE: This code handles signal-recognition, which happens every time
  18. * after a timer-interrupt and after each system call.
  19. *
  20. * Stack layout in 'ret_from_system_call':
  21. * ptrace needs to have all regs on the stack.
  22. * if the order here is changed, it needs to be
  23. * updated in fork.c:copy_thread, signal.c:do_signal,
  24. * ptrace.c and ptrace.h
  25. *
  26. * M32R/M32Rx/M32R2
  27. * @(sp) - r4
  28. * @(0x04,sp) - r5
  29. * @(0x08,sp) - r6
  30. * @(0x0c,sp) - *pt_regs
  31. * @(0x10,sp) - r0
  32. * @(0x14,sp) - r1
  33. * @(0x18,sp) - r2
  34. * @(0x1c,sp) - r3
  35. * @(0x20,sp) - r7
  36. * @(0x24,sp) - r8
  37. * @(0x28,sp) - r9
  38. * @(0x2c,sp) - r10
  39. * @(0x30,sp) - r11
  40. * @(0x34,sp) - r12
  41. * @(0x38,sp) - syscall_nr
  42. * @(0x3c,sp) - acc0h
  43. * @(0x40,sp) - acc0l
  44. * @(0x44,sp) - acc1h ; ISA_DSP_LEVEL2 only
  45. * @(0x48,sp) - acc1l ; ISA_DSP_LEVEL2 only
  46. * @(0x4c,sp) - psw
  47. * @(0x50,sp) - bpc
  48. * @(0x54,sp) - bbpsw
  49. * @(0x58,sp) - bbpc
  50. * @(0x5c,sp) - spu (cr3)
  51. * @(0x60,sp) - fp (r13)
  52. * @(0x64,sp) - lr (r14)
  53. * @(0x68,sp) - spi (cr2)
  54. * @(0x6c,sp) - orig_r0
  55. */
  56. #include <linux/linkage.h>
  57. #include <asm/irq.h>
  58. #include <asm/unistd.h>
  59. #include <asm/assembler.h>
  60. #include <asm/thread_info.h>
  61. #include <asm/errno.h>
  62. #include <asm/segment.h>
  63. #include <asm/smp.h>
  64. #include <asm/page.h>
  65. #include <asm/m32r.h>
  66. #include <asm/mmu_context.h>
  67. #include <asm/asm-offsets.h>
  68. #if !defined(CONFIG_MMU)
  69. #define sys_madvise sys_ni_syscall
  70. #define sys_readahead sys_ni_syscall
  71. #define sys_mprotect sys_ni_syscall
  72. #define sys_msync sys_ni_syscall
  73. #define sys_mlock sys_ni_syscall
  74. #define sys_munlock sys_ni_syscall
  75. #define sys_mlockall sys_ni_syscall
  76. #define sys_munlockall sys_ni_syscall
  77. #define sys_mremap sys_ni_syscall
  78. #define sys_mincore sys_ni_syscall
  79. #define sys_remap_file_pages sys_ni_syscall
  80. #endif /* CONFIG_MMU */
  81. #define R4(reg) @reg
  82. #define R5(reg) @(0x04,reg)
  83. #define R6(reg) @(0x08,reg)
  84. #define PTREGS(reg) @(0x0C,reg)
  85. #define R0(reg) @(0x10,reg)
  86. #define R1(reg) @(0x14,reg)
  87. #define R2(reg) @(0x18,reg)
  88. #define R3(reg) @(0x1C,reg)
  89. #define R7(reg) @(0x20,reg)
  90. #define R8(reg) @(0x24,reg)
  91. #define R9(reg) @(0x28,reg)
  92. #define R10(reg) @(0x2C,reg)
  93. #define R11(reg) @(0x30,reg)
  94. #define R12(reg) @(0x34,reg)
  95. #define SYSCALL_NR(reg) @(0x38,reg)
  96. #define ACC0H(reg) @(0x3C,reg)
  97. #define ACC0L(reg) @(0x40,reg)
  98. #define ACC1H(reg) @(0x44,reg)
  99. #define ACC1L(reg) @(0x48,reg)
  100. #define PSW(reg) @(0x4C,reg)
  101. #define BPC(reg) @(0x50,reg)
  102. #define BBPSW(reg) @(0x54,reg)
  103. #define BBPC(reg) @(0x58,reg)
  104. #define SPU(reg) @(0x5C,reg)
  105. #define FP(reg) @(0x60,reg) /* FP = R13 */
  106. #define LR(reg) @(0x64,reg)
  107. #define SP(reg) @(0x68,reg)
  108. #define ORIG_R0(reg) @(0x6C,reg)
  109. #define nr_syscalls ((syscall_table_size)/4)
  110. #ifdef CONFIG_PREEMPT
  111. #define preempt_stop(x) DISABLE_INTERRUPTS(x)
  112. #else
  113. #define preempt_stop(x)
  114. #define resume_kernel restore_all
  115. #endif
  116. /* how to get the thread information struct from ASM */
  117. #define GET_THREAD_INFO(reg) GET_THREAD_INFO reg
  118. .macro GET_THREAD_INFO reg
  119. ldi \reg, #-THREAD_SIZE
  120. and \reg, sp
  121. .endm
  122. ENTRY(ret_from_kernel_thread)
  123. pop r0
  124. bl schedule_tail
  125. GET_THREAD_INFO(r8)
  126. ld r0, R0(r8)
  127. ld r1, R1(r8)
  128. jl r1
  129. bra syscall_exit
  130. ENTRY(ret_from_fork)
  131. pop r0
  132. bl schedule_tail
  133. GET_THREAD_INFO(r8)
  134. bra syscall_exit
  135. /*
  136. * Return to user mode is not as complex as all this looks,
  137. * but we want the default path for a system call return to
  138. * go as quickly as possible which is why some of this is
  139. * less clear than it otherwise should be.
  140. */
  141. ; userspace resumption stub bypassing syscall exit tracing
  142. ALIGN
  143. ret_from_exception:
  144. preempt_stop(r4)
  145. ret_from_intr:
  146. ld r4, PSW(sp)
  147. #ifdef CONFIG_ISA_M32R2
  148. and3 r4, r4, #0x8800 ; check BSM and BPM bits
  149. #else
  150. and3 r4, r4, #0x8000 ; check BSM bit
  151. #endif
  152. beqz r4, resume_kernel
  153. resume_userspace:
  154. DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
  155. ; setting need_resched or sigpending
  156. ; between sampling and the iret
  157. GET_THREAD_INFO(r8)
  158. ld r9, @(TI_FLAGS, r8)
  159. and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done on
  160. ; int/exception return?
  161. bnez r4, work_pending
  162. bra restore_all
  163. #ifdef CONFIG_PREEMPT
  164. ENTRY(resume_kernel)
  165. GET_THREAD_INFO(r8)
  166. ld r9, @(TI_PRE_COUNT, r8) ; non-zero preempt_count ?
  167. bnez r9, restore_all
  168. need_resched:
  169. ld r9, @(TI_FLAGS, r8) ; need_resched set ?
  170. and3 r4, r9, #_TIF_NEED_RESCHED
  171. beqz r4, restore_all
  172. ld r4, PSW(sp) ; interrupts off (exception path) ?
  173. and3 r4, r4, #0x4000
  174. beqz r4, restore_all
  175. bl preempt_schedule_irq
  176. bra need_resched
  177. #endif
  178. ; system call handler stub
  179. ENTRY(system_call)
  180. SWITCH_TO_KERNEL_STACK
  181. SAVE_ALL
  182. ENABLE_INTERRUPTS(r4) ; Enable interrupt
  183. st sp, PTREGS(sp) ; implicit pt_regs parameter
  184. cmpui r7, #NR_syscalls
  185. bnc syscall_badsys
  186. st r7, SYSCALL_NR(sp) ; syscall_nr
  187. ; system call tracing in operation
  188. GET_THREAD_INFO(r8)
  189. ld r9, @(TI_FLAGS, r8)
  190. and3 r4, r9, #_TIF_SYSCALL_TRACE
  191. bnez r4, syscall_trace_entry
  192. syscall_call:
  193. slli r7, #2 ; table jump for the system call
  194. LDIMM (r4, sys_call_table)
  195. add r7, r4
  196. ld r7, @r7
  197. jl r7 ; execute system call
  198. st r0, R0(sp) ; save the return value
  199. syscall_exit:
  200. DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
  201. ; setting need_resched or sigpending
  202. ; between sampling and the iret
  203. ld r9, @(TI_FLAGS, r8)
  204. and3 r4, r9, #_TIF_ALLWORK_MASK ; current->work
  205. bnez r4, syscall_exit_work
  206. restore_all:
  207. RESTORE_ALL
  208. # perform work that needs to be done immediately before resumption
  209. # r9 : flags
  210. ALIGN
  211. work_pending:
  212. and3 r4, r9, #_TIF_NEED_RESCHED
  213. beqz r4, work_notifysig
  214. work_resched:
  215. bl schedule
  216. DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
  217. ; setting need_resched or sigpending
  218. ; between sampling and the iret
  219. ld r9, @(TI_FLAGS, r8)
  220. and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done other
  221. ; than syscall tracing?
  222. beqz r4, restore_all
  223. and3 r4, r4, #_TIF_NEED_RESCHED
  224. bnez r4, work_resched
  225. work_notifysig: ; deal with pending signals and
  226. ; notify-resume requests
  227. mv r0, sp ; arg1 : struct pt_regs *regs
  228. mv r1, r9 ; arg2 : __u32 thread_info_flags
  229. bl do_notify_resume
  230. bra resume_userspace
  231. ; perform syscall exit tracing
  232. ALIGN
  233. syscall_trace_entry:
  234. ldi r4, #-ENOSYS
  235. st r4, R0(sp)
  236. bl do_syscall_trace
  237. ld r0, ORIG_R0(sp)
  238. ld r1, R1(sp)
  239. ld r2, R2(sp)
  240. ld r3, R3(sp)
  241. ld r4, R4(sp)
  242. ld r5, R5(sp)
  243. ld r6, R6(sp)
  244. ld r7, SYSCALL_NR(sp)
  245. cmpui r7, #NR_syscalls
  246. bc syscall_call
  247. bra syscall_exit
  248. ; perform syscall exit tracing
  249. ALIGN
  250. syscall_exit_work:
  251. ld r9, @(TI_FLAGS, r8)
  252. and3 r4, r9, #_TIF_SYSCALL_TRACE
  253. beqz r4, work_pending
  254. ENABLE_INTERRUPTS(r4) ; could let do_syscall_trace() call
  255. ; schedule() instead
  256. bl do_syscall_trace
  257. bra resume_userspace
  258. ALIGN
  259. syscall_fault:
  260. SAVE_ALL
  261. GET_THREAD_INFO(r8)
  262. ldi r4, #-EFAULT
  263. st r4, R0(sp)
  264. bra resume_userspace
  265. ALIGN
  266. syscall_badsys:
  267. ldi r4, #-ENOSYS
  268. st r4, R0(sp)
  269. bra resume_userspace
  270. .global eit_vector
  271. .equ ei_vec_table, eit_vector + 0x0200
  272. /*
  273. * EI handler routine
  274. */
  275. ENTRY(ei_handler)
  276. #if defined(CONFIG_CHIP_M32700)
  277. ; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
  278. SWITCH_TO_KERNEL_STACK
  279. #endif
  280. SAVE_ALL
  281. mv r1, sp ; arg1(regs)
  282. ; get ICU status
  283. seth r0, #shigh(M32R_ICU_ISTS_ADDR)
  284. ld r0, @(low(M32R_ICU_ISTS_ADDR),r0)
  285. push r0
  286. #if defined(CONFIG_SMP)
  287. /*
  288. * If IRQ == 0 --> Nothing to do, Not write IMASK
  289. * If IRQ == IPI --> Do IPI handler, Not write IMASK
  290. * If IRQ != 0, IPI --> Do do_IRQ(), Write IMASK
  291. */
  292. slli r0, #4
  293. srli r0, #24 ; r0(irq_num<<2)
  294. ;; IRQ exist check
  295. #if defined(CONFIG_CHIP_M32700)
  296. /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
  297. bnez r0, 0f
  298. ld24 r14, #0x00070000
  299. seth r0, #shigh(M32R_ICU_IMASK_ADDR)
  300. st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
  301. bra 1f
  302. .fillinsn
  303. 0:
  304. #endif /* CONFIG_CHIP_M32700 */
  305. beqz r0, 1f ; if (!irq_num) goto exit
  306. ;; IPI check
  307. cmpi r0, #(M32R_IRQ_IPI0<<2) ; ISN < IPI0 check
  308. bc 2f
  309. cmpi r0, #((M32R_IRQ_IPI7+1)<<2) ; ISN > IPI7 check
  310. bnc 2f
  311. LDIMM (r2, ei_vec_table)
  312. add r2, r0
  313. ld r2, @r2
  314. beqz r2, 1f ; if (no IPI handler) goto exit
  315. mv r0, r1 ; arg0(regs)
  316. jl r2
  317. .fillinsn
  318. 1:
  319. addi sp, #4
  320. bra restore_all
  321. .fillinsn
  322. 2:
  323. srli r0, #2
  324. #else /* not CONFIG_SMP */
  325. srli r0, #22 ; r0(irq)
  326. #endif /* not CONFIG_SMP */
  327. #if defined(CONFIG_PLAT_HAS_INT1ICU)
  328. add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
  329. bnez r2, 3f
  330. seth r0, #shigh(M32R_INT1ICU_ISTS)
  331. lduh r0, @(low(M32R_INT1ICU_ISTS),r0) ; bit10-6 : ISN
  332. slli r0, #21
  333. srli r0, #27 ; ISN
  334. addi r0, #(M32R_INT1ICU_IRQ_BASE)
  335. bra check_end
  336. .fillinsn
  337. 3:
  338. #endif /* CONFIG_PLAT_HAS_INT1ICU */
  339. #if defined(CONFIG_PLAT_HAS_INT0ICU)
  340. add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt
  341. bnez r2, 4f
  342. seth r0, #shigh(M32R_INT0ICU_ISTS)
  343. lduh r0, @(low(M32R_INT0ICU_ISTS),r0) ; bit10-6 : ISN
  344. slli r0, #21
  345. srli r0, #27 ; ISN
  346. add3 r0, r0, #(M32R_INT0ICU_IRQ_BASE)
  347. bra check_end
  348. .fillinsn
  349. 4:
  350. #endif /* CONFIG_PLAT_HAS_INT0ICU */
  351. #if defined(CONFIG_PLAT_HAS_INT2ICU)
  352. add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt
  353. bnez r2, 5f
  354. seth r0, #shigh(M32R_INT2ICU_ISTS)
  355. lduh r0, @(low(M32R_INT2ICU_ISTS),r0) ; bit10-6 : ISN
  356. slli r0, #21
  357. srli r0, #27 ; ISN
  358. add3 r0, r0, #(M32R_INT2ICU_IRQ_BASE)
  359. ; bra check_end
  360. .fillinsn
  361. 5:
  362. #endif /* CONFIG_PLAT_HAS_INT2ICU */
  363. check_end:
  364. bl do_IRQ
  365. pop r14
  366. seth r0, #shigh(M32R_ICU_IMASK_ADDR)
  367. st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
  368. bra ret_from_intr
  369. /*
  370. * Default EIT handler
  371. */
  372. ALIGN
  373. int_msg:
  374. .asciz "Unknown interrupt\n"
  375. .byte 0
  376. ENTRY(default_eit_handler)
  377. push r0
  378. mvfc r0, psw
  379. push r1
  380. push r2
  381. push r3
  382. push r0
  383. LDIMM (r0, __KERNEL_DS)
  384. mv r0, r1
  385. mv r0, r2
  386. LDIMM (r0, int_msg)
  387. bl printk
  388. pop r0
  389. pop r3
  390. pop r2
  391. pop r1
  392. mvtc r0, psw
  393. pop r0
  394. infinit:
  395. bra infinit
  396. #ifdef CONFIG_MMU
  397. /*
  398. * Access Exception handler
  399. */
  400. ENTRY(ace_handler)
  401. SWITCH_TO_KERNEL_STACK
  402. SAVE_ALL
  403. seth r2, #shigh(MMU_REG_BASE) /* Check status register */
  404. ld r4, @(low(MESTS_offset),r2)
  405. st r4, @(low(MESTS_offset),r2)
  406. srl3 r1, r4, #4
  407. #ifdef CONFIG_CHIP_M32700
  408. and3 r1, r1, #0x0000ffff
  409. ; WORKAROUND: ignore TME bit for the M32700(TS1).
  410. #endif /* CONFIG_CHIP_M32700 */
  411. beqz r1, inst
  412. oprand:
  413. ld r2, @(low(MDEVA_offset),r2) ; set address
  414. srli r1, #1
  415. bra 1f
  416. inst:
  417. and3 r1, r4, #2
  418. srli r1, #1
  419. or3 r1, r1, #8
  420. mvfc r2, bpc ; set address
  421. .fillinsn
  422. 1:
  423. mvfc r3, psw
  424. mv r0, sp
  425. and3 r3, r3, 0x800
  426. srli r3, #9
  427. or r1, r3
  428. /*
  429. * do_page_fault():
  430. * r0 : struct pt_regs *regs
  431. * r1 : unsigned long error-code
  432. * r2 : unsigned long address
  433. * error-code:
  434. * +------+------+------+------+
  435. * | bit3 | bit2 | bit1 | bit0 |
  436. * +------+------+------+------+
  437. * bit 3 == 0:means data, 1:means instruction
  438. * bit 2 == 0:means kernel, 1:means user-mode
  439. * bit 1 == 0:means read, 1:means write
  440. * bit 0 == 0:means no page found 1:means protection fault
  441. *
  442. */
  443. bl do_page_fault
  444. bra ret_from_intr
  445. #endif /* CONFIG_MMU */
  446. ENTRY(alignment_check)
  447. /* void alignment_check(int error_code) */
  448. SWITCH_TO_KERNEL_STACK
  449. SAVE_ALL
  450. ldi r1, #0x30 ; error_code
  451. mv r0, sp ; pt_regs
  452. bl do_alignment_check
  453. error_code:
  454. bra ret_from_exception
  455. ENTRY(rie_handler)
  456. /* void rie_handler(int error_code) */
  457. SWITCH_TO_KERNEL_STACK
  458. SAVE_ALL
  459. ldi r1, #0x20 ; error_code
  460. mv r0, sp ; pt_regs
  461. bl do_rie_handler
  462. bra error_code
  463. ENTRY(pie_handler)
  464. /* void pie_handler(int error_code) */
  465. SWITCH_TO_KERNEL_STACK
  466. SAVE_ALL
  467. ldi r1, #0 ; error_code ; FIXME
  468. mv r0, sp ; pt_regs
  469. bl do_pie_handler
  470. bra error_code
  471. ENTRY(debug_trap)
  472. /* void debug_trap(void) */
  473. .global withdraw_debug_trap
  474. SWITCH_TO_KERNEL_STACK
  475. SAVE_ALL
  476. mv r0, sp ; pt_regs
  477. bl withdraw_debug_trap
  478. ldi r1, #0 ; error_code
  479. mv r0, sp ; pt_regs
  480. bl do_debug_trap
  481. bra error_code
  482. ENTRY(ill_trap)
  483. /* void ill_trap(void) */
  484. SWITCH_TO_KERNEL_STACK
  485. SAVE_ALL
  486. ldi r1, #0 ; error_code ; FIXME
  487. mv r0, sp ; pt_regs
  488. bl do_ill_trap
  489. bra error_code
  490. ENTRY(cache_flushing_handler)
  491. /* void _flush_cache_all(void); */
  492. .global _flush_cache_all
  493. SWITCH_TO_KERNEL_STACK
  494. push r0
  495. push r1
  496. push r2
  497. push r3
  498. push r4
  499. push r5
  500. push r6
  501. push r7
  502. push lr
  503. bl _flush_cache_all
  504. pop lr
  505. pop r7
  506. pop r6
  507. pop r5
  508. pop r4
  509. pop r3
  510. pop r2
  511. pop r1
  512. pop r0
  513. rte
  514. .section .rodata,"a"
  515. #include "syscall_table.S"
  516. syscall_table_size=(.-sys_call_table)