lwp_gcc.S 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-05-18 Jesven first version
  9. */
  10. #include "rtconfig.h"
  11. #include "asm-generic.h"
  12. #include "asm-fpu.h"
  13. /*********************
  14. * SPSR BIT *
  15. *********************/
  16. #define SPSR_Mode(v) ((v) << 0)
  17. #define SPSR_A64 (0 << 4)
  18. #define SPSR_RESEVRED_5 (0 << 5)
  19. #define SPSR_FIQ_MASKED(v) ((v) << 6)
  20. #define SPSR_IRQ_MASKED(v) ((v) << 7)
  21. #define SPSR_SERROR_MASKED(v) ((v) << 8)
  22. #define SPSR_D_MASKED(v) ((v) << 9)
  23. #define SPSR_RESEVRED_10_19 (0 << 10)
  24. #define SPSR_IL(v) ((v) << 20)
  25. #define SPSR_SS(v) ((v) << 21)
  26. #define SPSR_RESEVRED_22_27 (0 << 22)
  27. #define SPSR_V(v) ((v) << 28)
  28. #define SPSR_C(v) ((v) << 29)
  29. #define SPSR_Z(v) ((v) << 30)
  30. #define SPSR_N(v) ((v) << 31)
  31. /*********************
  32. * CONTEXT_OFFSET *
  33. *********************/
  34. #define CONTEXT_OFFSET_ELR_EL1 0x0
  35. #define CONTEXT_OFFSET_SPSR_EL1 0x8
  36. #define CONTEXT_OFFSET_SP_EL0 0x10
  37. #define CONTEXT_OFFSET_X30 0x18
  38. #define CONTEXT_OFFSET_FPCR 0x20
  39. #define CONTEXT_OFFSET_FPSR 0x28
  40. #define CONTEXT_OFFSET_X28 0x30
  41. #define CONTEXT_OFFSET_X29 0x38
  42. #define CONTEXT_OFFSET_X26 0x40
  43. #define CONTEXT_OFFSET_X27 0x48
  44. #define CONTEXT_OFFSET_X24 0x50
  45. #define CONTEXT_OFFSET_X25 0x58
  46. #define CONTEXT_OFFSET_X22 0x60
  47. #define CONTEXT_OFFSET_X23 0x68
  48. #define CONTEXT_OFFSET_X20 0x70
  49. #define CONTEXT_OFFSET_X21 0x78
  50. #define CONTEXT_OFFSET_X18 0x80
  51. #define CONTEXT_OFFSET_X19 0x88
  52. #define CONTEXT_OFFSET_X16 0x90
  53. #define CONTEXT_OFFSET_X17 0x98
  54. #define CONTEXT_OFFSET_X14 0xa0
  55. #define CONTEXT_OFFSET_X15 0xa8
  56. #define CONTEXT_OFFSET_X12 0xb0
  57. #define CONTEXT_OFFSET_X13 0xb8
  58. #define CONTEXT_OFFSET_X10 0xc0
  59. #define CONTEXT_OFFSET_X11 0xc8
  60. #define CONTEXT_OFFSET_X8 0xd0
  61. #define CONTEXT_OFFSET_X9 0xd8
  62. #define CONTEXT_OFFSET_X6 0xe0
  63. #define CONTEXT_OFFSET_X7 0xe8
  64. #define CONTEXT_OFFSET_X4 0xf0
  65. #define CONTEXT_OFFSET_X5 0xf8
  66. #define CONTEXT_OFFSET_X2 0x100
  67. #define CONTEXT_OFFSET_X3 0x108
  68. #define CONTEXT_OFFSET_X0 0x110
  69. #define CONTEXT_OFFSET_X1 0x118
  70. #define CONTEXT_OFFSET_Q15 0x120
  71. #define CONTEXT_OFFSET_Q14 0x130
  72. #define CONTEXT_OFFSET_Q13 0x140
  73. #define CONTEXT_OFFSET_Q12 0x150
  74. #define CONTEXT_OFFSET_Q11 0x160
  75. #define CONTEXT_OFFSET_Q10 0x170
  76. #define CONTEXT_OFFSET_Q9 0x180
  77. #define CONTEXT_OFFSET_Q8 0x190
  78. #define CONTEXT_OFFSET_Q7 0x1a0
  79. #define CONTEXT_OFFSET_Q6 0x1b0
  80. #define CONTEXT_OFFSET_Q5 0x1c0
  81. #define CONTEXT_OFFSET_Q4 0x1d0
  82. #define CONTEXT_OFFSET_Q3 0x1e0
  83. #define CONTEXT_OFFSET_Q2 0x1f0
  84. #define CONTEXT_OFFSET_Q1 0x200
  85. #define CONTEXT_OFFSET_Q0 0x210
  86. #define CONTEXT_FPU_SIZE 0x100
  87. #define CONTEXT_SIZE 0x220
  88. /**************************************************/
  89. .text
  90. /*
  91. * void arch_start_umode(args, text, ustack, kstack);
  92. */
  93. .global arch_start_umode
  94. .type arch_start_umode, % function
  95. arch_start_umode:
  96. mov sp, x3
  97. mov x4, #(SPSR_Mode(0) | SPSR_A64)
  98. mov x3, x2 ;/* user stack top */
  99. msr daifset, #3
  100. dsb sy
  101. mrs x30, sp_el0
  102. msr spsr_el1, x4
  103. msr elr_el1, x1
  104. eret
  105. /*
  106. * void arch_crt_start_umode(args, text, ustack, kstack);
  107. */
  108. .global arch_crt_start_umode
  109. .type arch_crt_start_umode, % function
  110. arch_crt_start_umode:
  111. sub x4, x2, #0x10
  112. adr x2, lwp_thread_return
  113. ldr x5, [x2]
  114. str x5, [x4]
  115. ldr x5, [x2, #4]
  116. str x5, [x4, #4]
  117. ldr x5, [x2, #8]
  118. str x5, [x4, #8]
  119. mov x5, x4
  120. dc cvau, x5
  121. add x5, x5, #8
  122. dc cvau, x5
  123. dsb sy
  124. ic ialluis
  125. dsb sy
  126. msr sp_el0, x4
  127. mov sp, x3
  128. mov x4, #(SPSR_Mode(0) | SPSR_A64)
  129. msr daifset, #3
  130. dsb sy
  131. mrs x30, sp_el0
  132. msr spsr_el1, x4
  133. msr elr_el1, x1
  134. eret
  135. /*
  136. void arch_set_thread_context(void *exit_addr, void *new_thread_stack, void *user_stack, void **thread_sp);
  137. */
  138. .global arch_set_thread_context
  139. arch_set_thread_context:
  140. sub x1, x1, #CONTEXT_SIZE
  141. str x2, [x1, #CONTEXT_OFFSET_SP_EL0]
  142. sub x1, x1, #CONTEXT_SIZE
  143. str xzr, [x1, #CONTEXT_OFFSET_X0] /* new thread return 0 */
  144. mov x4, #((3 << 6) | 0x4 | 0x1) /* el1h, disable interrupt */
  145. str x4, [x1, #CONTEXT_OFFSET_SPSR_EL1]
  146. str x0, [x1, #CONTEXT_OFFSET_ELR_EL1]
  147. str x1, [x3]
  148. ret
  149. .global arch_get_user_sp
  150. arch_get_user_sp:
  151. mrs x0, sp_el0
  152. ret
  153. .global arch_fork_exit
  154. .global arch_clone_exit
  155. arch_fork_exit:
  156. arch_clone_exit:
  157. b arch_syscall_exit
  158. /*
  159. void lwp_exec_user(void *args, void *kernel_stack, void *user_entry)
  160. */
  161. .global lwp_exec_user
  162. lwp_exec_user:
  163. mov sp, x1
  164. mov x4, #(SPSR_Mode(0) | SPSR_A64)
  165. ldr x3, =0x0000ffff80000000
  166. msr daifset, #3
  167. msr spsr_el1, x4
  168. msr elr_el1, x2
  169. eret
  170. /*
  171. * void SVC_Handler(regs);
  172. * since this routine reset the SP, we take it as a start point
  173. */
  174. START_POINT(SVC_Handler)
  175. /* x0 is initial sp */
  176. mov sp, x0
  177. msr daifclr, #3 /* enable interrupt */
  178. bl rt_thread_self
  179. bl lwp_user_setting_save
  180. ldp x8, x9, [sp, #(CONTEXT_OFFSET_X8)]
  181. and x0, x8, #0xf000
  182. cmp x0, #0xe000
  183. beq arch_signal_quit
  184. cmp x0, #0xf000
  185. beq ret_from_user
  186. uxtb x0, w8
  187. bl lwp_get_sys_api
  188. cmp x0, xzr
  189. mov x30, x0
  190. beq arch_syscall_exit
  191. ldp x0, x1, [sp, #(CONTEXT_OFFSET_X0)]
  192. ldp x2, x3, [sp, #(CONTEXT_OFFSET_X2)]
  193. ldp x4, x5, [sp, #(CONTEXT_OFFSET_X4)]
  194. ldp x6, x7, [sp, #(CONTEXT_OFFSET_X6)]
  195. blr x30
  196. /* jump explictly, make this code position independant */
  197. b arch_syscall_exit
  198. START_POINT_END(SVC_Handler)
  199. .global arch_syscall_exit
  200. arch_syscall_exit:
  201. msr daifset, #3
  202. ldp x2, x3, [sp], #0x10 /* SPSR and ELR. */
  203. msr spsr_el1, x3
  204. msr elr_el1, x2
  205. ldp x29, x30, [sp], #0x10
  206. msr sp_el0, x29
  207. ldp x28, x29, [sp], #0x10
  208. msr fpcr, x28
  209. msr fpsr, x29
  210. ldp x28, x29, [sp], #0x10
  211. ldp x26, x27, [sp], #0x10
  212. ldp x24, x25, [sp], #0x10
  213. ldp x22, x23, [sp], #0x10
  214. ldp x20, x21, [sp], #0x10
  215. ldp x18, x19, [sp], #0x10
  216. ldp x16, x17, [sp], #0x10
  217. ldp x14, x15, [sp], #0x10
  218. ldp x12, x13, [sp], #0x10
  219. ldp x10, x11, [sp], #0x10
  220. ldp x8, x9, [sp], #0x10
  221. add sp, sp, #0x40
  222. RESTORE_FPU sp
  223. .global arch_ret_to_user
  224. arch_ret_to_user:
  225. SAVE_FPU sp
  226. stp x0, x1, [sp, #-0x10]!
  227. stp x2, x3, [sp, #-0x10]!
  228. stp x4, x5, [sp, #-0x10]!
  229. stp x6, x7, [sp, #-0x10]!
  230. stp x8, x9, [sp, #-0x10]!
  231. stp x10, x11, [sp, #-0x10]!
  232. stp x12, x13, [sp, #-0x10]!
  233. stp x14, x15, [sp, #-0x10]!
  234. stp x16, x17, [sp, #-0x10]!
  235. stp x18, x19, [sp, #-0x10]!
  236. stp x20, x21, [sp, #-0x10]!
  237. stp x22, x23, [sp, #-0x10]!
  238. stp x24, x25, [sp, #-0x10]!
  239. stp x26, x27, [sp, #-0x10]!
  240. stp x28, x29, [sp, #-0x10]!
  241. mrs x0, fpcr
  242. mrs x1, fpsr
  243. stp x0, x1, [sp, #-0x10]!
  244. stp x29, x30, [sp, #-0x10]!
  245. bl lwp_check_debug
  246. bl lwp_check_exit_request
  247. cbz w0, 1f
  248. mov x0, xzr
  249. b sys_exit
  250. 1:
  251. ldr x0, =rt_dbg_ops
  252. ldr x0, [x0]
  253. cbz x0, 3f
  254. bl dbg_thread_in_debug
  255. mov x1, #(1 << 21)
  256. mrs x2, spsr_el1
  257. cbz w0, 2f
  258. orr x2, x2, x1
  259. msr spsr_el1, x2
  260. b 3f
  261. 2:
  262. bic x2, x2, x1
  263. msr spsr_el1, x2
  264. 3:
  265. bl lwp_signal_check
  266. cmp x0, xzr
  267. ldp x29, x30, [sp], #0x10
  268. ldp x0, x1, [sp], #0x10
  269. msr fpcr, x0
  270. msr fpsr, x1
  271. ldp x28, x29, [sp], #0x10
  272. ldp x26, x27, [sp], #0x10
  273. ldp x24, x25, [sp], #0x10
  274. ldp x22, x23, [sp], #0x10
  275. ldp x20, x21, [sp], #0x10
  276. ldp x18, x19, [sp], #0x10
  277. ldp x16, x17, [sp], #0x10
  278. ldp x14, x15, [sp], #0x10
  279. ldp x12, x13, [sp], #0x10
  280. ldp x10, x11, [sp], #0x10
  281. ldp x8, x9, [sp], #0x10
  282. ldp x6, x7, [sp], #0x10
  283. ldp x4, x5, [sp], #0x10
  284. ldp x2, x3, [sp], #0x10
  285. ldp x0, x1, [sp], #0x10
  286. RESTORE_FPU sp
  287. bne user_do_signal
  288. stp x0, x1, [sp, #-0x10]!
  289. ldr x0, =rt_dbg_ops
  290. ldr x0, [x0]
  291. cmp x0, xzr
  292. ldp x0, x1, [sp], #0x10
  293. beq 1f
  294. SAVE_FPU sp
  295. stp x0, x1, [sp, #-0x10]!
  296. stp x2, x3, [sp, #-0x10]!
  297. stp x4, x5, [sp, #-0x10]!
  298. stp x6, x7, [sp, #-0x10]!
  299. stp x8, x9, [sp, #-0x10]!
  300. stp x10, x11, [sp, #-0x10]!
  301. stp x12, x13, [sp, #-0x10]!
  302. stp x14, x15, [sp, #-0x10]!
  303. stp x16, x17, [sp, #-0x10]!
  304. stp x18, x19, [sp, #-0x10]!
  305. stp x20, x21, [sp, #-0x10]!
  306. stp x22, x23, [sp, #-0x10]!
  307. stp x24, x25, [sp, #-0x10]!
  308. stp x26, x27, [sp, #-0x10]!
  309. stp x28, x29, [sp, #-0x10]!
  310. mrs x0, fpcr
  311. mrs x1, fpsr
  312. stp x0, x1, [sp, #-0x10]!
  313. stp x29, x30, [sp, #-0x10]!
  314. mrs x0, elr_el1
  315. bl dbg_attach_req
  316. ldp x29, x30, [sp], #0x10
  317. ldp x0, x1, [sp], #0x10
  318. msr fpcr, x0
  319. msr fpsr, x1
  320. ldp x28, x29, [sp], #0x10
  321. ldp x26, x27, [sp], #0x10
  322. ldp x24, x25, [sp], #0x10
  323. ldp x22, x23, [sp], #0x10
  324. ldp x20, x21, [sp], #0x10
  325. ldp x18, x19, [sp], #0x10
  326. ldp x16, x17, [sp], #0x10
  327. ldp x14, x15, [sp], #0x10
  328. ldp x12, x13, [sp], #0x10
  329. ldp x10, x11, [sp], #0x10
  330. ldp x8, x9, [sp], #0x10
  331. ldp x6, x7, [sp], #0x10
  332. ldp x4, x5, [sp], #0x10
  333. ldp x2, x3, [sp], #0x10
  334. ldp x0, x1, [sp], #0x10
  335. RESTORE_FPU sp
  336. 1:
  337. eret
  338. /*
  339. struct rt_hw_exp_stack
  340. {
  341. unsigned long pc; 0
  342. unsigned long cpsr;
  343. unsigned long sp_el0; 0x10
  344. unsigned long x30;
  345. unsigned long fpcr; 0x20
  346. unsigned long fpsr;
  347. unsigned long x28; 0x30
  348. unsigned long x29;
  349. unsigned long x26; 0x40
  350. unsigned long x27;
  351. unsigned long x24; 0x50
  352. unsigned long x25;
  353. unsigned long x22; 0x60
  354. unsigned long x23;
  355. unsigned long x20; 0x70
  356. unsigned long x21;
  357. unsigned long x18; 0x80
  358. unsigned long x19;
  359. unsigned long x16; 0x90
  360. unsigned long x17;
  361. unsigned long x14; 0xa0
  362. unsigned long x15;
  363. unsigned long x12; 0xb0
  364. unsigned long x13;
  365. unsigned long x10; 0xc0
  366. unsigned long x11;
  367. unsigned long x8; 0xd0
  368. unsigned long x9;
  369. unsigned long x6; 0xe0
  370. unsigned long x7;
  371. unsigned long x4; 0xf0
  372. unsigned long x5;
  373. unsigned long x2; 0x100
  374. unsigned long x3;
  375. unsigned long x0; 0x110
  376. unsigned long x1;
  377. unsigned long long fpu[16]; 0x120
  378. 0x220 = 0x120 + 0x10 * 0x10
  379. };
  380. */
  381. .global lwp_check_debug
  382. lwp_check_debug:
  383. ldr x0, =rt_dbg_ops
  384. ldr x0, [x0]
  385. cbnz x0, 1f
  386. ret
  387. 1:
  388. stp x29, x30, [sp, #-0x10]!
  389. bl dbg_check_suspend
  390. cbz w0, lwp_check_debug_quit
  391. mrs x2, sp_el0
  392. sub x2, x2, #0x10
  393. mov x3, x2
  394. msr sp_el0, x2
  395. ldr x0, =lwp_debugreturn
  396. ldr w1, [x0]
  397. str w1, [x2]
  398. ldr w1, [x0, #4]
  399. str w1, [x2, #4]
  400. dc cvau, x2
  401. add x2, x2, #4
  402. dc cvau, x2
  403. dsb sy
  404. isb sy
  405. ic ialluis
  406. isb sy
  407. mrs x0, elr_el1
  408. mrs x1, spsr_el1
  409. stp x0, x1, [sp, #-0x10]!
  410. msr elr_el1, x3 /* lwp_debugreturn */
  411. mov x1, #(SPSR_Mode(0) | SPSR_A64)
  412. orr x1, x1, #(1 << 21)
  413. msr spsr_el1, x1
  414. eret
  415. ret_from_user:
  416. /* sp_el0 += 16 for drop ins lwp_debugreturn */
  417. mrs x0, sp_el0
  418. add x0, x0, #0x10
  419. msr sp_el0, x0
  420. /* now is el1, sp is pos(empty) - sizeof(context) */
  421. mov x0, sp
  422. add x0, x0, #0x220
  423. mov sp, x0
  424. ldp x0, x1, [sp], #0x10 /* x1 is origin spsr_el1 */
  425. msr elr_el1, x0 /* x0 is origin elr_el1 */
  426. msr spsr_el1, x1
  427. lwp_check_debug_quit:
  428. ldp x29, x30, [sp], #0x10
  429. ret
  430. arch_signal_quit:
  431. msr daifset, #3
  432. /*
  433. drop stack data
  434. */
  435. add sp, sp, #CONTEXT_SIZE
  436. bl lwp_signal_restore
  437. /* x0 is user_ctx : ori sp, pc, cpsr */
  438. ldr x1, [x0]
  439. ldr x2, [x0, #8]
  440. ldr x3, [x0, #16]
  441. msr spsr_el1, x3
  442. msr elr_el1, x2
  443. add x1, x1, #16
  444. msr sp_el0, x1
  445. msr spsel, #0
  446. ldp x29, x30, [sp], #0x10
  447. ldp x28, x29, [sp], #0x10
  448. msr fpcr, x28
  449. msr fpsr, x29
  450. ldp x28, x29, [sp], #0x10
  451. ldp x26, x27, [sp], #0x10
  452. ldp x24, x25, [sp], #0x10
  453. ldp x22, x23, [sp], #0x10
  454. ldp x20, x21, [sp], #0x10
  455. ldp x18, x19, [sp], #0x10
  456. ldp x16, x17, [sp], #0x10
  457. ldp x14, x15, [sp], #0x10
  458. ldp x12, x13, [sp], #0x10
  459. ldp x10, x11, [sp], #0x10
  460. ldp x8, x9, [sp], #0x10
  461. ldp x6, x7, [sp], #0x10
  462. ldp x4, x5, [sp], #0x10
  463. ldp x2, x3, [sp], #0x10
  464. ldp x0, x1, [sp], #0x10
  465. RESTORE_FPU sp
  466. msr spsel, #1
  467. b arch_ret_to_user
  468. user_do_signal:
  469. msr spsel, #0
  470. SAVE_FPU sp
  471. stp x0, x1, [sp, #-0x10]!
  472. stp x2, x3, [sp, #-0x10]!
  473. stp x4, x5, [sp, #-0x10]!
  474. stp x6, x7, [sp, #-0x10]!
  475. stp x8, x9, [sp, #-0x10]!
  476. stp x10, x11, [sp, #-0x10]!
  477. stp x12, x13, [sp, #-0x10]!
  478. stp x14, x15, [sp, #-0x10]!
  479. stp x16, x17, [sp, #-0x10]!
  480. stp x18, x19, [sp, #-0x10]!
  481. stp x20, x21, [sp, #-0x10]!
  482. stp x22, x23, [sp, #-0x10]!
  483. stp x24, x25, [sp, #-0x10]!
  484. stp x26, x27, [sp, #-0x10]!
  485. stp x28, x29, [sp, #-0x10]!
  486. mrs x28, fpcr
  487. mrs x29, fpsr
  488. stp x28, x29, [sp, #-0x10]!
  489. stp x29, x30, [sp, #-0x10]!
  490. sub sp, sp, #0x10
  491. adr x0, lwp_sigreturn
  492. ldr w1, [x0]
  493. str w1, [sp]
  494. ldr w1, [x0, #4]
  495. str w1, [sp, #4]
  496. mov x20, sp /* lwp_sigreturn */
  497. mov x0, sp
  498. dc cvau, x0
  499. dsb sy
  500. ic ialluis
  501. dsb sy
  502. msr spsel, #1
  503. mrs x1, elr_el1
  504. mrs x2, spsr_el1
  505. bl lwp_signal_backup
  506. /* x0 is signal */
  507. mov x19, x0
  508. bl lwp_sighandler_get
  509. adds x1, x0, xzr
  510. mov x0, x19
  511. bne 1f
  512. mov x1, x20
  513. 1:
  514. msr elr_el1, x1
  515. mov x30, x20
  516. eret
  517. lwp_debugreturn:
  518. mov x8, 0xf000
  519. svc #0
  520. lwp_sigreturn:
  521. mov x8, #0xe000
  522. svc #0
  523. lwp_thread_return:
  524. mov x0, xzr
  525. mov x8, #0x01
  526. svc #0
  527. .globl arch_get_tidr
  528. arch_get_tidr:
  529. mrs x0, tpidr_el0
  530. ret
  531. .global arch_set_thread_area
  532. arch_set_thread_area:
  533. .globl arch_set_tidr
  534. arch_set_tidr:
  535. msr tpidr_el0, x0
  536. ret