Warning, cross-references for /kernel/interrupt_handler.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include "arch/i386.h"
0025 #include "arch/i386-percpu.h"
0026 #include "arch/i386-measure.h"
0027 #include "kernel.h"
0028 #include "mem/mem.h"
0029 #include "util/elf.h"
0030 #include "fs/filesys.h"
0031 #include "smp/smp.h"
0032 #include "smp/apic.h"
0033 #include "util/printf.h"
0034 #include "util/screen.h"
0035 #include "util/debug.h"
0036 #include "drivers/input/keymap.h"
0037 #include "drivers/input/keyboard.h"
0038 #include "sched/sched.h"
0039 #include "sched/vcpu.h"
0040
0041
0042
0043
0044 static char kernel_ver[] = "0.1a";
0045 char *kernel_version = kernel_ver;
0046 uint32 tick;
0047
0048 extern uint32 ul_tss[][1024];
0049
0050
0051 static vector_handler vector_handlers[256];
0052
0053
0054 static uint32
0055 default_vector_handler (uint8 vec)
0056 {
0057 return 0;
0058 }
0059
0060
0061 void
0062 set_vector_handler (uint8 vec, vector_handler func)
0063 {
0064 vector_handlers[vec] = func;
0065 }
0066
0067
0068 void
0069 clr_vector_handler (uint8 vec)
0070 {
0071 vector_handlers[vec] = default_vector_handler;
0072 }
0073
0074
0075 vector_handler
0076 get_vector_handler (uint8 vec)
0077 {
0078 if (vector_handlers[vec])
0079 return vector_handlers[vec];
0080 else
0081 return default_vector_handler;
0082 }
0083
0084
0085
0086 uint32
0087 dispatch_vector (uint32 vec)
0088 {
0089 vector_handler func = vector_handlers[(uint8) vec];
0090 uint32 v;
0091
0092
0093 if (func)
0094 v = func (vec);
0095 else
0096 v = 0;
0097
0098 if (!mp_apic_mode && PIC2_BASE_IRQ <= vec && vec < (PIC2_BASE_IRQ + 8))
0099 outb (0x20, 0xA0);
0100 send_eoi ();
0101 return v;
0102 }
0103
0104 u8
0105 find_unused_vector (u8 min_prio)
0106 {
0107 u8 i;
0108 if (min_prio < MINIMUM_VECTOR_PRIORITY || min_prio > 0xF)
0109 return 0;
0110 for (i=(min_prio << 4); i < 0xFF; i++) {
0111 if (vector_handlers[i] == default_vector_handler)
0112 return i;
0113 }
0114 return (vector_handlers[i] == default_vector_handler ? i : 0);
0115 }
0116
0117
0118 uint16
0119 duplicate_TSS (uint32 ebp,
0120 uint32 *esp,
0121 uint32 child_eip,
0122 uint32 child_ebp,
0123 uint32 child_esp,
0124 uint32 child_eflags,
0125 uint32 child_directory)
0126 {
0127
0128 int i;
0129 descriptor *ad = (descriptor *) KERN_GDT;
0130 quest_tss *pTSS;
0131 uint32 pa;
0132
0133 pa = alloc_phys_frame ();
0134
0135
0136
0137
0138
0139
0140
0141
0142 pTSS = map_virtual_page (pa + 3);
0143
0144
0145 memset (pTSS, 0, 4096);
0146
0147
0148 for (i = 1; i < 256; i++)
0149 if (!(ad[i].fPresent))
0150 break;
0151
0152 if (i == 256)
0153 panic ("No free selector for TSS");
0154
0155 logger_printf ("duplicate_TSS: pTSS=%p i=0x%x esp=%p ebp=%p\n",
0156 pTSS, i << 3,
0157 child_esp, child_ebp);
0158
0159
0160 ad[i].uLimit0 = 0xFFF;
0161 ad[i].uLimit1 = 0;
0162 ad[i].pBase0 = (u32) pTSS & 0xFFFF;
0163 ad[i].pBase1 = ((u32) pTSS >> 16) & 0xFF;
0164 ad[i].pBase2 = (u32) pTSS >> 24;
0165 ad[i].uType = 0x09;
0166 ad[i].uDPL = 0;
0167 ad[i].fPresent = 1;
0168 ad[i].f0 = 0;
0169 ad[i].fX = 0;
0170 ad[i].fGranularity = 0;
0171
0172 pTSS->CR3 = (u32) child_directory;
0173
0174
0175 pTSS->initial_EIP = child_eip;
0176
0177
0178 linear_address_t esp_la; esp_la.raw = child_esp;
0179 pgdir_t child_pgdir;
0180 child_pgdir.dir_pa = child_directory;
0181 child_pgdir.dir_va = map_virtual_page (child_directory | 3);
0182 if (child_pgdir.dir_va == NULL)
0183 panic ("child_pgdir: out of memory");
0184 frame_t esp_frame = pgdir_get_frame (child_pgdir, (void *) (child_esp & (~0xFFF)));
0185 u32 *esp_virt = map_virtual_page (esp_frame | 3);
0186 if (esp_virt == NULL)
0187 panic ("esp_virt: out of memory");
0188 esp_virt[esp_la.offset >> 2] = pTSS->initial_EIP;
0189 unmap_virtual_page (child_pgdir.dir_va);
0190 unmap_virtual_page (esp_virt);
0191
0192 pTSS->EFLAGS = child_eflags & 0xFFFFBFFF;
0193 pTSS->ESP = child_esp;
0194 pTSS->EBP = child_ebp;
0195
0196 semaphore_init (&pTSS->Msem, 1, 0);
0197
0198 pTSS->cpu = 0xFF;
0199
0200
0201 return i << 3;
0202 }
0203
0204 char *exception_messages[] = {
0205 "Division Error",
0206 "Debug",
0207 "Non Maskable Interrupt",
0208 "Breakpoint",
0209 "Into Detected Overflow",
0210 "Out of Bounds",
0211 "Invalid Opcode",
0212 "No Coprocessor",
0213 "Double Fault",
0214 "Coprocessor Segment Overrun",
0215 "Bad TSS",
0216 "Segment Not Present",
0217 "Stack Fault",
0218 "General Protection Fault",
0219 "Page Fault",
0220 "Unknown Interrupt",
0221 "Coprocessor Fault",
0222 "Alignment Check",
0223 "Machine Check",
0224 "Reserved",
0225 "Reserved",
0226 "Reserved",
0227 "Reserved",
0228 "Reserved",
0229 "Reserved",
0230 "Reserved",
0231 "Reserved",
0232 "Reserved",
0233 "Reserved",
0234 "Reserved",
0235 "Reserved",
0236 "Reserved"
0237 };
0238
0239
0240
0241 extern void
0242 handle_interrupt (u32 edi, u32 esi, u32 ebp, u32 _esp, u32 ebx, u32 edx, u32 ecx, u32 eax,
0243 u32 fs_gs, u32 ds_es, u32 ulInt, u32 ulCode,
0244 u32 eip, u32 cs, u32 eflags, u32 esp, u32 ss)
0245 {
0246 u32 cr0, cr2, cr3;
0247 u16 tr, fs, ds;
0248
0249 asm volatile ("movl %%cr0, %%eax\n"
0250 "movl %%eax, %0\n"
0251 "movl %%cr2, %%eax\n"
0252 "movl %%eax, %1\n"
0253 "movl %%cr3, %%eax\n"
0254 "movl %%eax, %2\n"
0255 "xorl %%eax, %%eax\n"
0256 "str %%ax\n"
0257 "movw %%ax, %3\n"
0258 "movw %%fs, %%ax\n"
0259 "movw %%ax, %4\n"
0260 "movw %%ds, %%ax\n"
0261 "movw %%ax, %5\n"
0262 :"=m" (cr0), "=m" (cr2), "=m" (cr3),
0263 "=m" (tr), "=m" (fs), "=m" (ds):);
0264
0265 if ((cs & 0x3) == 0) {
0266
0267 asm volatile ("movl %%ss, %0":"=r" (ss));
0268 esp = _esp;
0269 }
0270
0271 spinlock_lock (&screen_lock);
0272 _putchar ('I');
0273 _putx (ulInt);
0274 _putchar (' ');
0275 _putchar ('c');
0276 _putx (ulCode);
0277 _putchar (' ');
0278 if (ulInt < 32)
0279 _print (exception_messages[ulInt]);
0280 _putchar ('\n');
0281
0282 #ifndef ENABLE_GDBSTUB
0283 #define _putchar com1_putc
0284 #define _putx com1_putx
0285 #define _print com1_puts
0286 #define _printf com1_printf
0287 #endif
0288
0289 _printf ("INT=%.2X CODE=%.8X %s\n",
0290 ulInt, ulCode, exception_messages[ulInt]);
0291 _printf ("EAX=%.8X ESI=%.8X\n", eax, esi);
0292 _printf ("EBX=%.8X EDI=%.8X\n", ebx, edi);
0293 _printf ("ECX=%.8X EBP=%.8X\n", ecx, ebp);
0294 _printf ("EDX=%.8X ESP=%.8X\n", edx, esp);
0295 _printf ("EFL=%.8X EIP=%.8X\n", eflags, eip);
0296 _printf ("CR0=%.8X CR2=%.8X\nCR3=%.8X TR=%.4X\n", cr0, cr2, cr3, tr);
0297 _printf (" CS=%.4X SS=%.4X DS=%.4X FS=%.4X\n", cs, ss, ds, fs);
0298 _printf ("CURRENT=0x%X\n", percpu_read (current_task));
0299 stacktrace_frame (esp, ebp);
0300
0301 #ifndef ENABLE_GDBSTUB
0302 #undef _putx
0303 #undef _putchar
0304 #undef _print
0305 #undef _printf
0306 #endif
0307
0308 spinlock_unlock (&screen_lock);
0309
0310 if (ulInt < 0x20)
0311
0312 crash_debug ("Unhandled exception");
0313
0314 send_eoi ();
0315 }
0316
0317 static int
0318 user_putchar (int ch, int attribute)
0319 {
0320 static int x, y;
0321
0322 if (ch == '\n') {
0323 x = 0;
0324 y++;
0325
0326 if (y > 24) {
0327 memcpy (pchVideo, pchVideo + 160, 24 * 160);
0328 memset (pchVideo + (24 * 160), 0, 160);
0329 y = 24;
0330 }
0331 return (int) (unsigned char) ch;
0332 }
0333
0334 if (y * 160 + x * 2 >= 0x1000) return ch;
0335
0336 pchVideo[y * 160 + x * 2] = ch;
0337 pchVideo[y * 160 + x * 2 + 1] = attribute;
0338 x++;
0339
0340 if (y * 160 + x * 2 >= 0x1000) return ch;
0341
0342 pchVideo[y * 160 + x * 2] = ' ';
0343 pchVideo[y * 160 + x * 2 + 1] = attribute;
0344
0345
0346 outb (0x0E, 0x3D4);
0347 outb ((y * 80 + x) >> 8, 0x3D5);
0348 outb (0x0F, 0x3D4);
0349 outb ((y * 80 + x) & 0xFF, 0x3D5);
0350
0351 return (int) (unsigned char) ch;
0352 }
0353
0354 static void
0355 _user_putchar_attr_4 (char c)
0356 {
0357 user_putchar (c, 4);
0358 }
0359
0360 static void
0361 splash_screen (void)
0362 {
0363 int _uname (char *);
0364 u32 _meminfo (u32, u32);
0365 u32 free = _meminfo (0, 0);
0366 char vers[80];
0367
0368 _uname (vers);
0369
0370 fun_printf (_user_putchar_attr_4,
0371 "**** Quest kernel version: %s *****"
0372 " //---\\ \\\\ \\ //-- //--\\ \\\\---\\ \n",
0373 vers);
0374
0375 fun_printf (_user_putchar_attr_4,
0376 "* Copyright Boston University, 2010 *"
0377 " || | || | ||-- \\\\--\\ || \n");
0378
0379 fun_printf (_user_putchar_attr_4,
0380 "******** 0x%.08X bytes free ******"
0381 " \\\\__\\_ \\\\_/ \\\\__ \\\\__/ || \n",
0382 free);
0383 }
0384
0385
0386 static u32
0387 syscall_putchar (u32 eax, u32 ebx)
0388 {
0389 static bool first = TRUE;
0390
0391 if (first) { splash_screen (); first = FALSE; }
0392 user_putchar (ebx, 7);
0393 return 0;
0394 }
0395
0396 static u32
0397 syscall_usleep (u32 eax, u32 ebx)
0398 {
0399 sched_usleep (ebx);
0400 return ebx;
0401 }
0402
0403 struct syscall {
0404 u32 (*func) (u32, u32);
0405 };
0406 struct syscall syscall_table[] = {
0407 { .func = syscall_putchar },
0408 { .func = syscall_usleep },
0409 };
0410 #define NUM_SYSCALLS (sizeof (syscall_table) / sizeof (struct syscall))
0411
0412 u32
0413 handle_syscall0 (u32 eax, u32 ebx)
0414 {
0415 u32 res;
0416 lock_kernel ();
0417 if (eax < NUM_SYSCALLS)
0418 res = syscall_table[eax].func (eax, ebx);
0419 else
0420 res = 0;
0421 unlock_kernel ();
0422 return res;
0423 }
0424
0425
0426
0427
0428
0429
0430
0431 task_id
0432 _fork (uint32 ebp, uint32 *esp)
0433 {
0434
0435 uint16 child_gdt_index;
0436 void *phys_addr;
0437 uint32 *virt_addr;
0438 uint32 priority;
0439 uint32 eflags, eip, this_esp, this_ebp;
0440
0441 #ifdef DEBUG_SYSCALL
0442 com1_printf ("_fork (%X, %p)\n", ebp, esp);
0443 #endif
0444 lock_kernel ();
0445
0446
0447
0448
0449
0450
0451 asm volatile ("call 1f\n"
0452 "movl $0, %0\n"
0453 "jmp 2f\n"
0454 "1:\n"
0455 "movl (%%esp), %0\n"
0456 "addl $4, %%esp\n"
0457 "2:\n":"=r" (eip):);
0458
0459 if (eip == 0) {
0460
0461 unlock_kernel ();
0462
0463
0464 return 0;
0465 }
0466
0467 asm volatile ("movl %%ebp, %0\n"
0468 "movl %%esp, %1\n"
0469 "pushfl\n"
0470 "pop %2\n":"=r" (this_ebp), "=r" (this_esp), "=r" (eflags):);
0471
0472
0473
0474 phys_addr = get_pdbr ();
0475 virt_addr = map_virtual_page ((uint32) phys_addr | 3);
0476
0477 if (virt_addr == NULL)
0478 panic ("_fork: virt_addr: out of memory");
0479
0480 pgdir_t parentpgd = { .dir_pa = (frame_t) phys_addr,
0481 .dir_va = (pgdir_entry_t *) virt_addr };
0482
0483 pgdir_t childpgd = clone_page_directory (parentpgd);
0484 if (childpgd.dir_pa == -1)
0485 panic ("_fork: clone_page_directory: failed");
0486
0487 unmap_virtual_page (parentpgd.dir_va);
0488 unmap_virtual_page (childpgd.dir_va);
0489
0490
0491
0492
0493 child_gdt_index =
0494 duplicate_TSS (ebp, esp, eip, this_ebp, this_esp, eflags, childpgd.dir_pa);
0495
0496
0497 priority = lookup_TSS (child_gdt_index)->priority =
0498 lookup_TSS (str ())->priority;
0499
0500 wakeup (child_gdt_index);
0501
0502
0503
0504 unlock_kernel ();
0505
0506 return child_gdt_index;
0507 }
0508
0509
0510 char *
0511 strncpy (char *s1, const char *s2, int length)
0512 {
0513
0514 while ((length--) && (*s1++ = *s2++));
0515
0516 if (length < 0)
0517 *(s1 - 1) = '\0';
0518
0519 return s1;
0520 }
0521
0522
0523
0524
0525
0526
0527
0528
0529 int
0530 _exec (char *filename, char *argv[], uint32 *curr_stack)
0531 {
0532
0533 uint32 *plPageDirectory = map_virtual_page ((uint32) get_pdbr () | 3);
0534 uint32 *plPageTable;
0535 uint32 pStack;
0536 Elf32_Ehdr *pe = (Elf32_Ehdr *) 0xFF400000;
0537 Elf32_Phdr *pph;
0538 void *pEntry;
0539 int filesize, orig_filesize;
0540
0541
0542 uint32 phys_addr = alloc_phys_frame () | 3;
0543
0544
0545 uint32 frame_map[32];
0546 uint32 *frame_ptr = map_virtual_page (phys_addr);
0547 uint32 *tmp_page;
0548 int i, j, c;
0549 char command_args[80];
0550 char filename_bak[256];
0551
0552 if (!argv || !argv[0]) {
0553 BITMAP_SET (mm_table, phys_addr >> 12);
0554 unmap_virtual_page (plPageDirectory);
0555 unmap_virtual_page (frame_ptr);
0556 return -1;
0557 }
0558
0559 lock_kernel ();
0560 #ifdef DEBUG_SYSCALL
0561 com1_printf ("_exec (%s, [%s,...], %p)\n", filename, argv[0], curr_stack);
0562 #endif
0563
0564
0565
0566
0567
0568 strncpy (command_args, argv[0], 80);
0569
0570
0571
0572
0573
0574
0575 strncpy (filename_bak, filename, 256);
0576
0577 #ifdef DEBUG_SYSCALL
0578 com1_printf ("_exec: vfs_dir\n");
0579 #endif
0580
0581 if ((filesize = vfs_dir (filename)) < 0) {
0582 BITMAP_SET (mm_table, phys_addr >> 12);
0583 unmap_virtual_page (plPageDirectory);
0584 unmap_virtual_page (frame_ptr);
0585 unlock_kernel ();
0586 return -1;
0587 }
0588
0589
0590
0591
0592
0593 #ifdef DEBUG_SYSCALL
0594 com1_printf ("_exec: setup page directory\n");
0595 #endif
0596 for (i = 0; i < 1019; i++) {
0597
0598 if (plPageDirectory[i]) {
0599 tmp_page = map_virtual_page (plPageDirectory[i] | 3);
0600 for (j = 0; j < 1024; j++) {
0601 if (tmp_page[j]) {
0602 if ((j < 0x200) || (j > 0x20F) || i) {
0603
0604 BITMAP_SET (mm_table, tmp_page[j] >> 12);
0605 tmp_page[j] = 0;
0606 }
0607 }
0608 }
0609 unmap_virtual_page (tmp_page);
0610 BITMAP_SET (mm_table, plPageDirectory[i] >> 12);
0611 plPageDirectory[i] = 0;
0612 }
0613 }
0614
0615
0616 plPageDirectory[0] = alloc_phys_frame () | 7;
0617 plPageTable = map_virtual_page (plPageDirectory[0]);
0618 memset (plPageTable, 0, 0x1000);
0619
0620 for (i = 0; i < filesize; i += 4096) {
0621 frame_ptr[i >> 12] = alloc_phys_frame () | 3;
0622 }
0623
0624
0625 plPageDirectory[(uint32) pe >> 22] = phys_addr;
0626
0627 flush_tlb_all ();
0628
0629 #ifdef DEBUG_SYSCALL
0630 com1_printf ("_exec: vfs read\n");
0631 #endif
0632
0633 orig_filesize = filesize;
0634 filesize = vfs_read (filename_bak, (void *) pe, orig_filesize);
0635 if (filesize != orig_filesize) {
0636 printf ("expected filesize=%d got filesize=%d\n", orig_filesize, filesize);
0637 panic ("File size mismatch on read");
0638 }
0639
0640 pph = (void *) pe + pe->e_phoff;
0641 pEntry = (void *) pe->e_entry;
0642
0643 memset (frame_map, 0, 32 * sizeof (uint32));
0644
0645 #ifdef DEBUG_SYSCALL
0646 com1_printf ("_exec: walk ELF header\n");
0647 #endif
0648
0649 for (i = 0; i < pe->e_phnum; i++) {
0650 if (pph->p_type == PT_LOAD) {
0651 if ((pph->p_offset & 0xFFF) != (pph->p_vaddr & 0xFFF))
0652 panic ("Misalignment in program header");
0653
0654
0655 c = ((pph->p_offset + pph->p_filesz - 1) >> 12) - (pph->p_offset >> 12) + 1;
0656
0657 for (j = 0; j < c; j++) {
0658 if (j == c - 1) {
0659
0660
0661
0662
0663 uint32 frame = alloc_phys_frame ();
0664 char *buf = map_virtual_page (frame | 3);
0665 int partial = (pph->p_offset + pph->p_filesz) & 0xFFF;
0666
0667 memcpy (buf, (char *) pe + (pph->p_offset & ~0xFFF) +
0668 (j << 12), partial);
0669 memset (buf + partial, 0, 0x1000 - partial);
0670
0671 unmap_virtual_page (buf);
0672
0673 plPageTable[((uint32) pph->p_vaddr >> 12) + j] = frame | 7;
0674 } else {
0675 BITMAP_SET (frame_map, j + (pph->p_offset >> 12));
0676 plPageTable[((uint32) pph->p_vaddr >> 12) + j] =
0677 frame_ptr[j + (pph->p_offset >> 12)] | 7;
0678 }
0679 }
0680
0681
0682 c = ((pph->p_offset + pph->p_memsz - 1) >> 12) - (pph->p_offset >> 12) + 1;
0683
0684
0685
0686
0687 for (; j < c; j++) {
0688 uint32 page_frame = (uint32) alloc_phys_frame ();
0689 void *virt_page = map_virtual_page (page_frame | 3);
0690 plPageTable[((uint32) pph->p_vaddr >> 12) + j] = page_frame | 7;
0691 memset (virt_page, 0, 0x1000);
0692 unmap_virtual_page (virt_page);
0693 }
0694 }
0695
0696 pph = (void *) pph + pe->e_phentsize;
0697 }
0698
0699
0700 for (i = 0; i < filesize; i += 4096) {
0701 if (!BITMAP_TST (frame_map, i >> 12))
0702 BITMAP_SET (mm_table, frame_ptr[i >> 12] >> 12);
0703 }
0704
0705
0706 for (i = 0; i < 16; i++)
0707 plPageTable[0x200 + i] = 0xA0000 | (i << 12) | 7;
0708
0709
0710 for (i = 0; i < 16; i++) {
0711 pStack = alloc_phys_frame ();
0712 plPageTable[1023 - i] = pStack | 7;
0713 invalidate_page ((void *) ((1023 - i) << 12));
0714 }
0715 memset ((void *) 0x3F0000, 0, 0x10000);
0716
0717 plPageDirectory[1021] = 0;
0718 unmap_virtual_page (plPageDirectory);
0719 unmap_virtual_page (plPageTable);
0720 unmap_virtual_page (frame_ptr);
0721 BITMAP_SET (mm_table, phys_addr >> 12);
0722
0723 flush_tlb_all ();
0724
0725
0726 memcpy ((void *) (0x400000 - 80), command_args, 80);
0727
0728
0729
0730
0731 *(uint32 *) (0x400000 - 84) = 0;
0732 *(uint32 *) (0x400000 - 88) = 0x400000 - 80;
0733 *(uint32 *) (0x400000 - 92) = 0x400000 - 88;
0734 *(uint32 *) (0x400000 - 96) = 1;
0735
0736
0737
0738 *(uint32 *) (0x400000 - 100) = 0;
0739
0740
0741
0742
0743 curr_stack[0] = 0x00230023;
0744 curr_stack[1] = 0x00230023;
0745 curr_stack[2] = (uint32) pEntry;
0746 curr_stack[3] = 0x1B;
0747
0748 curr_stack[4] = F_1 | F_IF | 0x3000;
0749 curr_stack[5] = 0x400000 - 100;
0750 curr_stack[6] = 0x23;
0751
0752 unlock_kernel ();
0753 return 0;
0754 }
0755
0756
0757 uint
0758 _getchar (uint ebx)
0759 {
0760
0761 uint c = 0;
0762
0763 lock_kernel ();
0764
0765 if (ebx == 0)
0766 c = keymap_getchar ();
0767 else {
0768 key_event e;
0769 uint i;
0770
0771 keyboard_8042_next (&e);
0772 for (i=0; i<KEY_EVENT_MAX; i++) {
0773 if (e.keys[i].latest) {
0774 c = e.keys[i].scancode;
0775 if (e.keys[i].release)
0776 c |= 0x80;
0777 break;
0778 }
0779 }
0780 }
0781
0782 unlock_kernel ();
0783
0784 return c;
0785 }
0786
0787
0788 void
0789 _switch_to (uint32 pid)
0790 {
0791
0792
0793
0794
0795
0796
0797
0798 uint32 _waitpid(task_id);
0799 _waitpid(pid);
0800 }
0801
0802
0803
0804
0805 int
0806 _open (char *pathname, int flags)
0807 {
0808 lock_kernel ();
0809
0810 int res = vfs_dir (pathname);
0811 unlock_kernel ();
0812 return res;
0813 }
0814
0815
0816 int
0817 _read (char *pathname, void *buf, int count)
0818 {
0819 lock_kernel ();
0820
0821 int res = vfs_read (pathname, buf, count);
0822 unlock_kernel ();
0823 return res;
0824 }
0825
0826
0827 int
0828 _uname (char *name)
0829 {
0830
0831
0832 memcpy (name, kernel_version, sizeof (kernel_ver));
0833
0834 return 0;
0835 }
0836
0837
0838 uint32
0839 _meminfo (uint32 eax, uint32 edx)
0840 {
0841
0842 int i, j = 0;
0843
0844 uint32 frame;
0845 uint32 pgd;
0846 uint32 *pgd_virt, *ptab1_virt;
0847 uint32 addr;
0848
0849 switch (eax) {
0850 case 0:
0851 for (i = 0; i < mm_limit; i++)
0852 if (BITMAP_TST (mm_table, i))
0853 j++;
0854
0855 return j << 12;
0856 case 1:{
0857 void *virt;
0858
0859 frame = alloc_phys_frame ();
0860 if (frame < 0)
0861 return -1;
0862
0863
0864 virt = map_virtual_page (frame | 3);
0865 memset ((void *) virt, 0, 0x1000);
0866 unmap_virtual_page (virt);
0867 return frame;
0868 }
0869 case 2:{
0870
0871 frame = edx;
0872 if ((frame >> 12) >= mm_limit)
0873
0874 return -1;
0875 if (BITMAP_TST (mm_table, frame >> 12))
0876
0877 return -1;
0878
0879 pgd = (uint32) get_pdbr ();
0880 pgd_virt = map_virtual_page (pgd | 3);
0881 ptab1_virt = map_virtual_page (pgd_virt[0] | 3);
0882
0883 addr = -1;
0884 for (i = 1; i < 1024; i++) {
0885 if ((ptab1_virt[i] & 0x1) == 0) {
0886
0887 ptab1_virt[i] = frame | 7;
0888 addr = i << 12;
0889 break;
0890 }
0891 }
0892 unmap_virtual_page (ptab1_virt);
0893 unmap_virtual_page (pgd_virt);
0894 return addr;
0895 }
0896 case 3:{
0897
0898 i = (edx >> 12) & 0x3FF;
0899 pgd = (uint32) get_pdbr ();
0900 pgd_virt = map_virtual_page (pgd | 3);
0901 ptab1_virt = map_virtual_page (pgd_virt[0] | 3);
0902 ptab1_virt[i] = 0;
0903 unmap_virtual_page (ptab1_virt);
0904 unmap_virtual_page (pgd_virt);
0905 return 0;
0906 }
0907 case 4:{
0908
0909 frame = edx;
0910
0911 BITMAP_SET (mm_table, frame >> 12);
0912 return 0;
0913 }
0914 default:
0915 return -1;
0916 }
0917 }
0918
0919
0920 uint32
0921 _time (void)
0922 {
0923
0924 return tick;
0925 }
0926
0927
0928 extern uint32
0929 _interrupt29 (void)
0930 {
0931 extern ACPI_OSD_HANDLER acpi_service_routine;
0932 extern void *acpi_service_routine_context;
0933 if (acpi_service_routine)
0934 return acpi_service_routine (acpi_service_routine_context);
0935 else
0936 return 0;
0937 }
0938
0939
0940
0941 extern void
0942 _interrupt3e (void)
0943 {
0944 uint8 phys_id = get_pcpu_id ();
0945 send_eoi ();
0946 LAPIC_start_timer (cpu_bus_freq / QUANTUM_HZ);
0947
0948 lock_kernel ();
0949
0950 if (str () != idleTSS_selector[phys_id]) {
0951
0952
0953 wakeup (str ());
0954 }
0955
0956
0957 schedule ();
0958 unlock_kernel ();
0959 }
0960
0961
0962
0963 void
0964 _timer (void)
0965 {
0966 void begin_kernel_threads (void);
0967 extern volatile bool mp_enabled;
0968 extern bool mp_ISA_PC;
0969 void net_tmr_process (void);
0970
0971 #ifdef DEBUG_PIT
0972 com1_printf ("tick: %u\n", tick);
0973 #endif
0974
0975 tick++;
0976
0977
0978
0979 send_eoi ();
0980
0981 if (mp_enabled) {
0982 lock_kernel ();
0983
0984
0985 process_sleepqueue ();
0986
0987 #if 1
0988 extern void vcpu_dump_stats (void);
0989 if ((tick & 0x1FF) == 0)
0990 vcpu_dump_stats ();
0991 #endif
0992
0993 unlock_kernel ();
0994
0995 #ifdef GDBSTUB_TCP
0996 {
0997 extern bool break_requested;
0998 if (break_requested) {
0999 break_requested = FALSE;
1000 BREAKPOINT ();
1001 }
1002 }
1003 #endif
1004 #if 0
1005 {
1006 void umsc_tmr_test (void);
1007 umsc_tmr_test ();
1008 }
1009 #endif
1010 }
1011
1012 if (!mp_ISA_PC) {
1013 if (!mp_enabled)
1014 com1_printf ("timer: enabling scheduling\n");
1015 mp_enabled = 1;
1016 begin_kernel_threads ();
1017 } else {
1018 begin_kernel_threads ();
1019
1020 if (str () == idleTSS_selector[0]) {
1021
1022 schedule ();
1023
1024 return;
1025 } else {
1026
1027 wakeup (str ());
1028
1029 schedule ();
1030 }
1031 }
1032 }
1033
1034
1035 void
1036 __exit (int status)
1037 {
1038
1039 void *phys_addr;
1040 uint32 *virt_addr;
1041 uint32 *tmp_page;
1042 int i, j;
1043 task_id tss;
1044 descriptor *ad = (descriptor *) KERN_GDT;
1045 uint32 *kern_page_table = (uint32 *) KERN_PGT;
1046 quest_tss *ptss;
1047 int waiter;
1048
1049 lock_kernel ();
1050
1051
1052
1053
1054
1055 phys_addr = get_pdbr ();
1056 virt_addr = map_virtual_page ((uint32) phys_addr | 3);
1057
1058
1059 for (i = 0; i < 1023; i++) {
1060 if (virt_addr[i]
1061 &&!(virt_addr[i] & 0x80)) {
1062 tmp_page = map_virtual_page (virt_addr[i] | 3);
1063 for (j = 0; j < 1024; j++) {
1064 if (tmp_page[j]) {
1065 if ((j < 0x200) || (j > 0x20F) || i) {
1066
1067 BITMAP_SET (mm_table, tmp_page[j] >> 12);
1068 }
1069 }
1070 }
1071 unmap_virtual_page (tmp_page);
1072 BITMAP_SET (mm_table, virt_addr[i] >> 12);
1073 }
1074 }
1075 BITMAP_SET (mm_table, (uint32) phys_addr >> 12);
1076 unmap_virtual_page (virt_addr);
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087 tss = str ();
1088 ltr (0);
1089
1090
1091
1092 ptss = lookup_TSS (tss);
1093
1094
1095 while ((waiter = queue_remove_head (&ptss->waitqueue)))
1096 wakeup (waiter);
1097
1098 BITMAP_SET (mm_table,
1099 kern_page_table[((uint32) ptss >> 12) & 0x3FF] >> 12);
1100
1101
1102 memset (ad + (tss >> 3), 0, sizeof (descriptor));
1103
1104 unmap_virtual_page (ptss);
1105
1106 schedule ();
1107
1108 panic ("__exit: unreachable");
1109 }
1110
1111
1112 extern uint32
1113 _waitpid (task_id pid)
1114 {
1115
1116 quest_tss *ptss;
1117
1118 lock_kernel ();
1119
1120 ptss = lookup_TSS (pid);
1121
1122 if (ptss) {
1123
1124
1125 queue_append (&ptss->waitqueue, str ());
1126
1127 schedule ();
1128 unlock_kernel ();
1129
1130 return 0;
1131 } else {
1132 unlock_kernel ();
1133
1134 return -1;
1135 }
1136 }
1137
1138
1139 extern int
1140 _sched_setparam (task_id pid, const struct sched_param *p)
1141 {
1142
1143 quest_tss *ptss;
1144
1145 lock_kernel ();
1146
1147 ptss = lookup_TSS (pid);
1148
1149 if (ptss) {
1150 if (p->sched_priority == -1)
1151 ptss->priority = (p->k * p->T) / p->m;
1152 else
1153 ptss->priority = p->sched_priority;
1154
1155 wakeup (str ());
1156
1157 schedule ();
1158 unlock_kernel ();
1159
1160 return 0;
1161
1162 } else
1163 unlock_kernel ();
1164
1165 return -1;
1166 }
1167
1168 #if 0
1169 static void *tlb_shootdown_page = NULL;
1170 static uint32 tlb_shootdown_count = 0;
1171 static spinlock tlb_shootdown_lock = SPINLOCK_INIT;
1172
1173 extern void
1174 invlpg_shootdown (void *va)
1175 {
1176
1177 invalidate_page (va);
1178 send_ipi (0xFF,
1179 LAPIC_ICR_LEVELASSERT |
1180 LAPIC_ICR_DS_ALLEX | LAPIC_ICR_DM_LOGICAL | 0xfd);
1181
1182 }
1183
1184 extern uint32
1185 invlpg_handler (uint8 vec)
1186 {
1187 asm volatile ("invlpg %0"::"m" (*(char *) tlb_shootdown_page));
1188 asm volatile ("lock decl %0"::"m" (tlb_shootdown_count));
1189 return 0;
1190 }
1191
1192 extern uint32
1193 flush_tlb_handler (uint8 vec)
1194 {
1195 asm volatile ("movl %%cr3, %%eax\n"
1196 "movl %%eax, %%cr3\n"
1197 "lock decl %0"::"m" (tlb_shootdown_count));
1198 return 0;
1199 }
1200
1201 #endif
1202
1203
1204 extern void
1205 init_interrupt_handlers (void)
1206 {
1207 int i;
1208 for (i = 0; i < 256; i++)
1209 vector_handlers[i] = default_vector_handler;
1210
1211
1212
1213
1214 }
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225