feat: sector rwm ops test code
[lunaix-os.git] / lunaix-os / kernel / proc0.c
1 #include <arch/x86/boot/multiboot.h>
2 #include <lunaix/common.h>
3 #include <lunaix/lunistd.h>
4 #include <lunaix/lxconsole.h>
5 #include <lunaix/mm/cake.h>
6 #include <lunaix/mm/pmm.h>
7 #include <lunaix/mm/valloc.h>
8 #include <lunaix/mm/vmm.h>
9 #include <lunaix/peripheral/ps2kbd.h>
10 #include <lunaix/proc.h>
11 #include <lunaix/spike.h>
12 #include <lunaix/syscall.h>
13 #include <lunaix/syslog.h>
14 #include <stddef.h>
15
16 #include <hal/acpi/acpi.h>
17 #include <hal/ahci/ahci.h>
18 #include <hal/apic.h>
19 #include <hal/ioapic.h>
20 #include <hal/pci.h>
21
22 #include <klibc/string.h>
23
24 LOG_MODULE("PROC0")
25
26 extern void
27 _lxinit_main(); /* lxinit.c */
28
29 void
30 init_platform();
31
32 void
33 lock_reserved_memory();
34
35 void
36 unlock_reserved_memory();
37
38 void
39 __do_reserved_memory(int unlock);
40
41 //#define USE_DEMO
42 #define DEMO_SIGNAL
43
44 extern void
45 _pconsole_main();
46
47 extern void
48 _signal_demo_main();
49
50 extern void
51 _lxinit_main();
52
53 void __USER__
54 __proc0_usr()
55 {
56     pid_t p;
57     if (!fork()) {
58         _pconsole_main();
59     }
60
61     if (!(p = fork())) {
62 #ifndef USE_DEMO
63         _exit(0);
64 #elif defined DEMO_SIGNAL
65         _signal_demo_main();
66 #else
67         _lxinit_main();
68 #endif
69     }
70
71     waitpid(p, 0, 0);
72
73     while (1) {
74         yield();
75     }
76 }
77
78 /**
79  * @brief LunaixOS的零号进程,该进程永远为可执行。
80  *
81  * 这主要是为了保证调度器在没有进程可调度时依然有事可做。
82  *
83  * 同时,该进程也负责fork出我们的init进程。
84  *
85  */
86 void
87 __proc0()
88 {
89     init_platform();
90
91     init_proc_user_space(__current);
92
93     asm volatile("movw %0, %%ax\n"
94                  "movw %%ax, %%es\n"
95                  "movw %%ax, %%ds\n"
96                  "movw %%ax, %%fs\n"
97                  "movw %%ax, %%gs\n"
98                  "pushl %0\n"
99                  "pushl %1\n"
100                  "pushl %2\n"
101                  "pushl %3\n"
102                  "retf" ::"i"(UDATA_SEG),
103                  "i"(USTACK_TOP & ~0xf),
104                  "i"(UCODE_SEG),
105                  "r"(__proc0_usr)
106                  : "eax", "memory");
107 }
108
109 extern uint8_t __kernel_start;            /* link/linker.ld */
110 extern uint8_t __kernel_end;              /* link/linker.ld */
111 extern uint8_t __init_hhk_end;            /* link/linker.ld */
112 extern multiboot_info_t* _k_init_mb_info; /* k_init.c */
113
114 char test_sequence[] = "Once upon a time, in a magical land of Equestria. "
115                        "There were two regal sisters who ruled together "
116                        "and created harmony for all the land.";
117
118 void
119 __test_disk_io()
120 {
121     struct hba_port* port = ahci_get_port(0);
122     char* buffer = valloc_dma(port->device->block_size);
123     strcpy(buffer, test_sequence);
124     kprintf("WRITE: %s\n", buffer);
125     int result;
126
127     // 写入第一扇区
128     result =
129       port->device->ops.write_buffer(port, 1, buffer, port->device->block_size);
130     if (!result) {
131         kprintf(KWARN "fail to write: %x\n", port->device->last_error);
132     }
133
134     memset(buffer, 0, port->device->block_size);
135
136     // 读出我们刚刚写的内容!
137     result =
138       port->device->ops.read_buffer(port, 1, buffer, port->device->block_size);
139     kprintf(KDEBUG "%x, %x\n", port->regs[HBA_RPxIS], port->regs[HBA_RPxTFD]);
140     if (!result) {
141         kprintf(KWARN "fail to read: %x\n", port->device->last_error);
142     } else {
143         kprint_hex(buffer, 256);
144     }
145 }
146
147 void
148 init_platform()
149 {
150     // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射
151     lock_reserved_memory();
152
153     cake_init();
154
155     assert_msg(kalloc_init(), "Fail to initialize heap");
156     valloc_init();
157
158     acpi_init(_k_init_mb_info);
159     apic_init();
160     ioapic_init();
161     timer_init(SYS_TIMER_FREQUENCY_HZ);
162     clock_init();
163     ps2_kbd_init();
164     pci_init();
165     ahci_init();
166     ahci_list_device();
167
168     __test_disk_io();
169
170     cake_stats();
171
172     syscall_install();
173
174     console_start_flushing();
175     console_flush();
176
177     unlock_reserved_memory();
178
179     for (size_t i = 0; i < (uintptr_t)(&__init_hhk_end); i += PG_SIZE) {
180         vmm_del_mapping(PD_REFERENCED, (void*)i);
181         pmm_free_page(KERNEL_PID, (void*)i);
182     }
183 }
184
185 void
186 lock_reserved_memory()
187 {
188     __do_reserved_memory(0);
189 }
190
191 void
192 unlock_reserved_memory()
193 {
194     __do_reserved_memory(1);
195 }
196
197 void
198 __do_reserved_memory(int unlock)
199 {
200     multiboot_memory_map_t* mmaps = _k_init_mb_info->mmap_addr;
201     size_t map_size =
202       _k_init_mb_info->mmap_length / sizeof(multiboot_memory_map_t);
203     // v_mapping mapping;
204     for (unsigned int i = 0; i < map_size; i++) {
205         multiboot_memory_map_t mmap = mmaps[i];
206         uint8_t* pa = PG_ALIGN(mmap.addr_low);
207         if (mmap.type == MULTIBOOT_MEMORY_AVAILABLE || pa <= MEM_4MB) {
208             // Don't fuck up our kernel code or any free area!
209             continue;
210         }
211         size_t pg_num = CEIL(mmap.len_low, PG_SIZE_BITS);
212         size_t j = 0;
213         if (!unlock) {
214             for (; j < pg_num; j++) {
215                 uintptr_t _pa = pa + (j << PG_SIZE_BITS);
216                 if (_pa >= KERNEL_MM_BASE) {
217                     // Don't fuck up our kernel space!
218                     break;
219                 }
220                 vmm_set_mapping(PD_REFERENCED, _pa, _pa, PG_PREM_R, VMAP_NULL);
221                 pmm_mark_page_occupied(
222                   KERNEL_PID, _pa >> PG_SIZE_BITS, PP_FGLOCKED);
223             }
224             // Save the progress for later unmapping.
225             mmaps[i].len_low = j * PG_SIZE;
226         } else {
227             for (; j < pg_num; j++) {
228                 uintptr_t _pa = pa + (j << PG_SIZE_BITS);
229                 vmm_del_mapping(PD_REFERENCED, _pa);
230                 if (mmap.type == MULTIBOOT_MEMORY_ACPI_RECLAIMABLE) {
231                     pmm_mark_page_free(_pa >> PG_SIZE_BITS);
232                 }
233             }
234         }
235     }
236 }