Warning, cross-references for /kernel/boot/init.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include "boot/multiboot.h"
0019 #include "arch/i386.h"
0020 #include "arch/i386-percpu.h"
0021 #include "util/cpuid.h"
0022 #include "kernel.h"
0023 #include "fs/filesys.h"
0024 #include "smp/smp.h"
0025 #include "mem/mem.h"
0026 #include "drivers/ata/ata.h"
0027 #include "drivers/pci/pci.h"
0028 #include "util/printf.h"
0029 #include "util/screen.h"
0030 #include "util/debug.h"
0031 #include "util/perfmon.h"
0032 #include "drivers/input/keyboard.h"
0033 #include "sched/sched.h"
0034
0035 extern descriptor idt[];
0036
0037 extern uint32 _readwrite_pages, _readonly_pages, _bootstrap_pages;
0038 extern uint32 _kernelstart, _physicalkernelstart;
0039
0040
0041 uint32 stack[1024] __attribute__ ((aligned (0x1000)));
0042
0043
0044 static uint16
0045 alloc_CPU_TSS (tss *tssp)
0046 {
0047 int i;
0048 descriptor *ad = (descriptor *)KERN_GDT;
0049
0050
0051 for (i = 1; i < 256; i++)
0052 if (!(ad[i].fPresent))
0053 break;
0054
0055 if (i == 256)
0056 panic ("No free selector for TSS");
0057
0058 ad[i].uLimit0 = sizeof (tss);
0059 ad[i].uLimit1 = 0;
0060 ad[i].pBase0 = (uint32) tssp & 0xFFFF;
0061 ad[i].pBase1 = ((uint32) tssp >> 16) & 0xFF;
0062 ad[i].pBase2 = (uint32) tssp >> 24;
0063 ad[i].uType = 0x09;
0064 ad[i].uDPL = 0;
0065 ad[i].fPresent = 1;
0066 ad[i].f0 = 0;
0067 ad[i].fX = 0;
0068 ad[i].fGranularity = 0;
0069
0070 tssp->usSS0 = 0x10;
0071 tssp->ulESP0 = (uint32) KERN_STK + 0x1000;
0072
0073 return i << 3;
0074
0075 }
0076 static uint16
0077 alloc_idle_TSS (int cpu_num)
0078 {
0079 int i;
0080 descriptor *ad = (descriptor *)KERN_GDT;
0081 quest_tss *pTSS = (quest_tss *) (&idleTSS[cpu_num]);
0082 void idle_task (void);
0083
0084
0085 for (i = 1; i < 256; i++)
0086 if (!(ad[i].fPresent))
0087 break;
0088
0089 if (i == 256)
0090 panic ("No free selector for TSS");
0091
0092 ad[i].uLimit0 = sizeof (idleTSS[cpu_num]) - 1;
0093 ad[i].uLimit1 = 0;
0094 ad[i].pBase0 = (u32) pTSS & 0xFFFF;
0095 ad[i].pBase1 = ((u32) pTSS >> 16) & 0xFF;
0096 ad[i].pBase2 = (u32) pTSS >> 24;
0097 ad[i].uType = 0x09;
0098 ad[i].uDPL = 0;
0099 ad[i].fPresent = 1;
0100 ad[i].f0 = 0;
0101 ad[i].fX = 0;
0102 ad[i].fGranularity = 0;
0103
0104 u32 *stk = map_virtual_page (alloc_phys_frame () | 3);
0105
0106 pTSS->CR3 = (u32) get_pdbr ();
0107 pTSS->initial_EIP = (u32) & idle_task;
0108 stk[1023] = pTSS->initial_EIP;
0109 pTSS->EFLAGS = F_1 | F_IOPL0;
0110
0111 pTSS->ESP = (u32) &stk[1023];
0112 pTSS->EBP = pTSS->ESP;
0113
0114
0115 return i << 3;
0116 }
0117
0118
0119
0120
0121 static uint16
0122 alloc_TSS (void *pPageDirectory, void *pEntry, int mod_num)
0123 {
0124
0125 int i;
0126 descriptor *ad = (idt + 256);
0127 quest_tss *pTSS = (quest_tss *) ul_tss[mod_num];
0128
0129
0130 for (i = 1; i < 256; i++)
0131 if (!(ad[i].fPresent))
0132 break;
0133
0134 if (i == 256)
0135 panic ("No free selector for TSS");
0136
0137 ad[i].uLimit0 = sizeof (ul_tss[mod_num]) - 1;
0138 ad[i].uLimit1 = 0;
0139 ad[i].pBase0 = (u32) pTSS & 0xFFFF;
0140 ad[i].pBase1 = ((u32) pTSS >> 16) & 0xFF;
0141 ad[i].pBase2 = (u32) pTSS >> 24;
0142 ad[i].uType = 0x09;
0143 ad[i].uDPL = 0;
0144 ad[i].fPresent = 1;
0145 ad[i].f0 = 0;
0146 ad[i].fX = 0;
0147 ad[i].fGranularity = 0;
0148
0149 pTSS->CR3 = (u32) pPageDirectory;
0150 pTSS->initial_EIP = (u32) pEntry;
0151
0152 if (mod_num != 1)
0153 pTSS->EFLAGS = F_1 | F_IF | F_IOPL0;
0154 else
0155 pTSS->EFLAGS = F_1 | F_IF | F_IOPL;
0156
0157
0158 pTSS->ESP = 0x400000 - 100;
0159 pTSS->EBP = 0x400000 - 100;
0160
0161 semaphore_init (&pTSS->Msem, 1, 0);
0162
0163
0164 return i << 3;
0165 }
0166
0167
0168
0169 static uint16
0170 load_module (multiboot_module * pmm, int mod_num)
0171 {
0172
0173 uint32 *plPageDirectory = get_phys_addr (pg_dir[mod_num]);
0174 uint32 *plPageTable = get_phys_addr (pg_table[mod_num]);
0175 void *pStack = get_phys_addr (ul_stack[mod_num]);
0176
0177 Elf32_Ehdr *pe, *pe0 = map_virtual_page ((uint) pmm->pe | 3);
0178 Elf32_Phdr *pph = (void *) pe0 + pe0->e_phoff;
0179 void *pEntry = (void *) pe0->e_entry;
0180 int i, c, j;
0181 uint32 *stack_virt_addr;
0182 uint32 page_count = 1;
0183
0184
0185 for (i = 0; i < pe0->e_phnum; i++) {
0186 if (pph->p_type == PT_LOAD)
0187 page_count += (pph->p_memsz >> 12);
0188 pph = (void *) pph + pe0->e_phentsize;
0189 }
0190
0191
0192 pe = map_contiguous_virtual_pages ((uint) pmm->pe | 3, page_count);
0193
0194 unmap_virtual_page (pe0);
0195
0196 pph = (void *) pe + pe->e_phoff;
0197
0198
0199 memcpy (&plPageDirectory[1023], (void *) (((uint32) get_pdbr ()) + 4092),
0200 4);
0201
0202 memcpy (&plPageDirectory[1019], (void *) (((uint32) get_pdbr ()) + 4076),
0203 4);
0204
0205
0206
0207 plPageDirectory[0] = (uint32) plPageTable | 7;
0208
0209 plPageDirectory[1022] = (uint32) get_phys_addr (kls_pg_table[mod_num]) | 3;
0210 kls_pg_table[mod_num][0] = (uint32) get_phys_addr (kl_stack[mod_num]) | 3;
0211
0212
0213 for (i = 0; i < pe->e_phnum; i++) {
0214
0215 if (pph->p_type == PT_LOAD) {
0216
0217 c = (pph->p_filesz + 0xFFF) >> 12;
0218
0219 for (j = 0; j < c; j++)
0220 plPageTable[((uint32) pph->p_vaddr >> 12) + j] =
0221 (uint32) pmm->pe + (pph->p_offset & 0xFFFFF000) + (j << 12) + 7;
0222
0223
0224 memset ((void *) pe + pph->p_offset + pph->p_filesz,
0225 0, (pph->p_memsz - pph->p_filesz) & 0x0FFF);
0226
0227
0228 c = (pph->p_memsz + 0xFFF) >> 12;
0229
0230
0231
0232
0233 for (; j <= c; j++) {
0234 uint32 page_frame = (uint32) alloc_phys_frame ();
0235 void *virt_addr = map_virtual_page (page_frame | 3);
0236 memset (virt_addr, 0, 0x1000);
0237 plPageTable[((uint32) pph->p_vaddr >> 12) + j] = page_frame + 7;
0238 unmap_virtual_page (virt_addr);
0239 }
0240 }
0241
0242 pph = (void *) pph + pe->e_phentsize;
0243 }
0244
0245
0246 plPageTable[1023] = (uint32) pStack | 7;
0247
0248 stack_virt_addr = map_virtual_page ((uint32) pStack | 3);
0249
0250
0251 memcpy ((char *) stack_virt_addr + 0x1000 - 80, pmm->string, 80);
0252 *(uint32 *) ((char *) stack_virt_addr + 0x1000 - 84) = 0;
0253 *(uint32 *) ((char *) stack_virt_addr + 0x1000 - 88) = 0x400000 - 80;
0254 *(uint32 *) ((char *) stack_virt_addr + 0x1000 - 92) = 0x400000 - 88;
0255 *(uint32 *) ((char *) stack_virt_addr + 0x1000 - 96) = 1;
0256
0257
0258 *(uint32 *) ((char *) stack_virt_addr + 0x1000 - 100) = 0;
0259
0260 unmap_virtual_page (stack_virt_addr);
0261 unmap_virtual_pages (pe, page_count);
0262
0263 u16 pid = alloc_TSS (plPageDirectory, pEntry, mod_num);
0264 com1_printf ("module %d loaded: task_id=0x%x\n", mod_num, pid);
0265 #if QUEST_SCHED==vcpu
0266 lookup_TSS (pid)->cpu = 0;
0267 #endif
0268 return pid;
0269 }
0270
0271
0272
0273 void
0274 init_pic (void)
0275 {
0276
0277
0278
0279
0280
0281
0282
0283 outb (0x11, 0x20);
0284 outb (PIC1_BASE_IRQ, 0x21);
0285 outb (0x04, 0x21);
0286 outb (0x0D, 0x21);
0287
0288
0289 outb (0x11, 0xA0);
0290 outb (PIC2_BASE_IRQ, 0xA1);
0291 outb (0x02, 0xA1);
0292 outb (0x09, 0xA1);
0293
0294 }
0295
0296
0297
0298 void
0299 init_pit (void)
0300 {
0301
0302 outb (0x34, 0x43);
0303
0304
0305 outb ((PIT_FREQ / HZ) & 0xFF, 0x40);
0306 outb ((PIT_FREQ / HZ) >> 8, 0x40);
0307 }
0308
0309 void
0310 initialize_serial_port (void)
0311 {
0312 outb (0, serial_port1 + 1);
0313
0314
0315
0316 outb (0x80, serial_port1 + 3);
0317 outb (0x03, serial_port1 + 0);
0318
0319
0320
0321
0322
0323
0324
0325 outb (0x00, serial_port1 + 1);
0326 outb (0x03, serial_port1 + 3);
0327 outb (0xC7, serial_port1 + 2);
0328 outb (0x0B, serial_port1 + 4);
0329 com1_puts ("COM1 initialized.\n");
0330 }
0331
0332 int
0333 parse_root_type (char *cmdline)
0334 {
0335 char *p, *q;
0336 for (p=cmdline; p[0] && p[1] && p[2] && p[3] && p[4]; p++) {
0337 if (p[0] == 'r' && p[1] == 'o' && p[2] == 'o' &&
0338 p[3] == 't' && p[4] == '=') {
0339 p+=5;
0340 for (q=p; *q && *q != ' '; q++);
0341 *q = '\0';
0342 if (q - p >= 4 &&
0343 p[0] == '(' && p[1] == 'h' && p[2] == 'd' && p[3] == ')')
0344 return VFS_FSYS_EZEXT2;
0345 if (q - p >= 4 &&
0346 p[0] == '(' && p[1] == 'c' && p[2] == 'd' && p[3] == ')')
0347 return VFS_FSYS_EZISO;
0348 if (q - p >= 6 &&
0349 p[0] == '(' && p[1] == 't' && p[2] == 'f' &&
0350 p[3] == 't' && p[4] == 'p' && p[5] == ')')
0351 return VFS_FSYS_EZTFTP;
0352 if (q - p >= 5 &&
0353 p[0] == '(' && p[1] == 'u' && p[2] == 's' &&
0354 p[3] == 'b' && p[4] == ')')
0355 return VFS_FSYS_EZUSB;
0356 }
0357 }
0358 return VFS_FSYS_NONE;
0359 }
0360
0361 u32 root_type, boot_device=0;
0362
0363 void
0364 init (multiboot * pmb)
0365 {
0366 int i, j, k, c, num_cpus;
0367 uint16 tss[NR_MODS];
0368 memory_map_t *mmap;
0369 uint32 limit;
0370 Elf32_Phdr *pph;
0371 Elf32_Ehdr *pe;
0372 char brandstring[I386_CPUID_BRAND_STRING_LENGTH];
0373
0374
0375 outw (0x8A00, 0x8A00);
0376
0377 initialize_serial_port ();
0378
0379 pchVideo = (char *)KERN_SCR;
0380
0381
0382 for (i = 0; i < 80 * 25; i++) {
0383 pchVideo[i * 2] = ' ';
0384 pchVideo[i * 2 + 1] = 7;
0385 }
0386
0387 print ("\n\n\n");
0388
0389 com1_printf ("cmdline: %s\n", pmb->cmdline);
0390 root_type = parse_root_type (pmb->cmdline);
0391 com1_printf ("root_type=%d\n", root_type);
0392
0393 if (pmb->flags & 0x2) {
0394 multiboot_drive *d;
0395 boot_device = pmb->boot_device;
0396 printf ("Boot device: %X\n", boot_device);
0397 com1_printf ("Boot device: %X\n", boot_device);
0398 if (pmb->flags & 0x80) {
0399 for (d = pmb->drives_addr, i = 0;
0400 i < pmb->drives_length;
0401 i += d->size, d = (multiboot_drive *) ((uint8 *) d + d->size)) {
0402 printf ("Found drive. number: %X\n", d->number);
0403 com1_printf ("Found drive. number: %X\n", d->number);
0404 }
0405 }
0406 }
0407
0408 cpuid_get_brand_string (brandstring, I386_CPUID_BRAND_STRING_LENGTH);
0409 printf ("CPUID says: %s\n", brandstring);
0410 if (!cpuid_msr_support ())
0411 panic ("Model-specific registers not supported!\n");
0412 if (!cpuid_tsc_support ())
0413 panic ("Timestamp counter not supported!");
0414 if (!cpuid_rdtscp_support ())
0415 logger_printf ("RDTSCP NOT supported.\n");
0416 else
0417 logger_printf ("RDTSCP supported.\n");
0418 if (cpuid_invariant_tsc_support ()) {
0419 print ("Invariant TSC support detected\n");
0420 com1_printf ("Invariant TSC support detected\n");
0421 }
0422
0423 for (mmap = (memory_map_t *) pmb->mmap_addr;
0424 (uint32) mmap < pmb->mmap_addr + pmb->mmap_length;
0425 mmap = (memory_map_t *) ((uint32) mmap
0426 + mmap->size + 4 )) {
0427
0428
0429
0430
0431 if (mmap->type == 1) {
0432 if (mmap->base_addr_high == 0x0) {
0433
0434 for (i = 0; i < (mmap->length_low >> 12); i++)
0435 BITMAP_SET (mm_table, (mmap->base_addr_low >> 12) + i);
0436 limit = (mmap->base_addr_low >> 12) + i;
0437
0438 if (limit > mm_limit)
0439 mm_limit = limit;
0440 }
0441 }
0442 }
0443
0444
0445
0446
0447
0448 for (i = 0;
0449 i <
0450 (uint32) &_bootstrap_pages + (uint32) &_readwrite_pages +
0451 (uint32) &_readonly_pages; i++)
0452 BITMAP_CLR (mm_table, 256 + i);
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463 for (i = 0; i < pmb->mods_count; i++) {
0464
0465 pe = map_virtual_page ((uint32)pmb->mods_addr[i].pe | 3);
0466
0467 pph = (void *) pe + pe->e_phoff;
0468
0469 for (j = 0; j < pe->e_phnum; j++) {
0470
0471 if (pph->p_type == PT_LOAD) {
0472 c = (pph->p_filesz + 0xFFF) >> 12;
0473
0474 for (k = 0; k < c; k++)
0475 BITMAP_CLR (mm_table, (((uint32) pe + pph->p_offset) >> 12) + k);
0476 }
0477 pph = (void *) pph + pe->e_phentsize;
0478 }
0479
0480 unmap_virtual_page (pe);
0481 }
0482
0483
0484
0485 for (i=0; i<256; i++)
0486 BITMAP_CLR (mm_table, i);
0487
0488
0489 BITMAP_CLR (mm_table, (u32) pmb >> 12);
0490
0491 #if 0
0492
0493 for (i = 0; i < 2000; i++)
0494 putchar (BITMAP_TST (mm_table, i) ? '1' : '0');
0495 while (1);
0496 #endif
0497
0498
0499
0500
0501
0502 init_interrupt_handlers ();
0503
0504
0505 init_pic ();
0506
0507
0508 init_pit ();
0509
0510 pow2_init ();
0511
0512
0513 percpu_per_cpu_init ();
0514
0515
0516 num_cpus = smp_init ();
0517 if (num_cpus > 1) {
0518 print ("Multi-processing detected. Number of CPUs: ");
0519 putx (num_cpus);
0520 putchar ('\n');
0521 } else {
0522 print ("Uni-processor mode.\n");
0523 }
0524
0525
0526 for (i = 0; i < num_cpus; i++) {
0527 cpuTSS_selector[i] = alloc_CPU_TSS (&cpuTSS[i]);
0528 idleTSS_selector[i] = alloc_idle_TSS (i);
0529 }
0530
0531
0532 if (!pmb->mods_count)
0533 panic ("No modules available");
0534 for (i = 0; i < pmb->mods_count; i++) {
0535 tss[i] = load_module (pmb->mods_addr + i, i);
0536 lookup_TSS (tss[i])->priority = MIN_PRIO;
0537 }
0538
0539
0540 *((uint32 *)get_pdbr()) = 0;
0541 flush_tlb_all ();
0542
0543
0544 hw_ltr (cpuTSS_selector[0]);
0545
0546
0547
0548
0549 smp_secondary_init ();
0550
0551
0552 { extern bool module_load_all (void); module_load_all (); }
0553
0554
0555 u32 *page_table = (u32 *) KERN_PGT;
0556 u32 free_pages = 0;
0557 for (i = 0; i < 1024; i++)
0558 if (page_table[i] == 0)
0559 free_pages++;
0560 printf ("free kernel pages=%d\n", free_pages);
0561 logger_printf ("free kernel pages=%d\n", free_pages);
0562
0563
0564 smp_enable_scheduling ();
0565
0566 #ifdef ENABLE_GDBSTUB
0567 {
0568 #ifndef GDBSTUB_TCP
0569 void set_debug_traps (void);
0570 set_debug_traps ();
0571 BREAKPOINT ();
0572 #endif
0573 }
0574 #endif
0575
0576
0577
0578
0579
0580 ltr (tss[0]);
0581
0582 asm volatile ("jmp _sw_init_user_task"::"D" (lookup_TSS (tss[0])));
0583
0584
0585 panic ("BSP: unreachable");
0586 }
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597