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