entry.S 13 KB

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