refactor: add user space printf.
[lunaix-os.git] / lunaix-os / kernel / proc0.c
1 #include <lunaix/block.h>
2 #include <lunaix/common.h>
3 #include <lunaix/fctrl.h>
4 #include <lunaix/fs.h>
5 #include <lunaix/fs/twifs.h>
6 #include <lunaix/lunistd.h>
7 #include <lunaix/lxconsole.h>
8 #include <lunaix/mm/cake.h>
9 #include <lunaix/mm/pmm.h>
10 #include <lunaix/mm/valloc.h>
11 #include <lunaix/mm/vmm.h>
12 #include <lunaix/peripheral/ps2kbd.h>
13 #include <lunaix/proc.h>
14 #include <lunaix/spike.h>
15 #include <lunaix/syscall.h>
16 #include <lunaix/syslog.h>
17 #include <lunaix/types.h>
18
19 #include <hal/acpi/acpi.h>
20 #include <hal/ahci/ahci.h>
21 #include <hal/apic.h>
22 #include <hal/ioapic.h>
23 #include <hal/pci.h>
24 #include <hal/rtc.h>
25
26 #include <arch/x86/boot/multiboot.h>
27
28 #include <klibc/string.h>
29
30 #include <ulibc/stdio.h>
31
32 LOG_MODULE("PROC0")
33
34 extern void
35 _lxinit_main(); /* lxinit.c */
36
37 void
38 init_platform();
39
40 void
41 lock_reserved_memory();
42
43 void
44 unlock_reserved_memory();
45
46 void
47 __do_reserved_memory(int unlock);
48
49 #define USE_DEMO
50 // #define DEMO_SIGNAL
51 // #define DEMO_READDIR
52 // #define DEMO_IOTEST
53 #define DEMO_INPUT_TEST
54
55 extern void
56 _pconsole_main();
57
58 extern void
59 _signal_demo_main();
60
61 extern void
62 _lxinit_main();
63
64 extern void
65 _readdir_main();
66
67 extern void
68 _iotest_main();
69
70 extern void
71 input_test();
72
73 void __USER__
74 __proc0_usr()
75 {
76     // 打开tty设备(控制台),作为标准输入输出。
77     //  tty设备属于序列设备(Sequential Device),该类型设备的上层读写
78     //  无须经过Lunaix的缓存层,而是直接下发到底层驱动。(不受FO_DIRECT的影响)
79     int fdstdout = open("/dev/tty", 0);
80     int fdstdin = dup2(stdout, 1);
81
82     pid_t p;
83     // if (!fork()) {
84     //     _pconsole_main();
85     // }
86
87     if (!(p = fork())) {
88 #ifndef USE_DEMO
89         _exit(0);
90 #elif defined DEMO_SIGNAL
91         _signal_demo_main();
92 #elif defined DEMO_READDIR
93         _readdir_main();
94 #elif defined DEMO_IOTEST
95         _iotest_main();
96 #elif defined DEMO_INPUT_TEST
97         input_test();
98 #else
99         _lxinit_main();
100 #endif
101         printf("==== test end ====\n");
102         _exit(0);
103     }
104
105     waitpid(p, 0, 0);
106
107     while (1) {
108         yield();
109     }
110 }
111
112 /**
113  * @brief LunaixOS的零号进程,该进程永远为可执行。
114  *
115  * 这主要是为了保证调度器在没有进程可调度时依然有事可做。
116  *
117  * 同时,该进程也负责fork出我们的init进程。
118  *
119  */
120 void
121 __proc0()
122 {
123     init_platform();
124
125     init_proc_user_space(__current);
126
127     asm volatile("movw %0, %%ax\n"
128                  "movw %%ax, %%es\n"
129                  "movw %%ax, %%ds\n"
130                  "movw %%ax, %%fs\n"
131                  "movw %%ax, %%gs\n"
132                  "pushl %0\n"
133                  "pushl %1\n"
134                  "pushl %2\n"
135                  "pushl %3\n"
136                  "retf" ::"i"(UDATA_SEG),
137                  "i"(USTACK_TOP & ~0xf),
138                  "i"(UCODE_SEG),
139                  "r"(__proc0_usr)
140                  : "eax", "memory");
141 }
142
143 extern uint8_t __kernel_start;            /* link/linker.ld */
144 extern uint8_t __kernel_end;              /* link/linker.ld */
145 extern uint8_t __init_hhk_end;            /* link/linker.ld */
146 extern multiboot_info_t* _k_init_mb_info; /* k_init.c */
147
148 void
149 init_platform()
150 {
151     // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射
152     lock_reserved_memory();
153
154     rtc_init();
155     acpi_init(_k_init_mb_info);
156     apic_init();
157     ioapic_init();
158     timer_init(SYS_TIMER_FREQUENCY_HZ);
159     clock_init();
160     ps2_kbd_init();
161     pci_init();
162     block_init();
163     ahci_init();
164
165     syscall_install();
166
167     console_start_flushing();
168     console_flush();
169
170     unlock_reserved_memory();
171
172     for (size_t i = 0; i < (uintptr_t)(&__init_hhk_end); i += PG_SIZE) {
173         vmm_del_mapping(PD_REFERENCED, (void*)i);
174         pmm_free_page(KERNEL_PID, (void*)i);
175     }
176 }
177
178 void
179 lock_reserved_memory()
180 {
181     __do_reserved_memory(0);
182 }
183
184 void
185 unlock_reserved_memory()
186 {
187     __do_reserved_memory(1);
188 }
189
190 void
191 __do_reserved_memory(int unlock)
192 {
193     multiboot_memory_map_t* mmaps = _k_init_mb_info->mmap_addr;
194     size_t map_size =
195       _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t);
196     // v_mapping mapping;
197     for (unsigned int i = 0; i < map_size; i++) {
198         multiboot_memory_map_t mmap = mmaps[i];
199         uint8_t* pa = PG_ALIGN(mmap.addr_low);
200         if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE || pa <= MEM_4MB) {
201             // Don't fuck up our kernel code or any free area!
202             continue;
203         }
204         size_t pg_num = CEIL(mmap.len_low, PG_SIZE_BITS);
205         size_t j = 0;
206         if (!unlock) {
207             for (; j < pg_num; j++) {
208                 uintptr_t _pa = pa + (j << PG_SIZE_BITS);
209                 if (_pa >= KERNEL_MM_BASE) {
210                     // Don't fuck up our kernel space!
211                     break;
212                 }
213                 vmm_set_mapping(PD_REFERENCED, _pa, _pa, PG_PREM_R, VMAP_NULL);
214                 pmm_mark_page_occupied(
215                   KERNEL_PID, _pa >> PG_SIZE_BITS, PP_FGLOCKED);
216             }
217             // Save the progress for later unmapping.
218             mmaps[i].len_low = j * PG_SIZE;
219         } else {
220             for (; j < pg_num; j++) {
221                 uintptr_t _pa = pa + (j << PG_SIZE_BITS);
222                 vmm_del_mapping(PD_REFERENCED, _pa);
223                 if (mmap.type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE) {
224                     pmm_mark_page_free(_pa >> PG_SIZE_BITS);
225                 }
226             }
227         }
228     }
229 }