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