001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019 #include <sos/errno.h>
020
021
022 #include <bootstrap/multiboot.h>
023 #include <hwcore/idt.h>
024 #include <hwcore/gdt.h>
025 #include <hwcore/irq.h>
026 #include <hwcore/exception.h>
027 #include <hwcore/i8254.h>
028 #include <sos/list.h>
029 #include <sos/physmem.h>
030 #include <hwcore/paging.h>
031 #include <hwcore/mm_context.h>
032 #include <hwcore/swintr.h>
033 #include <sos/kmem_vmm.h>
034 #include <sos/kmalloc.h>
035 #include <sos/time.h>
036 #include <sos/thread.h>
037 #include <sos/process.h>
038 #include <sos/umem_vmm.h>
039 #include <sos/klibc.h>
040 #include <sos/assert.h>
041 #include <drivers/x86_videomem.h>
042 #include <drivers/bochs.h>
043 #include <sos/calcload.h>
044 #include <sos/umem_vmm.h>
045 #include <sos/binfmt_elf32.h>
046 #include <drivers/zero.h>
047 #include <sos/fs.h>
048 #include <drivers/fs_virtfs.h>
049
050
051
052 void display_bits(unsigned char row, unsigned char col,
053 unsigned char attribute,
054 sos_ui32_t integer)
055 {
056 int i;
057
058 for (i = 31 ; i >= 0 ; i--)
059 {
060
061 int bit_i = (integer & (1 << i));
062
063 unsigned char ascii_code = bit_i?219:177;
064 sos_x86_videomem_putchar(row, col++,
065 attribute,
066 ascii_code);
067 }
068 }
069
070
071 static void clk_it(int intid)
072 {
073 static sos_ui32_t clock_count = 0;
074
075 display_bits(0, 48,
076 SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE,
077 clock_count);
078 clock_count++;
079
080
081 sos_time_do_tick();
082
083
084 sos_sched_do_timer_tick();
085 }
086
087
088
089
090
091
092
093
094 static void pgflt_ex(int intid, struct sos_cpu_state *ctxt)
095 {
096 static sos_ui32_t demand_paging_count = 0;
097 struct sos_thread * cur_thr = sos_thread_get_current();
098 sos_vaddr_t faulting_vaddr = sos_cpu_context_get_EX_faulting_vaddr(ctxt);
099 sos_paddr_t ppage_paddr;
100
101 if (sos_cpu_context_is_in_user_mode(ctxt)
102 || (cur_thr->fixup_uaccess.return_vaddr))
103 {
104 __label__ unforce_address_space;
105 sos_bool_t need_to_setup_mmu;
106 sos_ui32_t errcode = sos_cpu_context_get_EX_info(ctxt);
107
108
109
110 need_to_setup_mmu = (cur_thr->squatted_mm_context
111 != sos_process_get_mm_context(cur_thr->process));
112 if (need_to_setup_mmu)
113 sos_thread_prepare_user_space_access(NULL, 0);
114
115 if (SOS_OK ==
116 sos_umem_vmm_try_resolve_page_fault(faulting_vaddr,
117 errcode & (1 << 1),
118 TRUE))
119 goto unforce_address_space;
120
121
122
123 if (! sos_cpu_context_is_in_user_mode(ctxt))
124 {
125 cur_thr->fixup_uaccess.faulted_uaddr = faulting_vaddr;
126 sos_cpu_context_set_EX_return_address(ctxt,
127 cur_thr->fixup_uaccess.return_vaddr);
128 goto unforce_address_space;
129 }
130
131 if (need_to_setup_mmu)
132 sos_thread_end_user_space_access();
133
134 sos_bochs_printf("Unresolved USER page Fault at instruction 0x%x on access to address 0x%x (info=%x)!\n",
135 sos_cpu_context_get_PC(ctxt),
136 (unsigned)faulting_vaddr,
137 (unsigned)sos_cpu_context_get_EX_info(ctxt));
138 sos_bochs_printf("Terminating User thread\n");
139 sos_thread_exit();
140
141 unforce_address_space:
142 if (need_to_setup_mmu)
143 sos_thread_end_user_space_access();
144 return;
145 }
146
147
148 if (! sos_kmem_vmm_is_valid_vaddr(faulting_vaddr))
149 {
150
151
152 sos_display_fatal_error("Unresolved page Fault at instruction 0x%x on access to address 0x%x (info=%x)!",
153 sos_cpu_context_get_PC(ctxt),
154 (unsigned)faulting_vaddr,
155 (unsigned)sos_cpu_context_get_EX_info(ctxt));
156 SOS_ASSERT_FATAL(! "Got page fault (note: demand paging is disabled)");
157 }
158
159
160
161
162
163
164
165 demand_paging_count ++;
166 display_bits(0, 0,
167 SOS_X86_VIDEO_FG_LTRED | SOS_X86_VIDEO_BG_BLUE,
168 demand_paging_count);
169
170
171 ppage_paddr = sos_physmem_ref_physpage_new(FALSE);
172 if (! ppage_paddr)
173 SOS_ASSERT_FATAL(! "TODO: implement swap. (Out of mem in demand paging because no swap for kernel yet !)");
174 SOS_ASSERT_FATAL(SOS_OK == sos_paging_map(ppage_paddr,
175 SOS_PAGE_ALIGN_INF(faulting_vaddr),
176 FALSE,
177 SOS_VM_MAP_PROT_READ
178 | SOS_VM_MAP_PROT_WRITE
179 | SOS_VM_MAP_ATOMIC));
180 sos_physmem_unref_physpage(ppage_paddr);
181
182
183 }
184
185
186
187
188
189
190
191 static void idle_thread()
192 {
193 sos_ui32_t idle_twiddle = 0;
194
195 while (1)
196 {
197
198
199 asm("hlt\n");
200
201 idle_twiddle ++;
202 display_bits(0, 0, SOS_X86_VIDEO_FG_GREEN | SOS_X86_VIDEO_BG_BLUE,
203 idle_twiddle);
204
205
206 sos_thread_yield();
207 }
208 }
209
210
211
212
213
214 static void stat_thread()
215 {
216 while (1)
217 {
218 sos_ui32_t flags;
219 sos_ui32_t load1, load5, load15;
220 char str1[11], str5[11], str15[11];
221 struct sos_time t;
222 t.sec = 1;
223 t.nanosec = 0;
224
225 sos_thread_sleep(& t);
226
227 sos_disable_IRQs(flags);
228
229
230 sos_load_get_sload(&load1, &load5, &load15);
231 sos_load_to_string(str1, load1);
232 sos_load_to_string(str5, load5);
233 sos_load_to_string(str15, load15);
234 sos_x86_videomem_printf(16, 34,
235 SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
236 "Kernel (- Idle): %s %s %s ",
237 str1, str5, str15);
238
239 sos_load_get_uload(&load1, &load5, &load15);
240 sos_load_to_string(str1, load1);
241 sos_load_to_string(str5, load5);
242 sos_load_to_string(str15, load15);
243 sos_x86_videomem_printf(17, 34,
244 SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
245 "User: %s %s %s ",
246 str1, str5, str15);
247
248 sos_load_get_uratio(&load1, &load5, &load15);
249 sos_load_to_string(str1, load1);
250 sos_load_to_string(str5, load5);
251 sos_load_to_string(str15, load15);
252 sos_x86_videomem_printf(18, 34,
253 SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
254 "User CPU %%: %s %s %s ",
255 str1, str5, str15);
256
257
258 sos_load_get_sratio(&load1, &load5, &load15);
259 sos_load_to_string(str1, load1);
260 sos_load_to_string(str5, load5);
261 sos_load_to_string(str15, load15);
262 sos_x86_videomem_printf(19, 34,
263 SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
264 "Kernel CPU %% (+ Idle): %s %s %s ",
265 str1, str5, str15);
266 sos_restore_IRQs(flags);
267 }
268 }
269
270
271
272
273
274 static sos_ret_t
275 start_init(struct sos_fs_manager_instance * rootfs)
276 {
277 sos_ret_t retval;
278 struct sos_umem_vmm_as *as_init;
279 struct sos_process *proc_init;
280 struct sos_thread *new_thr;
281 sos_uaddr_t ustack, start_uaddr;
282 struct sos_fs_opened_file * init_root, * init_cwd, * unused_of;
283
284
285 proc_init = sos_process_create("init", FALSE);
286 if (! proc_init)
287 return -SOS_ENOMEM;
288 as_init = sos_process_get_address_space(proc_init);
289
290
291
292
293
294
295
296 retval = sos_fs_new_opened_file(proc_init, rootfs->root,
297 SOS_FS_OPEN_READ | SOS_FS_OPEN_WRITE,
298 & init_root);
299 if (SOS_OK != retval)
300 {
301 sos_process_unref(proc_init);
302 return -SOS_ENOENT;
303 }
304
305
306
307 retval = sos_fs_duplicate_opened_file(init_root, proc_init,
308 & init_cwd);
309 if (SOS_OK != retval)
310 {
311 sos_fs_close(init_root);
312 sos_process_unref(proc_init);
313 return -SOS_ENOENT;
314 }
315
316
317 if ( ( SOS_OK != sos_process_chroot(proc_init, init_root, & unused_of) )
318 || ( SOS_OK != sos_process_chdir(proc_init, init_cwd, & unused_of) ) )
319 {
320 sos_fs_close(init_root);
321 sos_fs_close(init_cwd);
322 sos_process_chroot(proc_init, NULL, & unused_of);
323 sos_process_chdir(proc_init, NULL, & unused_of);
324 sos_process_unref(proc_init);
325 return -SOS_ENOENT;
326 }
327
328
329 start_uaddr = sos_binfmt_elf32_map(as_init, "init");
330 if (0 == start_uaddr)
331 {
332 sos_process_unref(proc_init);
333 return -SOS_ENOENT;
334 }
335
336
337 ustack = (SOS_PAGING_TOP_USER_ADDRESS - SOS_DEFAULT_USER_STACK_SIZE) + 1;
338 retval = sos_dev_zero_map(as_init, &ustack, SOS_DEFAULT_USER_STACK_SIZE,
339 SOS_VM_MAP_PROT_READ | SOS_VM_MAP_PROT_WRITE,
340 0);
341 if (SOS_OK != retval)
342 {
343 sos_process_unref(proc_init);
344 return -SOS_ENOMEM;
345 }
346
347
348 new_thr = sos_create_user_thread(NULL,
349 proc_init,
350 start_uaddr,
351 0, 0,
352 ustack + SOS_DEFAULT_USER_STACK_SIZE - 4,
353 SOS_SCHED_PRIO_TS_LOWEST);
354 if (! new_thr)
355 {
356 sos_process_unref(proc_init);
357 return -SOS_ENOMEM;
358 }
359
360 sos_process_unref(proc_init);
361 return SOS_OK;
362 }
363
364
365
366
367
368 void sos_main(unsigned long magic, unsigned long arg)
369 {
370 unsigned i;
371 sos_paddr_t sos_kernel_core_base_paddr, sos_kernel_core_top_paddr;
372 struct sos_time tick_resolution;
373 struct sos_fs_manager_instance * rootfs;
374
375
376 unsigned long int upper_mem = 0;
377
378
379 sos_bochs_setup();
380
381 sos_x86_videomem_setup();
382 sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE);
383
384
385 if (magic == MULTIBOOT_BOOTLOADER_MAGIC)
386 {
387
388
389
390 multiboot_info_t *mbi = (multiboot_info_t *) arg;
391
392
393
394
395
396 upper_mem = mbi->mem_upper;
397 sos_x86_videomem_printf(1, 0,
398 SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
399 "Welcome From GRUB to %s%c RAM is %dMB (upper mem = 0x%x kB)",
400 "SOS article 8", ',',
401 (unsigned)(upper_mem >> 10) + 1,
402 (unsigned)upper_mem);
403 }
404 else if (magic == 0x42244224)
405 {
406
407 upper_mem = arg;
408 sos_x86_videomem_printf(1, 0,
409 SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
410 "Welcome to %s%c RAM is %dMB (upper mem = 0x%x kB)",
411 "SOS article 8", ',',
412 (unsigned)(upper_mem >> 10) + 1,
413 (unsigned)upper_mem);
414 }
415 else
416
417 sos_x86_videomem_printf(1, 0,
418 SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
419 "Welcome to SOS article 8");
420
421 sos_bochs_putstring("Message in a bochs: This is SOS article 8.\n");
422
423
424 sos_gdt_subsystem_setup();
425 sos_idt_subsystem_setup();
426
427
428 sos_exception_subsystem_setup();
429 sos_irq_subsystem_setup();
430
431
432 sos_i8254_set_frequency(100);
433
434
435
436 tick_resolution = (struct sos_time) { .sec=0, .nanosec=10000000UL };
437 sos_time_subsysem_setup(& tick_resolution);
438
439
440 if (upper_mem == 0)
441 {
442 sos_x86_videomem_putstring(20, 0,
443 SOS_X86_VIDEO_FG_LTRED
444 | SOS_X86_VIDEO_BG_BLUE
445 | SOS_X86_VIDEO_FG_BLINKING,
446 "I don't know RAM size ! Load me with Grub...");
447
448 for (;;)
449 continue;
450 }
451
452
453
454
455
456
457 sos_irq_set_routine(SOS_IRQ_TIMER,
458 clk_it);
459
460
461
462
463
464 SOS_ASSERT_FATAL(SOS_OK
465 == sos_physmem_subsystem_setup((upper_mem<<10) + (1<<20),
466 &sos_kernel_core_base_paddr,
467 &sos_kernel_core_top_paddr));
468
469
470
471
472
473
474
475 SOS_ASSERT_FATAL(SOS_OK ==
476 sos_paging_subsystem_setup(sos_kernel_core_base_paddr,
477 sos_kernel_core_top_paddr));
478
479
480 sos_exception_set_routine(SOS_EXCEPT_PAGE_FAULT,
481 pgflt_ex);
482
483
484
485
486
487 if (sos_kmem_vmm_subsystem_setup(sos_kernel_core_base_paddr,
488 sos_kernel_core_top_paddr,
489 bootstrap_stack_bottom,
490 bootstrap_stack_bottom
491 + bootstrap_stack_size))
492 sos_bochs_printf("Could not setup the Kernel virtual space allocator\n");
493
494 if (sos_kmalloc_subsystem_setup())
495 sos_bochs_printf("Could not setup the Kmalloc subsystem\n");
496
497
498
499
500 sos_mm_context_subsystem_setup();
501
502
503
504
505 sos_cpu_context_subsystem_setup();
506
507
508
509
510 sos_swintr_subsystem_setup();
511
512
513
514
515
516
517
518 sos_thread_subsystem_setup(bootstrap_stack_bottom,
519 bootstrap_stack_size);
520
521
522 sos_sched_subsystem_setup();
523
524
525 SOS_ASSERT_FATAL(sos_create_kernel_thread("idle", idle_thread, NULL,
526 SOS_SCHED_PRIO_TS_LOWEST) != NULL);
527
528
529 sos_load_subsystem_setup();
530
531
532 SOS_ASSERT_FATAL(sos_create_kernel_thread("stat_thread", stat_thread,
533 NULL,
534 SOS_SCHED_PRIO_TS_LOWEST) != NULL);
535
536
537
538
539
540 sos_umem_vmm_subsystem_setup();
541 sos_dev_zero_subsystem_setup();
542
543
544
545
546 sos_process_subsystem_setup();
547
548
549
550
551 asm volatile ("sti\n");
552
553
554 SOS_ASSERT_FATAL(SOS_OK == sos_fs_virtfs_subsystem_setup());
555 SOS_ASSERT_FATAL(SOS_OK == sos_fs_subsystem_setup(NULL,
556 "virtfs",
557 NULL,
558 & rootfs));
559
560
561
562
563 start_init(rootfs);
564
565
566
567
568
569
570
571
572
573
574
575
576 sos_bochs_printf("Bye from primary thread !\n");
577 sos_thread_exit();
578 SOS_FATAL_ERROR("No trespassing !");
579 }