entry.S 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. /*
  2. * Copyright (C) 2012 Regents of the University of California
  3. * Copyright (C) 2017 SiFive
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License
  7. * as published by the Free Software Foundation, version 2.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include <linux/init.h>
  15. #include <linux/linkage.h>
  16. #include <asm/asm.h>
  17. #include <asm/csr.h>
  18. #include <asm/unistd.h>
  19. #include <asm/thread_info.h>
  20. #include <asm/asm-offsets.h>
  21. .text
  22. .altmacro
  23. /*
  24. * Prepares to enter a system call or exception by saving all registers to the
  25. * stack.
  26. */
  27. .macro SAVE_ALL
  28. LOCAL _restore_kernel_tpsp
  29. LOCAL _save_context
  30. /*
  31. * If coming from userspace, preserve the user thread pointer and load
  32. * the kernel thread pointer. If we came from the kernel, sscratch
  33. * will contain 0, and we should continue on the current TP.
  34. */
  35. csrrw tp, sscratch, tp
  36. bnez tp, _save_context
  37. _restore_kernel_tpsp:
  38. csrr tp, sscratch
  39. REG_S sp, TASK_TI_KERNEL_SP(tp)
  40. _save_context:
  41. REG_S sp, TASK_TI_USER_SP(tp)
  42. REG_L sp, TASK_TI_KERNEL_SP(tp)
  43. addi sp, sp, -(PT_SIZE_ON_STACK)
  44. REG_S x1, PT_RA(sp)
  45. REG_S x3, PT_GP(sp)
  46. REG_S x5, PT_T0(sp)
  47. REG_S x6, PT_T1(sp)
  48. REG_S x7, PT_T2(sp)
  49. REG_S x8, PT_S0(sp)
  50. REG_S x9, PT_S1(sp)
  51. REG_S x10, PT_A0(sp)
  52. REG_S x11, PT_A1(sp)
  53. REG_S x12, PT_A2(sp)
  54. REG_S x13, PT_A3(sp)
  55. REG_S x14, PT_A4(sp)
  56. REG_S x15, PT_A5(sp)
  57. REG_S x16, PT_A6(sp)
  58. REG_S x17, PT_A7(sp)
  59. REG_S x18, PT_S2(sp)
  60. REG_S x19, PT_S3(sp)
  61. REG_S x20, PT_S4(sp)
  62. REG_S x21, PT_S5(sp)
  63. REG_S x22, PT_S6(sp)
  64. REG_S x23, PT_S7(sp)
  65. REG_S x24, PT_S8(sp)
  66. REG_S x25, PT_S9(sp)
  67. REG_S x26, PT_S10(sp)
  68. REG_S x27, PT_S11(sp)
  69. REG_S x28, PT_T3(sp)
  70. REG_S x29, PT_T4(sp)
  71. REG_S x30, PT_T5(sp)
  72. REG_S x31, PT_T6(sp)
  73. /*
  74. * Disable user-mode memory access as it should only be set in the
  75. * actual user copy routines.
  76. *
  77. * Disable the FPU to detect illegal usage of floating point in kernel
  78. * space.
  79. */
  80. li t0, SR_SUM | SR_FS
  81. REG_L s0, TASK_TI_USER_SP(tp)
  82. csrrc s1, sstatus, t0
  83. csrr s2, sepc
  84. csrr s3, sbadaddr
  85. csrr s4, scause
  86. csrr s5, sscratch
  87. REG_S s0, PT_SP(sp)
  88. REG_S s1, PT_SSTATUS(sp)
  89. REG_S s2, PT_SEPC(sp)
  90. REG_S s3, PT_SBADADDR(sp)
  91. REG_S s4, PT_SCAUSE(sp)
  92. REG_S s5, PT_TP(sp)
  93. .endm
  94. /*
  95. * Prepares to return from a system call or exception by restoring all
  96. * registers from the stack.
  97. */
  98. .macro RESTORE_ALL
  99. REG_L a0, PT_SSTATUS(sp)
  100. REG_L a2, PT_SEPC(sp)
  101. csrw sstatus, a0
  102. csrw sepc, a2
  103. REG_L x1, PT_RA(sp)
  104. REG_L x3, PT_GP(sp)
  105. REG_L x4, PT_TP(sp)
  106. REG_L x5, PT_T0(sp)
  107. REG_L x6, PT_T1(sp)
  108. REG_L x7, PT_T2(sp)
  109. REG_L x8, PT_S0(sp)
  110. REG_L x9, PT_S1(sp)
  111. REG_L x10, PT_A0(sp)
  112. REG_L x11, PT_A1(sp)
  113. REG_L x12, PT_A2(sp)
  114. REG_L x13, PT_A3(sp)
  115. REG_L x14, PT_A4(sp)
  116. REG_L x15, PT_A5(sp)
  117. REG_L x16, PT_A6(sp)
  118. REG_L x17, PT_A7(sp)
  119. REG_L x18, PT_S2(sp)
  120. REG_L x19, PT_S3(sp)
  121. REG_L x20, PT_S4(sp)
  122. REG_L x21, PT_S5(sp)
  123. REG_L x22, PT_S6(sp)
  124. REG_L x23, PT_S7(sp)
  125. REG_L x24, PT_S8(sp)
  126. REG_L x25, PT_S9(sp)
  127. REG_L x26, PT_S10(sp)
  128. REG_L x27, PT_S11(sp)
  129. REG_L x28, PT_T3(sp)
  130. REG_L x29, PT_T4(sp)
  131. REG_L x30, PT_T5(sp)
  132. REG_L x31, PT_T6(sp)
  133. REG_L x2, PT_SP(sp)
  134. .endm
  135. ENTRY(handle_exception)
  136. SAVE_ALL
  137. /*
  138. * Set sscratch register to 0, so that if a recursive exception
  139. * occurs, the exception vector knows it came from the kernel
  140. */
  141. csrw sscratch, x0
  142. /* Load the global pointer */
  143. .option push
  144. .option norelax
  145. la gp, __global_pointer$
  146. .option pop
  147. la ra, ret_from_exception
  148. /*
  149. * MSB of cause differentiates between
  150. * interrupts and exceptions
  151. */
  152. bge s4, zero, 1f
  153. /* Handle interrupts */
  154. move a0, sp /* pt_regs */
  155. move a1, s4 /* scause */
  156. tail do_IRQ
  157. 1:
  158. /* Exceptions run with interrupts enabled or disabled
  159. depending on the state of sstatus.SR_SPIE */
  160. andi t0, s1, SR_SPIE
  161. beqz t0, 1f
  162. csrs sstatus, SR_SIE
  163. 1:
  164. /* Handle syscalls */
  165. li t0, EXC_SYSCALL
  166. beq s4, t0, handle_syscall
  167. /* Handle other exceptions */
  168. slli t0, s4, RISCV_LGPTR
  169. la t1, excp_vect_table
  170. la t2, excp_vect_table_end
  171. move a0, sp /* pt_regs */
  172. add t0, t1, t0
  173. /* Check if exception code lies within bounds */
  174. bgeu t0, t2, 1f
  175. REG_L t0, 0(t0)
  176. jr t0
  177. 1:
  178. tail do_trap_unknown
  179. handle_syscall:
  180. /* save the initial A0 value (needed in signal handlers) */
  181. REG_S a0, PT_ORIG_A0(sp)
  182. /*
  183. * Advance SEPC to avoid executing the original
  184. * scall instruction on sret
  185. */
  186. addi s2, s2, 0x4
  187. REG_S s2, PT_SEPC(sp)
  188. /* Trace syscalls, but only if requested by the user. */
  189. REG_L t0, TASK_TI_FLAGS(tp)
  190. andi t0, t0, _TIF_SYSCALL_TRACE
  191. bnez t0, handle_syscall_trace_enter
  192. check_syscall_nr:
  193. /* Check to make sure we don't jump to a bogus syscall number. */
  194. li t0, __NR_syscalls
  195. la s0, sys_ni_syscall
  196. /* Syscall number held in a7 */
  197. bgeu a7, t0, 1f
  198. la s0, sys_call_table
  199. slli t0, a7, RISCV_LGPTR
  200. add s0, s0, t0
  201. REG_L s0, 0(s0)
  202. 1:
  203. jalr s0
  204. ret_from_syscall:
  205. /* Set user a0 to kernel a0 */
  206. REG_S a0, PT_A0(sp)
  207. /* Trace syscalls, but only if requested by the user. */
  208. REG_L t0, TASK_TI_FLAGS(tp)
  209. andi t0, t0, _TIF_SYSCALL_TRACE
  210. bnez t0, handle_syscall_trace_exit
  211. ret_from_exception:
  212. REG_L s0, PT_SSTATUS(sp)
  213. csrc sstatus, SR_SIE
  214. andi s0, s0, SR_SPP
  215. bnez s0, restore_all
  216. resume_userspace:
  217. /* Interrupts must be disabled here so flags are checked atomically */
  218. REG_L s0, TASK_TI_FLAGS(tp) /* current_thread_info->flags */
  219. andi s1, s0, _TIF_WORK_MASK
  220. bnez s1, work_pending
  221. /* Save unwound kernel stack pointer in thread_info */
  222. addi s0, sp, PT_SIZE_ON_STACK
  223. REG_S s0, TASK_TI_KERNEL_SP(tp)
  224. /*
  225. * Save TP into sscratch, so we can find the kernel data structures
  226. * again.
  227. */
  228. csrw sscratch, tp
  229. restore_all:
  230. RESTORE_ALL
  231. sret
  232. work_pending:
  233. /* Enter slow path for supplementary processing */
  234. la ra, ret_from_exception
  235. andi s1, s0, _TIF_NEED_RESCHED
  236. bnez s1, work_resched
  237. work_notifysig:
  238. /* Handle pending signals and notify-resume requests */
  239. csrs sstatus, SR_SIE /* Enable interrupts for do_notify_resume() */
  240. move a0, sp /* pt_regs */
  241. move a1, s0 /* current_thread_info->flags */
  242. tail do_notify_resume
  243. work_resched:
  244. tail schedule
  245. /* Slow paths for ptrace. */
  246. handle_syscall_trace_enter:
  247. move a0, sp
  248. call do_syscall_trace_enter
  249. REG_L a0, PT_A0(sp)
  250. REG_L a1, PT_A1(sp)
  251. REG_L a2, PT_A2(sp)
  252. REG_L a3, PT_A3(sp)
  253. REG_L a4, PT_A4(sp)
  254. REG_L a5, PT_A5(sp)
  255. REG_L a6, PT_A6(sp)
  256. REG_L a7, PT_A7(sp)
  257. j check_syscall_nr
  258. handle_syscall_trace_exit:
  259. move a0, sp
  260. call do_syscall_trace_exit
  261. j ret_from_exception
  262. END(handle_exception)
  263. ENTRY(ret_from_fork)
  264. la ra, ret_from_exception
  265. tail schedule_tail
  266. ENDPROC(ret_from_fork)
  267. ENTRY(ret_from_kernel_thread)
  268. call schedule_tail
  269. /* Call fn(arg) */
  270. la ra, ret_from_exception
  271. move a0, s1
  272. jr s0
  273. ENDPROC(ret_from_kernel_thread)
  274. /*
  275. * Integer register context switch
  276. * The callee-saved registers must be saved and restored.
  277. *
  278. * a0: previous task_struct (must be preserved across the switch)
  279. * a1: next task_struct
  280. *
  281. * The value of a0 and a1 must be preserved by this function, as that's how
  282. * arguments are passed to schedule_tail.
  283. */
  284. ENTRY(__switch_to)
  285. /* Save context into prev->thread */
  286. li a4, TASK_THREAD_RA
  287. add a3, a0, a4
  288. add a4, a1, a4
  289. REG_S ra, TASK_THREAD_RA_RA(a3)
  290. REG_S sp, TASK_THREAD_SP_RA(a3)
  291. REG_S s0, TASK_THREAD_S0_RA(a3)
  292. REG_S s1, TASK_THREAD_S1_RA(a3)
  293. REG_S s2, TASK_THREAD_S2_RA(a3)
  294. REG_S s3, TASK_THREAD_S3_RA(a3)
  295. REG_S s4, TASK_THREAD_S4_RA(a3)
  296. REG_S s5, TASK_THREAD_S5_RA(a3)
  297. REG_S s6, TASK_THREAD_S6_RA(a3)
  298. REG_S s7, TASK_THREAD_S7_RA(a3)
  299. REG_S s8, TASK_THREAD_S8_RA(a3)
  300. REG_S s9, TASK_THREAD_S9_RA(a3)
  301. REG_S s10, TASK_THREAD_S10_RA(a3)
  302. REG_S s11, TASK_THREAD_S11_RA(a3)
  303. /* Restore context from next->thread */
  304. REG_L ra, TASK_THREAD_RA_RA(a4)
  305. REG_L sp, TASK_THREAD_SP_RA(a4)
  306. REG_L s0, TASK_THREAD_S0_RA(a4)
  307. REG_L s1, TASK_THREAD_S1_RA(a4)
  308. REG_L s2, TASK_THREAD_S2_RA(a4)
  309. REG_L s3, TASK_THREAD_S3_RA(a4)
  310. REG_L s4, TASK_THREAD_S4_RA(a4)
  311. REG_L s5, TASK_THREAD_S5_RA(a4)
  312. REG_L s6, TASK_THREAD_S6_RA(a4)
  313. REG_L s7, TASK_THREAD_S7_RA(a4)
  314. REG_L s8, TASK_THREAD_S8_RA(a4)
  315. REG_L s9, TASK_THREAD_S9_RA(a4)
  316. REG_L s10, TASK_THREAD_S10_RA(a4)
  317. REG_L s11, TASK_THREAD_S11_RA(a4)
  318. /* Swap the CPU entry around. */
  319. lw a3, TASK_TI_CPU(a0)
  320. lw a4, TASK_TI_CPU(a1)
  321. sw a3, TASK_TI_CPU(a1)
  322. sw a4, TASK_TI_CPU(a0)
  323. #if TASK_TI != 0
  324. #error "TASK_TI != 0: tp will contain a 'struct thread_info', not a 'struct task_struct' so get_current() won't work."
  325. addi tp, a1, TASK_TI
  326. #else
  327. move tp, a1
  328. #endif
  329. ret
  330. ENDPROC(__switch_to)
  331. ENTRY(__fstate_save)
  332. li a2, TASK_THREAD_F0
  333. add a0, a0, a2
  334. li t1, SR_FS
  335. csrs sstatus, t1
  336. frcsr t0
  337. fsd f0, TASK_THREAD_F0_F0(a0)
  338. fsd f1, TASK_THREAD_F1_F0(a0)
  339. fsd f2, TASK_THREAD_F2_F0(a0)
  340. fsd f3, TASK_THREAD_F3_F0(a0)
  341. fsd f4, TASK_THREAD_F4_F0(a0)
  342. fsd f5, TASK_THREAD_F5_F0(a0)
  343. fsd f6, TASK_THREAD_F6_F0(a0)
  344. fsd f7, TASK_THREAD_F7_F0(a0)
  345. fsd f8, TASK_THREAD_F8_F0(a0)
  346. fsd f9, TASK_THREAD_F9_F0(a0)
  347. fsd f10, TASK_THREAD_F10_F0(a0)
  348. fsd f11, TASK_THREAD_F11_F0(a0)
  349. fsd f12, TASK_THREAD_F12_F0(a0)
  350. fsd f13, TASK_THREAD_F13_F0(a0)
  351. fsd f14, TASK_THREAD_F14_F0(a0)
  352. fsd f15, TASK_THREAD_F15_F0(a0)
  353. fsd f16, TASK_THREAD_F16_F0(a0)
  354. fsd f17, TASK_THREAD_F17_F0(a0)
  355. fsd f18, TASK_THREAD_F18_F0(a0)
  356. fsd f19, TASK_THREAD_F19_F0(a0)
  357. fsd f20, TASK_THREAD_F20_F0(a0)
  358. fsd f21, TASK_THREAD_F21_F0(a0)
  359. fsd f22, TASK_THREAD_F22_F0(a0)
  360. fsd f23, TASK_THREAD_F23_F0(a0)
  361. fsd f24, TASK_THREAD_F24_F0(a0)
  362. fsd f25, TASK_THREAD_F25_F0(a0)
  363. fsd f26, TASK_THREAD_F26_F0(a0)
  364. fsd f27, TASK_THREAD_F27_F0(a0)
  365. fsd f28, TASK_THREAD_F28_F0(a0)
  366. fsd f29, TASK_THREAD_F29_F0(a0)
  367. fsd f30, TASK_THREAD_F30_F0(a0)
  368. fsd f31, TASK_THREAD_F31_F0(a0)
  369. sw t0, TASK_THREAD_FCSR_F0(a0)
  370. csrc sstatus, t1
  371. ret
  372. ENDPROC(__fstate_save)
  373. ENTRY(__fstate_restore)
  374. li a2, TASK_THREAD_F0
  375. add a0, a0, a2
  376. li t1, SR_FS
  377. lw t0, TASK_THREAD_FCSR_F0(a0)
  378. csrs sstatus, t1
  379. fld f0, TASK_THREAD_F0_F0(a0)
  380. fld f1, TASK_THREAD_F1_F0(a0)
  381. fld f2, TASK_THREAD_F2_F0(a0)
  382. fld f3, TASK_THREAD_F3_F0(a0)
  383. fld f4, TASK_THREAD_F4_F0(a0)
  384. fld f5, TASK_THREAD_F5_F0(a0)
  385. fld f6, TASK_THREAD_F6_F0(a0)
  386. fld f7, TASK_THREAD_F7_F0(a0)
  387. fld f8, TASK_THREAD_F8_F0(a0)
  388. fld f9, TASK_THREAD_F9_F0(a0)
  389. fld f10, TASK_THREAD_F10_F0(a0)
  390. fld f11, TASK_THREAD_F11_F0(a0)
  391. fld f12, TASK_THREAD_F12_F0(a0)
  392. fld f13, TASK_THREAD_F13_F0(a0)
  393. fld f14, TASK_THREAD_F14_F0(a0)
  394. fld f15, TASK_THREAD_F15_F0(a0)
  395. fld f16, TASK_THREAD_F16_F0(a0)
  396. fld f17, TASK_THREAD_F17_F0(a0)
  397. fld f18, TASK_THREAD_F18_F0(a0)
  398. fld f19, TASK_THREAD_F19_F0(a0)
  399. fld f20, TASK_THREAD_F20_F0(a0)
  400. fld f21, TASK_THREAD_F21_F0(a0)
  401. fld f22, TASK_THREAD_F22_F0(a0)
  402. fld f23, TASK_THREAD_F23_F0(a0)
  403. fld f24, TASK_THREAD_F24_F0(a0)
  404. fld f25, TASK_THREAD_F25_F0(a0)
  405. fld f26, TASK_THREAD_F26_F0(a0)
  406. fld f27, TASK_THREAD_F27_F0(a0)
  407. fld f28, TASK_THREAD_F28_F0(a0)
  408. fld f29, TASK_THREAD_F29_F0(a0)
  409. fld f30, TASK_THREAD_F30_F0(a0)
  410. fld f31, TASK_THREAD_F31_F0(a0)
  411. fscsr t0
  412. csrc sstatus, t1
  413. ret
  414. ENDPROC(__fstate_restore)
  415. .section ".rodata"
  416. /* Exception vector table */
  417. ENTRY(excp_vect_table)
  418. RISCV_PTR do_trap_insn_misaligned
  419. RISCV_PTR do_trap_insn_fault
  420. RISCV_PTR do_trap_insn_illegal
  421. RISCV_PTR do_trap_break
  422. RISCV_PTR do_trap_load_misaligned
  423. RISCV_PTR do_trap_load_fault
  424. RISCV_PTR do_trap_store_misaligned
  425. RISCV_PTR do_trap_store_fault
  426. RISCV_PTR do_trap_ecall_u /* system call, gets intercepted */
  427. RISCV_PTR do_trap_ecall_s
  428. RISCV_PTR do_trap_unknown
  429. RISCV_PTR do_trap_ecall_m
  430. RISCV_PTR do_page_fault /* instruction page fault */
  431. RISCV_PTR do_page_fault /* load page fault */
  432. RISCV_PTR do_trap_unknown
  433. RISCV_PTR do_page_fault /* store page fault */
  434. excp_vect_table_end:
  435. END(excp_vect_table)