Kernel address space isolation and make the kernel heap global to all processes.
[lunaix-os.git] / lunaix-os / kernel / process.c
1 #include <lunaix/process.h>
2 #include <lunaix/mm/vmm.h>
3 #include <lunaix/clock.h>
4 #include <lunaix/syslog.h>
5 #include <lunaix/common.h>
6
7 LOG_MODULE("PROC")
8
9 void* __dup_pagetable(pid_t pid, uintptr_t mount_point) {
10     void* ptd_pp = pmm_alloc_page(pid, PP_FGPERSIST);
11     x86_page_table* ptd = vmm_fmap_page(pid, PG_MOUNT_1, ptd_pp, PG_PREM_RW);
12     x86_page_table* pptd = (x86_page_table*) (mount_point | (0x3FF << 12));
13
14     for (size_t i = 0; i < PG_MAX_ENTRIES - 1; i++)
15     {
16         x86_pte_t ptde = pptd->entry[i];
17         if (!ptde || !(ptde & PG_PRESENT)) {
18             ptd->entry[i] = ptde;
19             continue;
20         }
21         
22         x86_page_table* ppt = (x86_page_table*) (mount_point | (i << 12));
23         void* pt_pp = pmm_alloc_page(pid, PP_FGPERSIST);
24         x86_page_table* pt = vmm_fmap_page(pid, PG_MOUNT_2, pt_pp, PG_PREM_RW);
25
26         for (size_t j = 0; j < PG_MAX_ENTRIES; j++)
27         {
28             uintptr_t va = ((i << 10) | j) << 12;
29             x86_pte_t ppte = ppt->entry[j];
30             if (!ppte || !(ppte & PG_PRESENT)) {
31                 pt->entry[j] = ppte;
32                 continue;
33             }
34
35             // FIXME: 根据 mm_region 将读共享的页(如堆)标为只读,而私有的页(如栈),则复制;而写共享的页则无需更改flags
36             if (va >= KSTACK_START) {
37                 void* ppa = vmm_dup_page(pid, PG_ENTRY_ADDR(ppte));
38                 ppte = ppte & 0xfff | (uintptr_t)ppa;
39             }
40             pt->entry[j] = ppte;
41             // ppte = ppte & ~PG_WRITE;
42             // pt->entry[j] = ppte;
43             // ppt->entry[j] = ppte;
44         }
45
46         ptd->entry[i] = (uintptr_t)pt_pp | PG_PREM_RW;
47     }
48     
49     ptd->entry[PG_MAX_ENTRIES - 1] = NEW_L1_ENTRY(T_SELF_REF_PERM, ptd_pp);
50
51     return ptd_pp;
52 }
53
54 void* dup_pagetable(pid_t pid) {
55     return __dup_pagetable(pid, L2_BASE_VADDR);
56 }
57
58 void dup_proc() {
59     pid_t pid = alloc_pid();
60
61     /* 
62         FIXME: Problematic! It should mount the page table of process then copy it.
63         The current implementation copy the CURRENTLY loaded pgt.
64         However, dup_pagetable is designed to copy current loaded pgt.
65         
66     */
67
68     void* mnt_pt = vmm_mount_pd(__current->page_table);
69
70     void* pg = __dup_pagetable(pid, mnt_pt);
71
72     vmm_unmount_pd();
73
74     struct proc_info pcb = (struct proc_info) {
75         .created = clock_systime(),
76         .pid = pid,
77         .mm = __current->mm,
78         .page_table = pg,
79         .intr_ctx = __current->intr_ctx,
80         .parent_created = __current->created
81     };
82
83     // 正如同fork,返回两次。
84     pcb.intr_ctx.registers.eax = 0;
85     __current->intr_ctx.registers.eax = pid;
86
87     push_process(&pcb);
88     
89 }