1 /**
2  * @file process.h
3  * @author longjin
4  * @brief 进程
5  * @date 2022-01-29
6  *
7  * @copyright Copyright (c) 2022
8  *
9  */
10 
11 #pragma once
12 #include "ptrace.h"
13 #include <common/cpu.h>
14 #include <common/errno.h>
15 #include <common/glib.h>
16 #include <common/wait_queue.h>
17 #include <filesystem/vfs/VFS.h>
18 #include <mm/mm-types.h>
19 #include <syscall/syscall.h>
20 
21 #include <asm/current.h>
22 
23 #include "proc-types.h"
24 
25 extern void process_exit_thread(struct process_control_block *pcb);
26 extern int process_exit_files(struct process_control_block *pcb);
27 
28 /**
29  * @brief 任务状态段结构体
30  *
31  */
32 
33 // 设置初始进程的tss
34 #define INITIAL_TSS                                                                                                   \
35     {                                                                                                                 \
36         .reserved0 = 0, .rsp0 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)),                             \
37         .rsp1 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)),                                             \
38         .rsp2 = (ul)(initial_proc_union.stack + STACK_SIZE / sizeof(ul)), .reserved1 = 0, .ist1 = 0xffff800000007c00, \
39         .ist2 = 0xffff800000007c00, .ist3 = 0xffff800000007c00, .ist4 = 0xffff800000007c00,                           \
40         .ist5 = 0xffff800000007c00, .ist6 = 0xffff800000007c00, .ist7 = 0xffff800000007c00, .reserved2 = 0,           \
41         .reserved3 = 0, .io_map_base_addr = 0                                                                         \
42     }
43 
44 #define GET_CURRENT_PCB    \
45     "movq %rsp, %rbx \n\t" \
46     "andq $-32768, %rbx\n\t"
47 
48 /**
49  * @brief 切换进程上下文
50  * 先把rbp和rax保存到栈中,然后将rsp和rip保存到prev的thread结构体中
51  * 然后调用__switch_to切换栈,配置其他信息,最后恢复下一个进程的rax rbp。
52  */
53 
54 #define switch_to(prev, next)                                                                       \
55     do                                                                                              \
56     {                                                                                               \
57         __asm__ __volatile__("pushq	%%rbp	\n\t"                                                     \
58                              "pushq	%%rax	\n\t"                                                     \
59                              "movq	%%rsp,	%0	\n\t"                                                  \
60                              "movq	%2,	%%rsp	\n\t"                                                  \
61                              "leaq	2f(%%rip),	%%rax	\n\t"                                           \
62                              "movq	%%rax,	%1	\n\t"                                                  \
63                              "pushq	%3		\n\t"                                                       \
64                              "jmp	__switch_to	\n\t"                                                 \
65                              "2:	\n\t"                                                              \
66                              "popq	%%rax	\n\t"                                                      \
67                              "popq	%%rbp	\n\t"                                                      \
68                              : "=m"(prev->thread->rsp), "=m"(prev->thread->rip)                     \
69                              : "m"(next->thread->rsp), "m"(next->thread->rip), "D"(prev), "S"(next) \
70                              : "memory", "rax");                                                    \
71     } while (0)
72 
73 /**
74  * @brief 初始化系统的第一个进程
75  *
76  */
77 void process_init();
78 
79 /**
80  * @brief fork当前进程
81  *
82  * @param regs 新的寄存器值
83  * @param clone_flags 克隆标志
84  * @param stack_start 堆栈开始地址
85  * @param stack_size 堆栈大小
86  * @return unsigned long
87  */
88 unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned long stack_start,
89                       unsigned long stack_size);
90 
91 /**
92  * @brief 根据pid获取进程的pcb。存在对应的pcb时,返回对应的pcb的指针,否则返回NULL
93  * 当进程管理模块拥有pcblist_lock之后,调用本函数之前,应当对其加锁
94  * @param pid
95  * @return struct process_control_block*
96  */
97 struct process_control_block *process_find_pcb_by_pid(pid_t pid);
98 
99 /**
100  * @brief 将进程加入到调度器的就绪队列中
101  *
102  * @param pcb 进程的pcb
103  *
104  * @return 如果进程被成功唤醒,则返回1,如果进程正在运行,则返回0.如果pcb为NULL,则返回-EINVAL
105  */
106 int process_wakeup(struct process_control_block *pcb);
107 
108 /**
109  * @brief 将进程加入到调度器的就绪队列中,并标志当前进程需要被调度
110  *
111  * @param pcb 进程的pcb
112  */
113 int process_wakeup_immediately(struct process_control_block *pcb);
114 
115 /**
116  * @brief 释放进程的页表
117  *
118  * @param pcb 要被释放页表的进程
119  * @return uint64_t
120  */
121 uint64_t process_exit_mm(struct process_control_block *pcb);
122 
123 /**
124  * @brief 进程退出时执行的函数
125  *
126  * @param code 返回码
127  * @return ul
128  */
129 ul process_do_exit(ul code);
130 
131 /**
132  * @brief 当子进程退出后向父进程发送通知
133  *
134  */
135 void process_exit_notify();
136 
137 /**
138  * @brief 初始化内核进程
139  *
140  * @param fn 目标程序的地址
141  * @param arg 向目标程序传入的参数
142  * @param flags
143  * @return int
144  */
145 
146 pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
147 
148 int process_fd_alloc(struct vfs_file_t *file);
149 
150 int process_release_pcb(struct process_control_block *pcb);
151 
152 /**
153  * @brief 切换页表
154  * @param prev 前一个进程的pcb
155  * @param next 下一个进程的pcb
156  *
157  */
158 #define process_switch_mm(next_pcb)                                    \
159     do                                                                 \
160     {                                                                  \
161         asm volatile("movq %0, %%cr3	\n\t" ::"r"(next_pcb->mm->pgd) \
162                      : "memory");                                      \
163     } while (0)
164 // flush_tlb();
165 
166 // 获取当前cpu id
167 #define proc_current_cpu_id (current_pcb->cpu_id)
168 
169 extern unsigned long head_stack_start; // 导出内核层栈基地址(定义在head.S
170 extern ul _stack_start;
171 extern void ret_from_intr(void); // 导出从中断返回的函数(定义在entry.S
172 
173 extern struct tss_struct initial_tss[MAX_CPU_NUM];
174 extern struct mm_struct initial_mm;
175 extern struct thread_struct initial_thread;
176 extern union proc_union initial_proc_union;
177 extern struct process_control_block *initial_proc[MAX_CPU_NUM];
178 
179 /**
180  * @brief 给pcb设置名字
181  *
182  * @param pcb 需要设置名字的pcb
183  * @param pcb_name 保存名字的char数组
184  */
185 void process_set_pcb_name(struct process_control_block *pcb, const char *pcb_name);
186 
187 /**
188  * @brief 判断进程是否已经停止
189  *
190  * hint: 本函数在rust中实现,请参考rust版本的注释
191  *
192  * @param pcb 目标pcb
193  * @return true
194  * @return false
195  */
196 extern bool process_is_stopped(struct process_control_block *pcb);
197 
198 /**
199  * @brief 尝试唤醒指定的进程。
200  * 本函数的行为:If (@_state & @pcb->state) @pcb->state = TASK_RUNNING.
201  *
202  * hint: 本函数在rust中实现,请参考rust版本的注释
203  */
204 extern int process_try_to_wake_up(struct process_control_block *_pcb, uint64_t _state, int32_t _wake_flags);
205 
206 /** @brief 当进程,满足 (@state & @pcb->state)时,唤醒进程,并设置: @pcb->state = TASK_RUNNING.
207  *
208  * hint: 本函数在rust中实现,请参考rust版本的注释
209  * @return true 唤醒成功
210  * @return false 唤醒失败
211  */
212 extern int process_wake_up_state(struct process_control_block *pcb, uint64_t state);
213 void __switch_to(struct process_control_block *prev, struct process_control_block *next);
214