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 }