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