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