entry.S 13 KB

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