entry.S 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  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_fork)
  121. pop r0
  122. bl schedule_tail
  123. GET_THREAD_INFO(r8)
  124. bra syscall_exit
  125. /*
  126. * Return to user mode is not as complex as all this looks,
  127. * but we want the default path for a system call return to
  128. * go as quickly as possible which is why some of this is
  129. * less clear than it otherwise should be.
  130. */
  131. ; userspace resumption stub bypassing syscall exit tracing
  132. ALIGN
  133. ret_from_exception:
  134. preempt_stop(r4)
  135. ret_from_intr:
  136. ld r4, PSW(sp)
  137. #ifdef CONFIG_ISA_M32R2
  138. and3 r4, r4, #0x8800 ; check BSM and BPM bits
  139. #else
  140. and3 r4, r4, #0x8000 ; check BSM bit
  141. #endif
  142. beqz r4, resume_kernel
  143. resume_userspace:
  144. DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
  145. ; setting need_resched or sigpending
  146. ; between sampling and the iret
  147. GET_THREAD_INFO(r8)
  148. ld r9, @(TI_FLAGS, r8)
  149. and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done on
  150. ; int/exception return?
  151. bnez r4, work_pending
  152. bra restore_all
  153. #ifdef CONFIG_PREEMPT
  154. ENTRY(resume_kernel)
  155. GET_THREAD_INFO(r8)
  156. ld r9, @(TI_PRE_COUNT, r8) ; non-zero preempt_count ?
  157. bnez r9, restore_all
  158. need_resched:
  159. ld r9, @(TI_FLAGS, r8) ; need_resched set ?
  160. and3 r4, r9, #_TIF_NEED_RESCHED
  161. beqz r4, restore_all
  162. ld r4, PSW(sp) ; interrupts off (exception path) ?
  163. and3 r4, r4, #0x4000
  164. beqz r4, restore_all
  165. LDIMM (r4, PREEMPT_ACTIVE)
  166. st r4, @(TI_PRE_COUNT, r8)
  167. ENABLE_INTERRUPTS(r4)
  168. bl schedule
  169. ldi r4, #0
  170. st r4, @(TI_PRE_COUNT, r8)
  171. DISABLE_INTERRUPTS(r4)
  172. bra need_resched
  173. #endif
  174. ; system call handler stub
  175. ENTRY(system_call)
  176. SWITCH_TO_KERNEL_STACK
  177. SAVE_ALL
  178. ENABLE_INTERRUPTS(r4) ; Enable interrupt
  179. st sp, PTREGS(sp) ; implicit pt_regs parameter
  180. cmpui r7, #NR_syscalls
  181. bnc syscall_badsys
  182. st r7, SYSCALL_NR(sp) ; syscall_nr
  183. ; system call tracing in operation
  184. GET_THREAD_INFO(r8)
  185. ld r9, @(TI_FLAGS, r8)
  186. and3 r4, r9, #_TIF_SYSCALL_TRACE
  187. bnez r4, syscall_trace_entry
  188. syscall_call:
  189. slli r7, #2 ; table jump for the system call
  190. LDIMM (r4, sys_call_table)
  191. add r7, r4
  192. ld r7, @r7
  193. jl r7 ; execute system call
  194. st r0, R0(sp) ; save the return value
  195. syscall_exit:
  196. DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
  197. ; setting need_resched or sigpending
  198. ; between sampling and the iret
  199. ld r9, @(TI_FLAGS, r8)
  200. and3 r4, r9, #_TIF_ALLWORK_MASK ; current->work
  201. bnez r4, syscall_exit_work
  202. restore_all:
  203. RESTORE_ALL
  204. # perform work that needs to be done immediately before resumption
  205. # r9 : flags
  206. ALIGN
  207. work_pending:
  208. and3 r4, r9, #_TIF_NEED_RESCHED
  209. beqz r4, work_notifysig
  210. work_resched:
  211. bl schedule
  212. DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt
  213. ; setting need_resched or sigpending
  214. ; between sampling and the iret
  215. ld r9, @(TI_FLAGS, r8)
  216. and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done other
  217. ; than syscall tracing?
  218. beqz r4, restore_all
  219. and3 r4, r4, #_TIF_NEED_RESCHED
  220. bnez r4, work_resched
  221. work_notifysig: ; deal with pending signals and
  222. ; notify-resume requests
  223. mv r0, sp ; arg1 : struct pt_regs *regs
  224. mv r1, r9 ; arg2 : __u32 thread_info_flags
  225. bl do_notify_resume
  226. bra resume_userspace
  227. ; perform syscall exit tracing
  228. ALIGN
  229. syscall_trace_entry:
  230. ldi r4, #-ENOSYS
  231. st r4, R0(sp)
  232. bl do_syscall_trace
  233. ld r0, ORIG_R0(sp)
  234. ld r1, R1(sp)
  235. ld r2, R2(sp)
  236. ld r3, R3(sp)
  237. ld r4, R4(sp)
  238. ld r5, R5(sp)
  239. ld r6, R6(sp)
  240. ld r7, SYSCALL_NR(sp)
  241. cmpui r7, #NR_syscalls
  242. bc syscall_call
  243. bra syscall_exit
  244. ; perform syscall exit tracing
  245. ALIGN
  246. syscall_exit_work:
  247. ld r9, @(TI_FLAGS, r8)
  248. and3 r4, r9, #_TIF_SYSCALL_TRACE
  249. beqz r4, work_pending
  250. ENABLE_INTERRUPTS(r4) ; could let do_syscall_trace() call
  251. ; schedule() instead
  252. bl do_syscall_trace
  253. bra resume_userspace
  254. ALIGN
  255. syscall_fault:
  256. SAVE_ALL
  257. GET_THREAD_INFO(r8)
  258. ldi r4, #-EFAULT
  259. st r4, R0(sp)
  260. bra resume_userspace
  261. ALIGN
  262. syscall_badsys:
  263. ldi r4, #-ENOSYS
  264. st r4, R0(sp)
  265. bra resume_userspace
  266. .global eit_vector
  267. .equ ei_vec_table, eit_vector + 0x0200
  268. /*
  269. * EI handler routine
  270. */
  271. ENTRY(ei_handler)
  272. #if defined(CONFIG_CHIP_M32700)
  273. ; WORKAROUND: force to clear SM bit and use the kernel stack (SPI).
  274. SWITCH_TO_KERNEL_STACK
  275. #endif
  276. SAVE_ALL
  277. mv r1, sp ; arg1(regs)
  278. ; get ICU status
  279. seth r0, #shigh(M32R_ICU_ISTS_ADDR)
  280. ld r0, @(low(M32R_ICU_ISTS_ADDR),r0)
  281. push r0
  282. #if defined(CONFIG_SMP)
  283. /*
  284. * If IRQ == 0 --> Nothing to do, Not write IMASK
  285. * If IRQ == IPI --> Do IPI handler, Not write IMASK
  286. * If IRQ != 0, IPI --> Do do_IRQ(), Write IMASK
  287. */
  288. slli r0, #4
  289. srli r0, #24 ; r0(irq_num<<2)
  290. ;; IRQ exist check
  291. #if defined(CONFIG_CHIP_M32700)
  292. /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */
  293. bnez r0, 0f
  294. ld24 r14, #0x00070000
  295. seth r0, #shigh(M32R_ICU_IMASK_ADDR)
  296. st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
  297. bra 1f
  298. .fillinsn
  299. 0:
  300. #endif /* CONFIG_CHIP_M32700 */
  301. beqz r0, 1f ; if (!irq_num) goto exit
  302. ;; IPI check
  303. cmpi r0, #(M32R_IRQ_IPI0<<2) ; ISN < IPI0 check
  304. bc 2f
  305. cmpi r0, #((M32R_IRQ_IPI7+1)<<2) ; ISN > IPI7 check
  306. bnc 2f
  307. LDIMM (r2, ei_vec_table)
  308. add r2, r0
  309. ld r2, @r2
  310. beqz r2, 1f ; if (no IPI handler) goto exit
  311. mv r0, r1 ; arg0(regs)
  312. jl r2
  313. .fillinsn
  314. 1:
  315. addi sp, #4
  316. bra restore_all
  317. .fillinsn
  318. 2:
  319. srli r0, #2
  320. #else /* not CONFIG_SMP */
  321. srli r0, #22 ; r0(irq)
  322. #endif /* not CONFIG_SMP */
  323. #if defined(CONFIG_PLAT_HAS_INT1ICU)
  324. add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt
  325. bnez r2, 3f
  326. seth r0, #shigh(M32R_INT1ICU_ISTS)
  327. lduh r0, @(low(M32R_INT1ICU_ISTS),r0) ; bit10-6 : ISN
  328. slli r0, #21
  329. srli r0, #27 ; ISN
  330. addi r0, #(M32R_INT1ICU_IRQ_BASE)
  331. bra check_end
  332. .fillinsn
  333. 3:
  334. #endif /* CONFIG_PLAT_HAS_INT1ICU */
  335. #if defined(CONFIG_PLAT_HAS_INT0ICU)
  336. add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt
  337. bnez r2, 4f
  338. seth r0, #shigh(M32R_INT0ICU_ISTS)
  339. lduh r0, @(low(M32R_INT0ICU_ISTS),r0) ; bit10-6 : ISN
  340. slli r0, #21
  341. srli r0, #27 ; ISN
  342. add3 r0, r0, #(M32R_INT0ICU_IRQ_BASE)
  343. bra check_end
  344. .fillinsn
  345. 4:
  346. #endif /* CONFIG_PLAT_HAS_INT0ICU */
  347. #if defined(CONFIG_PLAT_HAS_INT2ICU)
  348. add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt
  349. bnez r2, 5f
  350. seth r0, #shigh(M32R_INT2ICU_ISTS)
  351. lduh r0, @(low(M32R_INT2ICU_ISTS),r0) ; bit10-6 : ISN
  352. slli r0, #21
  353. srli r0, #27 ; ISN
  354. add3 r0, r0, #(M32R_INT2ICU_IRQ_BASE)
  355. ; bra check_end
  356. .fillinsn
  357. 5:
  358. #endif /* CONFIG_PLAT_HAS_INT2ICU */
  359. check_end:
  360. bl do_IRQ
  361. pop r14
  362. seth r0, #shigh(M32R_ICU_IMASK_ADDR)
  363. st r14, @(low(M32R_ICU_IMASK_ADDR),r0)
  364. bra ret_from_intr
  365. /*
  366. * Default EIT handler
  367. */
  368. ALIGN
  369. int_msg:
  370. .asciz "Unknown interrupt\n"
  371. .byte 0
  372. ENTRY(default_eit_handler)
  373. push r0
  374. mvfc r0, psw
  375. push r1
  376. push r2
  377. push r3
  378. push r0
  379. LDIMM (r0, __KERNEL_DS)
  380. mv r0, r1
  381. mv r0, r2
  382. LDIMM (r0, int_msg)
  383. bl printk
  384. pop r0
  385. pop r3
  386. pop r2
  387. pop r1
  388. mvtc r0, psw
  389. pop r0
  390. infinit:
  391. bra infinit
  392. #ifdef CONFIG_MMU
  393. /*
  394. * Access Exception handler
  395. */
  396. ENTRY(ace_handler)
  397. SWITCH_TO_KERNEL_STACK
  398. SAVE_ALL
  399. seth r2, #shigh(MMU_REG_BASE) /* Check status register */
  400. ld r4, @(low(MESTS_offset),r2)
  401. st r4, @(low(MESTS_offset),r2)
  402. srl3 r1, r4, #4
  403. #ifdef CONFIG_CHIP_M32700
  404. and3 r1, r1, #0x0000ffff
  405. ; WORKAROUND: ignore TME bit for the M32700(TS1).
  406. #endif /* CONFIG_CHIP_M32700 */
  407. beqz r1, inst
  408. oprand:
  409. ld r2, @(low(MDEVA_offset),r2) ; set address
  410. srli r1, #1
  411. bra 1f
  412. inst:
  413. and3 r1, r4, #2
  414. srli r1, #1
  415. or3 r1, r1, #8
  416. mvfc r2, bpc ; set address
  417. .fillinsn
  418. 1:
  419. mvfc r3, psw
  420. mv r0, sp
  421. and3 r3, r3, 0x800
  422. srli r3, #9
  423. or r1, r3
  424. /*
  425. * do_page_fault():
  426. * r0 : struct pt_regs *regs
  427. * r1 : unsigned long error-code
  428. * r2 : unsigned long address
  429. * error-code:
  430. * +------+------+------+------+
  431. * | bit3 | bit2 | bit1 | bit0 |
  432. * +------+------+------+------+
  433. * bit 3 == 0:means data, 1:means instruction
  434. * bit 2 == 0:means kernel, 1:means user-mode
  435. * bit 1 == 0:means read, 1:means write
  436. * bit 0 == 0:means no page found 1:means protection fault
  437. *
  438. */
  439. bl do_page_fault
  440. bra ret_from_intr
  441. #endif /* CONFIG_MMU */
  442. ENTRY(alignment_check)
  443. /* void alignment_check(int error_code) */
  444. SWITCH_TO_KERNEL_STACK
  445. SAVE_ALL
  446. ldi r1, #0x30 ; error_code
  447. mv r0, sp ; pt_regs
  448. bl do_alignment_check
  449. error_code:
  450. bra ret_from_exception
  451. ENTRY(rie_handler)
  452. /* void rie_handler(int error_code) */
  453. SWITCH_TO_KERNEL_STACK
  454. SAVE_ALL
  455. ldi r1, #0x20 ; error_code
  456. mv r0, sp ; pt_regs
  457. bl do_rie_handler
  458. bra error_code
  459. ENTRY(pie_handler)
  460. /* void pie_handler(int error_code) */
  461. SWITCH_TO_KERNEL_STACK
  462. SAVE_ALL
  463. ldi r1, #0 ; error_code ; FIXME
  464. mv r0, sp ; pt_regs
  465. bl do_pie_handler
  466. bra error_code
  467. ENTRY(debug_trap)
  468. /* void debug_trap(void) */
  469. .global withdraw_debug_trap
  470. SWITCH_TO_KERNEL_STACK
  471. SAVE_ALL
  472. mv r0, sp ; pt_regs
  473. bl withdraw_debug_trap
  474. ldi r1, #0 ; error_code
  475. mv r0, sp ; pt_regs
  476. bl do_debug_trap
  477. bra error_code
  478. ENTRY(ill_trap)
  479. /* void ill_trap(void) */
  480. SWITCH_TO_KERNEL_STACK
  481. SAVE_ALL
  482. ldi r1, #0 ; error_code ; FIXME
  483. mv r0, sp ; pt_regs
  484. bl do_ill_trap
  485. bra error_code
  486. ENTRY(cache_flushing_handler)
  487. /* void _flush_cache_all(void); */
  488. .global _flush_cache_all
  489. SWITCH_TO_KERNEL_STACK
  490. push r0
  491. push r1
  492. push r2
  493. push r3
  494. push r4
  495. push r5
  496. push r6
  497. push r7
  498. push lr
  499. bl _flush_cache_all
  500. pop lr
  501. pop r7
  502. pop r6
  503. pop r5
  504. pop r4
  505. pop r3
  506. pop r2
  507. pop r1
  508. pop r0
  509. rte
  510. .section .rodata,"a"
  511. #include "syscall_table.S"
  512. syscall_table_size=(.-sys_call_table)