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