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 }