1 #include "process.h"
2 #include <common/err.h>
3 #include <common/kthread.h>
4 #include <common/spinlock.h>
5 
6 extern spinlock_t process_global_pid_write_lock;
7 extern long process_global_pid;
8 
9 extern void kernel_thread_func(void);
10 extern uint64_t rs_procfs_register_pid(uint64_t);
11 extern uint64_t rs_procfs_unregister_pid(uint64_t);
12 extern void *rs_dup_fpstate();
13 extern uint64_t rs_process_copy_mm(bool clone_vm, struct process_control_block *new_pcb);
14 
15 extern int process_copy_files(uint64_t clone_flags, struct process_control_block *pcb);
16 int process_copy_flags(uint64_t clone_flags, struct process_control_block *pcb);
17 int process_copy_mm(uint64_t clone_flags, struct process_control_block *pcb);
18 int process_copy_thread(uint64_t clone_flags, struct process_control_block *pcb, uint64_t stack_start,
19                         uint64_t stack_size, struct pt_regs *current_regs);
20 
21 extern int process_copy_sighand(uint64_t clone_flags, struct process_control_block *pcb);
22 extern int process_copy_signal(uint64_t clone_flags, struct process_control_block *pcb);
23 extern void process_exit_sighand(struct process_control_block *pcb);
24 extern void process_exit_signal(struct process_control_block *pcb);
25 
26 /**
27  * @brief fork当前进程
28  *
29  * @param regs 新的寄存器值
30  * @param clone_flags 克隆标志
31  * @param stack_start 堆栈开始地址
32  * @param stack_size 堆栈大小
33  * @return unsigned long
34  */
do_fork(struct pt_regs * regs,unsigned long clone_flags,unsigned long stack_start,unsigned long stack_size)35 unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned long stack_start,
36                       unsigned long stack_size)
37 {
38     int retval = 0;
39     struct process_control_block *tsk = NULL;
40 
41     // 为新的进程分配栈空间,并将pcb放置在底部
42     tsk = (struct process_control_block *)kzalloc(STACK_SIZE, 0);
43     barrier();
44 
45     if (tsk == NULL)
46     {
47         retval = -ENOMEM;
48         return retval;
49     }
50 
51     barrier();
52     memset(tsk, 0, sizeof(struct process_control_block));
53     io_mfence();
54     // 将当前进程的pcb复制到新的pcb内
55     memcpy(tsk, current_pcb, sizeof(struct process_control_block));
56     tsk->worker_private = NULL;
57     io_mfence();
58 
59     // 初始化进程的循环链表结点
60     list_init(&tsk->list);
61 
62     io_mfence();
63     // 判断是否为内核态调用fork
64     if ((current_pcb->flags & PF_KTHREAD) && stack_start != 0)
65         tsk->flags |= PF_KFORK;
66 
67     if (tsk->flags & PF_KTHREAD)
68     {
69         // 对于内核线程,设置其worker私有信息
70         retval = kthread_set_worker_private(tsk);
71         if (IS_ERR_VALUE(retval))
72             goto copy_flags_failed;
73         tsk->virtual_runtime = 0;
74     }
75     tsk->priority = 2;
76     tsk->preempt_count = 0;
77 
78     // 增加全局的pid并赋值给新进程的pid
79     spin_lock(&process_global_pid_write_lock);
80     tsk->pid = process_global_pid++;
81     barrier();
82     // 加入到进程链表中
83     // todo: 对pcb_list_lock加锁
84     tsk->prev_pcb = &initial_proc_union.pcb;
85     barrier();
86     tsk->next_pcb = initial_proc_union.pcb.next_pcb;
87     barrier();
88     initial_proc_union.pcb.next_pcb = tsk;
89     barrier();
90     tsk->parent_pcb = current_pcb;
91     barrier();
92 
93     spin_unlock(&process_global_pid_write_lock);
94 
95     tsk->cpu_id = proc_current_cpu_id;
96     tsk->state = PROC_UNINTERRUPTIBLE;
97 
98     tsk->parent_pcb = current_pcb;
99     wait_queue_init(&tsk->wait_child_proc_exit, NULL);
100     barrier();
101     list_init(&tsk->list);
102 
103     retval = -ENOMEM;
104 
105     // 拷贝标志位
106     retval = process_copy_flags(clone_flags, tsk);
107     if (retval)
108         goto copy_flags_failed;
109 
110     // 拷贝内存空间分布结构体
111     retval = process_copy_mm(clone_flags, tsk);
112     if (retval)
113         goto copy_mm_failed;
114 
115     // 拷贝文件
116     retval = process_copy_files(clone_flags, tsk);
117     if (retval)
118         goto copy_files_failed;
119 
120     // 拷贝信号处理函数
121     retval = process_copy_sighand(clone_flags, tsk);
122     if (retval)
123         goto copy_sighand_failed;
124 
125     retval = process_copy_signal(clone_flags, tsk);
126     if (retval)
127         goto copy_signal_failed;
128 
129     // 拷贝线程结构体
130     retval = process_copy_thread(clone_flags, tsk, stack_start, stack_size, regs);
131     if (retval)
132         goto copy_thread_failed;
133 
134     // 拷贝成功
135     retval = tsk->pid;
136 
137     tsk->flags &= ~PF_KFORK;
138 
139     // 创建对应procfs文件
140     rs_procfs_register_pid(tsk->pid);
141     // kdebug("Fork ok. pid: %d\n", tsk->pid);
142     // 唤醒进程
143     process_wakeup(tsk);
144 
145     return retval;
146 
147 copy_thread_failed:;
148     // 回收线程
149     process_exit_thread(tsk);
150 copy_files_failed:;
151     // 回收文件
152     process_exit_files(tsk);
153     rs_procfs_unregister_pid(tsk->pid);
154 copy_sighand_failed:;
155     process_exit_sighand(tsk);
156 copy_signal_failed:;
157     process_exit_signal(tsk);
158 copy_mm_failed:;
159     // 回收内存空间分布结构体
160     process_exit_mm(tsk);
161 copy_flags_failed:;
162     kfree(tsk);
163     return retval;
164 }
165 
166 /**
167  * @brief 拷贝当前进程的标志位
168  *
169  * @param clone_flags 克隆标志位
170  * @param pcb 新的进程的pcb
171  * @return uint64_t
172  */
process_copy_flags(uint64_t clone_flags,struct process_control_block * pcb)173 int process_copy_flags(uint64_t clone_flags, struct process_control_block *pcb)
174 {
175     if (clone_flags & CLONE_VM)
176         pcb->flags |= PF_VFORK;
177     return 0;
178 }
179 
180 /**
181  * @brief 拷贝当前进程的内存空间分布结构体信息
182  *
183  * @param clone_flags 克隆标志位
184  * @param pcb 新的进程的pcb
185  * @return uint64_t
186  */
process_copy_mm(uint64_t clone_flags,struct process_control_block * pcb)187 int process_copy_mm(uint64_t clone_flags, struct process_control_block *pcb)
188 {
189     pcb->address_space = NULL;
190     bool clone_vm = (clone_flags & CLONE_VM);
191     return (int)rs_process_copy_mm(clone_vm, pcb);
192 }
193 
194 /**
195  * @brief 重写内核栈中的rbp地址
196  *
197  * @param new_regs 子进程的reg
198  * @param new_pcb 子进程的pcb
199  * @return int
200  */
process_rewrite_rbp(struct pt_regs * new_regs,struct process_control_block * new_pcb)201 static int process_rewrite_rbp(struct pt_regs *new_regs, struct process_control_block *new_pcb)
202 {
203 
204     uint64_t new_top = ((uint64_t)new_pcb) + STACK_SIZE;
205     uint64_t old_top = (uint64_t)(current_pcb) + STACK_SIZE;
206 
207     uint64_t *rbp = &new_regs->rbp;
208     uint64_t *tmp = rbp;
209 
210     // 超出内核栈范围
211     if ((uint64_t)*rbp >= old_top || (uint64_t)*rbp < (old_top - STACK_SIZE))
212         return 0;
213 
214     while (1)
215     {
216         // 计算delta
217         uint64_t delta = old_top - *rbp;
218         // 计算新的rbp值
219         uint64_t newVal = new_top - delta;
220 
221         // 新的值不合法
222         if (unlikely((uint64_t)newVal >= new_top || (uint64_t)newVal < (new_top - STACK_SIZE)))
223             break;
224         // 将新的值写入对应位置
225         *rbp = newVal;
226         // 跳转栈帧
227         rbp = (uint64_t *)*rbp;
228     }
229 
230     // 设置内核态fork返回到enter_syscall_int()函数内的时候,rsp寄存器的值
231     new_regs->rsp = new_top - (old_top - new_regs->rsp);
232     return 0;
233 }
234 
235 /**
236  * @brief 拷贝当前进程的线程结构体
237  *
238  * @param clone_flags 克隆标志位
239  * @param pcb 新的进程的pcb
240  * @return uint64_t
241  */
process_copy_thread(uint64_t clone_flags,struct process_control_block * pcb,uint64_t stack_start,uint64_t stack_size,struct pt_regs * current_regs)242 int process_copy_thread(uint64_t clone_flags, struct process_control_block *pcb, uint64_t stack_start,
243                         uint64_t stack_size, struct pt_regs *current_regs)
244 {
245     // 将线程结构体放置在pcb后方
246     struct thread_struct *thd = (struct thread_struct *)(pcb + 1);
247     memset(thd, 0, sizeof(struct thread_struct));
248     pcb->thread = thd;
249 
250     struct pt_regs *child_regs = NULL;
251     // 拷贝栈空间
252     if (pcb->flags & PF_KFORK) // 内核态下的fork
253     {
254         // 内核态下则拷贝整个内核栈
255         uint32_t size = ((uint64_t)current_pcb) + STACK_SIZE - (uint64_t)(current_regs);
256 
257         child_regs = (struct pt_regs *)(((uint64_t)pcb) + STACK_SIZE - size);
258         memcpy(child_regs, (void *)current_regs, size);
259 
260         barrier();
261         // 然后重写新的栈中,每个栈帧的rbp值
262         process_rewrite_rbp(child_regs, pcb);
263     }
264     else
265     {
266         child_regs = (struct pt_regs *)((uint64_t)pcb + STACK_SIZE - sizeof(struct pt_regs));
267         memcpy(child_regs, current_regs, sizeof(struct pt_regs));
268         barrier();
269         child_regs->rsp = stack_start;
270     }
271 
272     // 设置子进程的返回值为0
273     child_regs->rax = 0;
274     if (pcb->flags & PF_KFORK)
275         thd->rbp = (uint64_t)(child_regs + 1); // 设置新的内核线程开始执行时的rbp(也就是进入ret_from_intr时的rbp)
276     else
277         thd->rbp = (uint64_t)pcb + STACK_SIZE;
278 
279     // 设置新的内核线程开始执行的时候的rsp
280     thd->rsp = (uint64_t)child_regs;
281     thd->fs = current_pcb->thread->fs;
282     thd->gs = current_pcb->thread->gs;
283 
284     // 根据是否为内核线程、是否在内核态fork,设置进程的开始执行的地址
285     if (pcb->flags & PF_KFORK)
286         thd->rip = (uint64_t)ret_from_intr;
287     else if (pcb->flags & PF_KTHREAD && (!(pcb->flags & PF_KFORK)))
288         thd->rip = (uint64_t)kernel_thread_func;
289     else
290         thd->rip = (uint64_t)ret_from_intr;
291 
292     pcb->fp_state = rs_dup_fpstate();
293 
294     return 0;
295 }