Diff markup
001 001
002 <<
003 002
004 003
005 004
006 005
007 006
008 007
009 008
010 009
011 010
012 011
013 012
014 013
015 014
016 015
017 016
018 017
019 018
020 019
021 #include <bootstrap/multiboot.h> 020 #include <bootstrap/multiboot.h>
022 #include <hwcore/idt.h> 021 #include <hwcore/idt.h>
023 #include <hwcore/gdt.h> 022 #include <hwcore/gdt.h>
024 #include <hwcore/irq.h> 023 #include <hwcore/irq.h>
025 #include <hwcore/exception.h> 024 #include <hwcore/exception.h>
026 #include <hwcore/i8254.h> 025 #include <hwcore/i8254.h>
027 #include <sos/list.h> 026 #include <sos/list.h>
028 #include <sos/physmem.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>
029 #include <sos/klibc.h> 033 #include <sos/klibc.h>
030 #include <sos/assert.h> 034 #include <sos/assert.h>
031 #include <drivers/x86_videomem.h> 035 #include <drivers/x86_videomem.h>
032 #include <drivers/bochs.h> 036 #include <drivers/bochs.h>
033 037
034 038
035 039
036 040
037 static void display_bits(unsigned char row, un !! 041 void display_bits(unsigned char row, unsigned char col,
038 unsigned char attribu !! 042 unsigned char attribute,
039 sos_ui32_t integer) !! 043 sos_ui32_t integer)
040 { 044 {
041 int i; 045 int i;
042 046
043 for (i = 31 ; i >= 0 ; i--) 047 for (i = 31 ; i >= 0 ; i--)
044 { 048 {
045 049
046 int bit_i = (integer & (1 << i)); 050 int bit_i = (integer & (1 << i));
047 051
048 unsigned char ascii_code = bit_i?219:177 052 unsigned char ascii_code = bit_i?219:177;
049 sos_x86_videomem_putchar(row, col++, 053 sos_x86_videomem_putchar(row, col++,
050 attribute, 054 attribute,
051 ascii_code); 055 ascii_code);
052 } 056 }
053 } 057 }
054 058
055 059
056 060
057 static void clk_it(int intid) 061 static void clk_it(int intid)
058 { 062 {
059 static sos_ui32_t clock_count = 0; 063 static sos_ui32_t clock_count = 0;
060 064
061 display_bits(0, 48, 065 display_bits(0, 48,
062 SOS_X86_VIDEO_FG_LTGREEN | SOS_ 066 SOS_X86_VIDEO_FG_LTGREEN | SOS_X86_VIDEO_BG_BLUE,
063 clock_count); 067 clock_count);
064 clock_count++; 068 clock_count++;
065 069
>> 070
>> 071 sos_time_do_tick();
066 } 072 }
067 073
068 #define MY_PPAGE_NUM_INT 511 !! 074
069 struct my_ppage !! 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)
070 { 085 {
071 sos_ui32_t before[MY_PPAGE_NUM_INT]; !! 086 static void backtracer(sos_vaddr_t PC,
072 struct my_ppage *prev, *next; !! 087 sos_vaddr_t params,
073 sos_ui32_t after[MY_PPAGE_NUM_INT]; !! 088 sos_ui32_t depth,
074 }; !! 089 void *custom_arg)
075 <<
076 static void test_physmem() <<
077 { <<
078 <<
079 struct my_ppage *ppage_list, *my_ppage; <<
080 sos_count_t num_alloc_ppages = 0, num_free_p <<
081 <<
082 ppage_list = NULL; <<
083 while ((my_ppage = (struct my_ppage*)sos_phy <<
084 != NULL) <<
085 { 090 {
086 int i; !! 091 sos_ui32_t invalid = 0xffffffff, *arg1, *arg2, *arg3, *arg4;
087 num_alloc_ppages++; !! 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);
088 130
089 !! 131 }
090 sos_x86_videomem_printf(2, 0, !! 132
091 SOS_X86_VIDEO_FG !! 133 sos_backtrace(cpu_state, 15, stack_bottom, stack_size, backtracer, NULL);
092 | SOS_X86_VIDEO_ !! 134 }
093 "Could allocate !! 135
094 num_alloc_ppages !! 136
095 !! 137
096 !! 138 static void pgflt_ex(int intid, const struct sos_cpu_state *ctxt)
097 for (i = 0 ; i < MY_PPAGE_NUM_INT ; i++) !! 139 {
098 my_ppage->before[i] = my_ppage->after[ !! 140 static sos_ui32_t demand_paging_count = 0;
099 !! 141 sos_vaddr_t faulting_vaddr = sos_cpu_context_get_EX_faulting_vaddr(ctxt);
100 !! 142 sos_paddr_t ppage_paddr;
101 list_add_tail(ppage_list, my_ppage); !! 143
102 } !! 144
103 !! 145 if (! sos_kmem_vmm_is_valid_vaddr(faulting_vaddr))
104 !! 146 {
105 while ((my_ppage = list_pop_head(ppage_list) !! 147
106 { !! 148
107 !! 149 dump_backtrace(ctxt,
108 !! 150 bootstrap_stack_bottom,
109 int i; !! 151 bootstrap_stack_size,
110 for (i = 0 ; i < MY_PPAGE_NUM_INT ; i++) !! 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)
111 { 228 {
112 !! 229 struct sos_time t = (struct sos_time){ .sec=0, .nanosec=50000000 };
113 if ((my_ppage->before[i] != (sos_ui !! 230 sos_bochs_printf("[37msleep1(%c)[m\n", thr_arg->character);
114 || (my_ppage->after[i] != (sos_ !! 231 sos_x86_videomem_putchar(thr_arg->row, thr_arg->col, 0x1e, 's');
115 { !! 232 SOS_ASSERT_FATAL(SOS_OK == sos_thread_sleep(& t));
116 !! 233 SOS_ASSERT_FATAL(sos_time_is_zero(& t));
117 sos_x86_videomem_putstring(20, 0 !! 234 sos_x86_videomem_putchar(thr_arg->row, thr_arg->col, 0x1e, 'R');
118 SOS_X <<
119 | S <<
120 "Page <<
121 return; <<
122 } <<
123 } 235 }
124 236
125 !! 237
126 if (sos_physmem_unref_physpage((sos_padd !! 238 else if ((random() % 300) == 0)
127 { 239 {
128 !! 240 struct sos_time t = (struct sos_time){ .sec=0, .nanosec=300000000 };
129 sos_x86_videomem_putstring(20, 0, !! 241 sos_bochs_printf("[37msleep2(%c)[m\n", thr_arg->character);
130 SOS_X86_V !! 242 sos_x86_videomem_putchar(thr_arg->row, thr_arg->col, 0x1e, 'S');
131 | SOS_X !! 243 SOS_ASSERT_FATAL(SOS_OK == sos_thread_sleep(& t));
132 "Cannot r !! 244 SOS_ASSERT_FATAL(sos_time_is_zero(& t));
133 return; !! 245 sos_x86_videomem_putchar(thr_arg->row, thr_arg->col, 0x1e, 'R');
134 } 246 }
135 247
136 !! 248
137 num_free_ppages ++; <<
138 sos_x86_videomem_printf(2, 0, <<
139 SOS_X86_VIDEO_FG <<
140 | SOS_X86_VIDEO_ <<
141 "Could free %d p <<
142 num_free_ppages) <<
143 } 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);
144 270
145 !! 271 arg_e = (struct thr_arg) { .character='e', .col=0, .row=19, .color=0x14 };
146 sos_x86_videomem_printf(2, 0, !! 272 sos_create_kernel_thread("YO[e]", demo_thread, (void*)&arg_e);
147 SOS_X86_VIDEO_FG_LTG <<
148 | SOS_X86_VIDEO_BG_B <<
149 "Could allocate %d b <<
150 num_alloc_ppages << <<
151 num_free_ppages << S <<
152 273
153 SOS_ASSERT_FATAL(num_alloc_ppages == num_fre !! 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);
154 } 281 }
155 282
156 283
157 !! 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
158 void sos_main(unsigned long magic, unsigned lo 311 void sos_main(unsigned long magic, unsigned long addr)
159 { 312 {
160 unsigned i; 313 unsigned i;
161 sos_paddr_t sos_kernel_core_base_paddr, sos_ 314 sos_paddr_t sos_kernel_core_base_paddr, sos_kernel_core_top_paddr;
>> 315 struct sos_time tick_resolution;
162 316
163 317
164 318
165 319
166 multiboot_info_t *mbi; 320 multiboot_info_t *mbi;
167 mbi = (multiboot_info_t *) addr; 321 mbi = (multiboot_info_t *) addr;
168 322
169 323
170 sos_bochs_setup(); 324 sos_bochs_setup();
171 325
172 sos_x86_videomem_setup(); 326 sos_x86_videomem_setup();
173 sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE); 327 sos_x86_videomem_cls(SOS_X86_VIDEO_BG_BLUE);
174 328
175 329
176 if (magic == MULTIBOOT_BOOTLOADER_MAGIC) 330 if (magic == MULTIBOOT_BOOTLOADER_MAGIC)
177 331
178 sos_x86_videomem_printf(1, 0, 332 sos_x86_videomem_printf(1, 0,
179 SOS_X86_VIDEO_FG_Y 333 SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
180 "Welcome From GRUB 334 "Welcome From GRUB to %s%c RAM is %dMB (upper mem = 0x%x kB)",
181 "SOS", ',', !! 335 "SOS article 6.5", ',',
182 (unsigned)(mbi->me 336 (unsigned)(mbi->mem_upper >> 10) + 1,
183 (unsigned)mbi->mem 337 (unsigned)mbi->mem_upper);
184 else 338 else
185 339
186 sos_x86_videomem_printf(1, 0, 340 sos_x86_videomem_printf(1, 0,
187 SOS_X86_VIDEO_FG_Y 341 SOS_X86_VIDEO_FG_YELLOW | SOS_X86_VIDEO_BG_BLUE,
188 "Welcome to SOS"); !! 342 "Welcome to SOS article 6.5");
189 343
190 sos_bochs_putstring("Message in a bochs\n"); !! 344 sos_bochs_putstring("Message in a bochs: This is SOS article 6.5.\n");
191 345
192 346
193 sos_gdt_setup(); !! 347 sos_gdt_subsystem_setup();
194 sos_idt_setup(); !! 348 sos_idt_subsystem_setup();
195 349
196 350
197 sos_exceptions_setup(); !! 351 sos_exception_subsystem_setup();
198 sos_irq_setup(); !! 352 sos_irq_subsystem_setup();
199 353
200 354
201 sos_i8254_set_frequency(100); 355 sos_i8254_set_frequency(100);
202 356
>> 357
>> 358
>> 359 tick_resolution = (struct sos_time) { .sec=0, .nanosec=10000000UL };
>> 360 sos_time_subsysem_setup(& tick_resolution);
203 361
204 362
205 if (magic != MULTIBOOT_BOOTLOADER_MAGIC) 363 if (magic != MULTIBOOT_BOOTLOADER_MAGIC)
206 { 364 {
207 sos_x86_videomem_putstring(20, 0, 365 sos_x86_videomem_putstring(20, 0,
208 SOS_X86_VIDEO 366 SOS_X86_VIDEO_FG_LTRED
209 | SOS_X86_V 367 | SOS_X86_VIDEO_BG_BLUE
210 | SOS_X86_V 368 | SOS_X86_VIDEO_FG_BLINKING,
211 "I'm not load 369 "I'm not loaded with Grub !");
212 370
213 for (;;) 371 for (;;)
214 continue; 372 continue;
215 } 373 }
216 374
>> 375
>> 376
>> 377
>> 378
217 379
218 sos_irq_set_routine(SOS_IRQ_TIMER, 380 sos_irq_set_routine(SOS_IRQ_TIMER,
219 clk_it); !! 381 clk_it);
220 !! 382
221 !! 383
222 asm volatile ("sti\n"); !! 384
>> 385
>> 386
223 387
224 388
225 389
226 sos_physmem_setup((mbi->mem_upper<<10) + (1< !! 390 sos_physmem_subsystem_setup((mbi->mem_upper<<10) + (1<<20),
227 & sos_kernel_core_base_pad !! 391 & sos_kernel_core_base_paddr,
228 & sos_kernel_core_top_padd !! 392 & sos_kernel_core_top_paddr);
229 test_physmem(); !! 393
230 !! 394
231 !! 395
232 for (;;) !! 396
233 continue; !! 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
234 440
235 return; !! 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 !");
236 } 461 }