lwp_arch.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. * 2020-11-18 Jesven first version
  9. * 2021-02-03 lizhirui port to riscv64
  10. * 2021-02-06 lizhirui add thread filter
  11. * 2021-02-19 lizhirui port to new version of rt-smart
  12. * 2021-03-02 lizhirui add a auxillary function for interrupt
  13. * 2021-03-04 lizhirui delete thread filter
  14. * 2021-03-04 lizhirui modify for new version of rt-smart
  15. */
  16. #include <rthw.h>
  17. #include <stddef.h>
  18. #ifdef RT_USING_USERSPACE
  19. #include <mmu.h>
  20. #include <page.h>
  21. #include <lwp_mm_area.h>
  22. #include <lwp_user_mm.h>
  23. #include <lwp_arch.h>
  24. #include <stack.h>
  25. #include <cpuport.h>
  26. #include <encoding.h>
  27. extern size_t MMUTable[];
  28. int arch_expand_user_stack(void *addr)
  29. {
  30. int ret = 0;
  31. size_t stack_addr = (size_t)addr;
  32. stack_addr &= ~PAGE_OFFSET_MASK;
  33. if ((stack_addr >= (size_t)USER_STACK_VSTART) && (stack_addr < (size_t)USER_STACK_VEND))
  34. {
  35. void *map = lwp_map_user(lwp_self(), (void *)stack_addr, PAGE_SIZE, RT_FALSE);
  36. if (map || lwp_user_accessable(addr, 1))
  37. {
  38. ret = 1;
  39. }
  40. }
  41. return ret;
  42. }
  43. void *lwp_copy_return_code_to_user_stack()
  44. {
  45. void lwp_thread_return();
  46. void lwp_thread_return_end();
  47. rt_thread_t tid = rt_thread_self();
  48. if (tid->user_stack != RT_NULL)
  49. {
  50. size_t size = (size_t)lwp_thread_return_end - (size_t)lwp_thread_return;
  51. size_t userstack = (size_t)tid->user_stack + tid->user_stack_size - size;
  52. memcpy((void *)userstack, lwp_thread_return, size);
  53. return (void *)userstack;
  54. }
  55. return RT_NULL;
  56. }
  57. rt_mmu_info* arch_kernel_get_mmu_info(void)
  58. {
  59. extern rt_mmu_info *mmu_info;
  60. return mmu_info;
  61. }
  62. uint32_t lwp_fix_sp(uint32_t cursp)
  63. {
  64. void lwp_thread_return();
  65. void lwp_thread_return_end();
  66. if (cursp == 0)
  67. {
  68. return 0;
  69. }
  70. return cursp - ((size_t)lwp_thread_return_end - (size_t)lwp_thread_return);
  71. }
  72. rt_thread_t rt_thread_sp_to_thread(void *spmember_addr)
  73. {
  74. return (rt_thread_t)(((rt_ubase_t)spmember_addr) - (offsetof(struct rt_thread, sp)));
  75. }
  76. void *get_thread_kernel_stack_top(rt_thread_t thread)
  77. {
  78. return (void *)(((rt_size_t)thread->stack_addr) + ((rt_size_t)thread->stack_size));
  79. }
  80. //don't support this temporarily in riscv
  81. void *lwp_get_user_sp()
  82. {
  83. return RT_NULL;
  84. }
  85. int arch_user_space_init(struct rt_lwp *lwp)
  86. {
  87. size_t *mmu_table;
  88. mmu_table = (size_t *)rt_pages_alloc(0);
  89. if (!mmu_table)
  90. {
  91. return -1;
  92. }
  93. lwp->end_heap = USER_HEAP_VADDR;
  94. memcpy(mmu_table, MMUTable, PAGE_SIZE);
  95. rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, mmu_table, 4 * PAGE_SIZE);
  96. rt_hw_mmu_map_init(&lwp->mmu_info, (void *)0x100000000UL, 0xFFFFFFFEFFFFFFFFUL, (rt_size_t *)mmu_table, 0);
  97. return 0;
  98. }
  99. void *arch_kernel_mmu_table_get(void)
  100. {
  101. return (void *)((char *)MMUTable);
  102. }
  103. void arch_user_space_vtable_free(struct rt_lwp *lwp)
  104. {
  105. if (lwp && lwp->mmu_info.vtable)
  106. {
  107. rt_pages_free(lwp->mmu_info.vtable, 0);
  108. }
  109. }
  110. long _sys_clone(void *arg[]);
  111. long sys_clone(void *arg[])
  112. {
  113. return _sys_clone(arg);
  114. }
  115. /**
  116. * set exec context for fork/clone.
  117. */
  118. void lwp_set_thread_context(void *exit_addr, void *new_thread_stack, void *user_stack, void **thread_sp)
  119. {
  120. struct rt_hw_stack_frame *syscall_frame;
  121. struct rt_hw_stack_frame *thread_frame;
  122. rt_uint8_t *stk;
  123. rt_uint8_t *syscall_stk;
  124. stk = (rt_uint8_t *)new_thread_stack;
  125. /* reserve syscall context, all the registers are copyed from parent */
  126. stk -= CTX_REG_NR * REGBYTES;
  127. syscall_stk = stk;
  128. syscall_frame = (struct rt_hw_stack_frame *)stk;
  129. /* modify user sp */
  130. syscall_frame->user_sp_exc_stack = (rt_ubase_t)user_stack;
  131. /* skip ecall */
  132. syscall_frame->epc += 4;
  133. /* child return value is 0 */
  134. syscall_frame->a0 = 0;
  135. syscall_frame->a1 = 0;
  136. /* build temp thread context */
  137. stk -= sizeof(struct rt_hw_stack_frame);
  138. thread_frame = (struct rt_hw_stack_frame *)stk;
  139. int i;
  140. for (i = 0; i < sizeof(struct rt_hw_stack_frame) / sizeof(rt_ubase_t); i++)
  141. {
  142. ((rt_ubase_t *)thread_frame)[i] = 0xdeadbeaf;
  143. }
  144. /* set pc for thread */
  145. thread_frame->epc = (rt_ubase_t)exit_addr;
  146. /* set old exception mode as supervisor, because in kernel */
  147. thread_frame->sstatus = read_csr(sstatus) | SSTATUS_SPP;
  148. /* set stack as syscall stack */
  149. thread_frame->user_sp_exc_stack = (rt_ubase_t)syscall_stk;
  150. /* save new stack top */
  151. *thread_sp = (void *)stk;
  152. /**
  153. * The stack for child thread:
  154. *
  155. * +------------------------+ --> kernel stack top
  156. * | syscall stack |
  157. * | |
  158. * | @sp | --> `user_stack`
  159. * | @epc | --> user ecall addr + 4 (skip ecall)
  160. * | @a0&a1 | --> 0 (for child return 0)
  161. * | |
  162. * +------------------------+ --> temp thread stack top
  163. * | temp thread stack | ^
  164. * | | |
  165. * | @sp | ---------/
  166. * | @epc | --> `exit_addr` (sys_clone_exit/sys_fork_exit)
  167. * | |
  168. * +------------------------+ --> thread sp
  169. */
  170. }
  171. #endif