1 /* 2 * Copyright 2008-2011, Michael Lotz, mmlr@mlotz.ch. 3 * Copyright 2010, Clemens Zeidler, haiku@clemens-zeidler.de. 4 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. 5 * Copyright 2002-2010, Axel Dörfler, axeld@pinc-software.de. 6 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. 7 * Distributed under the terms of the MIT License. 8 * 9 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 10 * Distributed under the terms of the NewOS License. 11 */ 12 13 14 #include <arch/x86/descriptors.h> 15 16 #include <stdio.h> 17 18 #include <boot/kernel_args.h> 19 #include <cpu.h> 20 #include <tls.h> 21 #include <vm/vm.h> 22 #include <vm/vm_priv.h> 23 24 #include <arch/int.h> 25 #include <arch/user_debugger.h> 26 27 #include "interrupts.h" 28 29 30 static interrupt_descriptor* sIDTs[B_MAX_CPU_COUNT]; 31 32 // table with functions handling respective interrupts 33 typedef void interrupt_handler_function(struct iframe* frame); 34 35 static const uint32 kInterruptHandlerTableSize = 256; 36 interrupt_handler_function* gInterruptHandlerTable[kInterruptHandlerTableSize]; 37 38 segment_descriptor* gGDT; 39 40 41 /*! Initializes a descriptor in an IDT. 42 */ 43 static void 44 set_gate(interrupt_descriptor *gate_addr, addr_t addr, int type, int dpl) 45 { 46 unsigned int gate1; // first byte of gate desc 47 unsigned int gate2; // second byte of gate desc 48 49 gate1 = (KERNEL_CODE_SEG << 16) | (0x0000ffff & addr); 50 gate2 = (0xffff0000 & addr) | 0x8000 | (dpl << 13) | (type << 8); 51 52 gate_addr->a = gate1; 53 gate_addr->b = gate2; 54 } 55 56 57 /*! Initializes the descriptor for interrupt vector \a n in the IDT of the 58 specified CPU to an interrupt-gate descriptor with the given procedure 59 address. 60 For CPUs other than the boot CPU it must not be called before 61 arch_int_init_post_vm(). 62 */ 63 static void 64 set_interrupt_gate(int32 cpu, int n, void (*addr)()) 65 { 66 set_gate(&sIDTs[cpu][n], (addr_t)addr, 14, DPL_KERNEL); 67 } 68 69 70 /*! Initializes the descriptor for interrupt vector \a n in the IDT of the 71 specified CPU to an trap-gate descriptor with the given procedure address. 72 For CPUs other than the boot CPU it must not be called before 73 arch_int_init_post_vm(). 74 */ 75 static void 76 set_trap_gate(int32 cpu, int n, void (*addr)()) 77 { 78 set_gate(&sIDTs[cpu][n], (unsigned int)addr, 15, DPL_USER); 79 } 80 81 82 /*! Initializes the descriptor for interrupt vector \a n in the IDT of CPU 83 \a cpu to a task-gate descripter referring to the TSS segment identified 84 by TSS segment selector \a segment. 85 For CPUs other than the boot CPU it must not be called before 86 arch_int_init_post_vm() (arch_cpu_init_post_vm() is fine). 87 */ 88 static void 89 set_task_gate(int32 cpu, int32 n, int32 segment) 90 { 91 sIDTs[cpu][n].a = (segment << 16); 92 sIDTs[cpu][n].b = 0x8000 | (0 << 13) | (0x5 << 8); // present, dpl 0, type 5 93 } 94 95 96 static void 97 load_tss(int cpu) 98 { 99 short seg = (TSS_SEGMENT(cpu) << 3) | DPL_KERNEL; 100 asm("ltr %%ax" : : "a" (seg)); 101 } 102 103 104 // #pragma mark - Double fault handling 105 106 107 void 108 x86_double_fault_exception(struct iframe* frame) 109 { 110 int cpu = x86_double_fault_get_cpu(); 111 112 // The double fault iframe contains no useful information (as 113 // per Intel's architecture spec). Thus we simply save the 114 // information from the (unhandlable) exception which caused the 115 // double in our iframe. This will result even in useful stack 116 // traces. Only problem is that we trust that at least the 117 // TSS is still accessible. 118 struct tss *tss = &gCPU[cpu].arch.tss; 119 120 frame->cs = tss->cs; 121 frame->es = tss->es; 122 frame->ds = tss->ds; 123 frame->fs = tss->fs; 124 frame->gs = tss->gs; 125 frame->ip = tss->eip; 126 frame->bp = tss->ebp; 127 frame->sp = tss->esp; 128 frame->ax = tss->eax; 129 frame->bx = tss->ebx; 130 frame->cx = tss->ecx; 131 frame->dx = tss->edx; 132 frame->si = tss->esi; 133 frame->di = tss->edi; 134 frame->flags = tss->eflags; 135 136 // Use a special handler for page faults which avoids the triple fault 137 // pitfalls. 138 set_interrupt_gate(cpu, 14, &trap14_double_fault); 139 140 debug_double_fault(cpu); 141 } 142 143 144 void 145 x86_page_fault_exception_double_fault(struct iframe* frame) 146 { 147 addr_t cr2 = x86_read_cr2(); 148 149 // Only if this CPU has a fault handler, we're allowed to be here. 150 cpu_ent& cpu = gCPU[x86_double_fault_get_cpu()]; 151 addr_t faultHandler = cpu.fault_handler; 152 if (faultHandler != 0) { 153 debug_set_page_fault_info(cr2, frame->ip, 154 (frame->error_code & 0x2) != 0 ? DEBUG_PAGE_FAULT_WRITE : 0); 155 frame->ip = faultHandler; 156 frame->bp = cpu.fault_handler_stack_pointer; 157 return; 158 } 159 160 // No fault handler. This is bad. Since we originally came from a double 161 // fault, we don't try to reenter the kernel debugger. Instead we just 162 // print the info we've got and enter an infinite loop. 163 kprintf("Page fault in double fault debugger without fault handler! " 164 "Touching address %p from eip %p. Entering infinite loop...\n", 165 (void*)cr2, (void*)frame->ip); 166 167 while (true); 168 } 169 170 171 static void 172 init_double_fault(int cpuNum) 173 { 174 // set up the double fault TSS 175 struct tss* tss = &gCPU[cpuNum].arch.double_fault_tss; 176 177 memset(tss, 0, sizeof(struct tss)); 178 size_t stackSize; 179 tss->sp0 = (addr_t)x86_get_double_fault_stack(cpuNum, &stackSize); 180 tss->sp0 += stackSize; 181 tss->ss0 = KERNEL_DATA_SEG; 182 tss->cr3 = x86_read_cr3(); 183 // copy the current cr3 to the double fault cr3 184 tss->eip = (uint32)&double_fault; 185 tss->es = KERNEL_DATA_SEG; 186 tss->cs = KERNEL_CODE_SEG; 187 tss->ss = KERNEL_DATA_SEG; 188 tss->esp = tss->sp0; 189 tss->ds = KERNEL_DATA_SEG; 190 tss->fs = KERNEL_DATA_SEG; 191 tss->gs = KERNEL_DATA_SEG; 192 tss->ldt_seg_selector = 0; 193 tss->io_map_base = sizeof(struct tss); 194 195 // add TSS descriptor for this new TSS 196 uint16 tssSegmentDescriptorIndex = DOUBLE_FAULT_TSS_BASE_SEGMENT + cpuNum; 197 set_tss_descriptor(&gGDT[tssSegmentDescriptorIndex], 198 (addr_t)tss, sizeof(struct tss)); 199 200 set_task_gate(cpuNum, 8, tssSegmentDescriptorIndex << 3); 201 } 202 203 204 // #pragma mark - 205 206 207 void 208 x86_descriptors_init(kernel_args* args) 209 { 210 uint32 i; 211 interrupt_handler_function** table; 212 213 // Get the GDT and boot CPU IDT set up by the boot loader. 214 gGDT = (segment_descriptor*)args->arch_args.vir_gdt; 215 sIDTs[0] = (interrupt_descriptor *)(addr_t)args->arch_args.vir_idt; 216 217 set_interrupt_gate(0, 0, &trap0); 218 set_interrupt_gate(0, 1, &trap1); 219 set_interrupt_gate(0, 2, &trap2); 220 set_trap_gate(0, 3, &trap3); 221 set_interrupt_gate(0, 4, &trap4); 222 set_interrupt_gate(0, 5, &trap5); 223 set_interrupt_gate(0, 6, &trap6); 224 set_interrupt_gate(0, 7, &trap7); 225 // trap8 (double fault) is set in init_double_fault(). 226 set_interrupt_gate(0, 9, &trap9); 227 set_interrupt_gate(0, 10, &trap10); 228 set_interrupt_gate(0, 11, &trap11); 229 set_interrupt_gate(0, 12, &trap12); 230 set_interrupt_gate(0, 13, &trap13); 231 set_interrupt_gate(0, 14, &trap14); 232 // set_interrupt_gate(0, 15, &trap15); 233 set_interrupt_gate(0, 16, &trap16); 234 set_interrupt_gate(0, 17, &trap17); 235 set_interrupt_gate(0, 18, &trap18); 236 set_interrupt_gate(0, 19, &trap19); 237 238 // legacy or ioapic interrupts 239 set_interrupt_gate(0, 32, &trap32); 240 set_interrupt_gate(0, 33, &trap33); 241 set_interrupt_gate(0, 34, &trap34); 242 set_interrupt_gate(0, 35, &trap35); 243 set_interrupt_gate(0, 36, &trap36); 244 set_interrupt_gate(0, 37, &trap37); 245 set_interrupt_gate(0, 38, &trap38); 246 set_interrupt_gate(0, 39, &trap39); 247 set_interrupt_gate(0, 40, &trap40); 248 set_interrupt_gate(0, 41, &trap41); 249 set_interrupt_gate(0, 42, &trap42); 250 set_interrupt_gate(0, 43, &trap43); 251 set_interrupt_gate(0, 44, &trap44); 252 set_interrupt_gate(0, 45, &trap45); 253 set_interrupt_gate(0, 46, &trap46); 254 set_interrupt_gate(0, 47, &trap47); 255 256 // additional ioapic interrupts 257 set_interrupt_gate(0, 48, &trap48); 258 set_interrupt_gate(0, 49, &trap49); 259 set_interrupt_gate(0, 50, &trap50); 260 set_interrupt_gate(0, 51, &trap51); 261 set_interrupt_gate(0, 52, &trap52); 262 set_interrupt_gate(0, 53, &trap53); 263 set_interrupt_gate(0, 54, &trap54); 264 set_interrupt_gate(0, 55, &trap55); 265 266 // configurable msi or msi-x interrupts 267 set_interrupt_gate(0, 56, &trap56); 268 set_interrupt_gate(0, 57, &trap57); 269 set_interrupt_gate(0, 58, &trap58); 270 set_interrupt_gate(0, 59, &trap59); 271 set_interrupt_gate(0, 60, &trap60); 272 set_interrupt_gate(0, 61, &trap61); 273 set_interrupt_gate(0, 62, &trap62); 274 set_interrupt_gate(0, 63, &trap63); 275 set_interrupt_gate(0, 64, &trap64); 276 set_interrupt_gate(0, 65, &trap65); 277 set_interrupt_gate(0, 66, &trap66); 278 set_interrupt_gate(0, 67, &trap67); 279 set_interrupt_gate(0, 68, &trap68); 280 set_interrupt_gate(0, 69, &trap69); 281 set_interrupt_gate(0, 70, &trap70); 282 set_interrupt_gate(0, 71, &trap71); 283 set_interrupt_gate(0, 72, &trap72); 284 set_interrupt_gate(0, 73, &trap73); 285 set_interrupt_gate(0, 74, &trap74); 286 set_interrupt_gate(0, 75, &trap75); 287 set_interrupt_gate(0, 76, &trap76); 288 set_interrupt_gate(0, 77, &trap77); 289 set_interrupt_gate(0, 78, &trap78); 290 set_interrupt_gate(0, 79, &trap79); 291 set_interrupt_gate(0, 80, &trap80); 292 set_interrupt_gate(0, 81, &trap81); 293 set_interrupt_gate(0, 82, &trap82); 294 set_interrupt_gate(0, 83, &trap83); 295 set_interrupt_gate(0, 84, &trap84); 296 set_interrupt_gate(0, 85, &trap85); 297 set_interrupt_gate(0, 86, &trap86); 298 set_interrupt_gate(0, 87, &trap87); 299 set_interrupt_gate(0, 88, &trap88); 300 set_interrupt_gate(0, 89, &trap89); 301 set_interrupt_gate(0, 90, &trap90); 302 set_interrupt_gate(0, 91, &trap91); 303 set_interrupt_gate(0, 92, &trap92); 304 set_interrupt_gate(0, 93, &trap93); 305 set_interrupt_gate(0, 94, &trap94); 306 set_interrupt_gate(0, 95, &trap95); 307 set_interrupt_gate(0, 96, &trap96); 308 set_interrupt_gate(0, 97, &trap97); 309 310 set_trap_gate(0, 98, &trap98); // for performance testing only 311 set_trap_gate(0, 99, &trap99); // syscall interrupt 312 313 reserve_io_interrupt_vectors(2, 98); 314 315 // configurable msi or msi-x interrupts 316 set_interrupt_gate(0, 100, &trap100); 317 set_interrupt_gate(0, 101, &trap101); 318 set_interrupt_gate(0, 102, &trap102); 319 set_interrupt_gate(0, 103, &trap103); 320 set_interrupt_gate(0, 104, &trap104); 321 set_interrupt_gate(0, 105, &trap105); 322 set_interrupt_gate(0, 106, &trap106); 323 set_interrupt_gate(0, 107, &trap107); 324 set_interrupt_gate(0, 108, &trap108); 325 set_interrupt_gate(0, 109, &trap109); 326 set_interrupt_gate(0, 110, &trap110); 327 set_interrupt_gate(0, 111, &trap111); 328 set_interrupt_gate(0, 112, &trap112); 329 set_interrupt_gate(0, 113, &trap113); 330 set_interrupt_gate(0, 114, &trap114); 331 set_interrupt_gate(0, 115, &trap115); 332 set_interrupt_gate(0, 116, &trap116); 333 set_interrupt_gate(0, 117, &trap117); 334 set_interrupt_gate(0, 118, &trap118); 335 set_interrupt_gate(0, 119, &trap119); 336 set_interrupt_gate(0, 120, &trap120); 337 set_interrupt_gate(0, 121, &trap121); 338 set_interrupt_gate(0, 122, &trap122); 339 set_interrupt_gate(0, 123, &trap123); 340 set_interrupt_gate(0, 124, &trap124); 341 set_interrupt_gate(0, 125, &trap125); 342 set_interrupt_gate(0, 126, &trap126); 343 set_interrupt_gate(0, 127, &trap127); 344 set_interrupt_gate(0, 128, &trap128); 345 set_interrupt_gate(0, 129, &trap129); 346 set_interrupt_gate(0, 130, &trap130); 347 set_interrupt_gate(0, 131, &trap131); 348 set_interrupt_gate(0, 132, &trap132); 349 set_interrupt_gate(0, 133, &trap133); 350 set_interrupt_gate(0, 134, &trap134); 351 set_interrupt_gate(0, 135, &trap135); 352 set_interrupt_gate(0, 136, &trap136); 353 set_interrupt_gate(0, 137, &trap137); 354 set_interrupt_gate(0, 138, &trap138); 355 set_interrupt_gate(0, 139, &trap139); 356 set_interrupt_gate(0, 140, &trap140); 357 set_interrupt_gate(0, 141, &trap141); 358 set_interrupt_gate(0, 142, &trap142); 359 set_interrupt_gate(0, 143, &trap143); 360 set_interrupt_gate(0, 144, &trap144); 361 set_interrupt_gate(0, 145, &trap145); 362 set_interrupt_gate(0, 146, &trap146); 363 set_interrupt_gate(0, 147, &trap147); 364 set_interrupt_gate(0, 148, &trap148); 365 set_interrupt_gate(0, 149, &trap149); 366 set_interrupt_gate(0, 150, &trap150); 367 set_interrupt_gate(0, 151, &trap151); 368 set_interrupt_gate(0, 152, &trap152); 369 set_interrupt_gate(0, 153, &trap153); 370 set_interrupt_gate(0, 154, &trap154); 371 set_interrupt_gate(0, 155, &trap155); 372 set_interrupt_gate(0, 156, &trap156); 373 set_interrupt_gate(0, 157, &trap157); 374 set_interrupt_gate(0, 158, &trap158); 375 set_interrupt_gate(0, 159, &trap159); 376 set_interrupt_gate(0, 160, &trap160); 377 set_interrupt_gate(0, 161, &trap161); 378 set_interrupt_gate(0, 162, &trap162); 379 set_interrupt_gate(0, 163, &trap163); 380 set_interrupt_gate(0, 164, &trap164); 381 set_interrupt_gate(0, 165, &trap165); 382 set_interrupt_gate(0, 166, &trap166); 383 set_interrupt_gate(0, 167, &trap167); 384 set_interrupt_gate(0, 168, &trap168); 385 set_interrupt_gate(0, 169, &trap169); 386 set_interrupt_gate(0, 170, &trap170); 387 set_interrupt_gate(0, 171, &trap171); 388 set_interrupt_gate(0, 172, &trap172); 389 set_interrupt_gate(0, 173, &trap173); 390 set_interrupt_gate(0, 174, &trap174); 391 set_interrupt_gate(0, 175, &trap175); 392 set_interrupt_gate(0, 176, &trap176); 393 set_interrupt_gate(0, 177, &trap177); 394 set_interrupt_gate(0, 178, &trap178); 395 set_interrupt_gate(0, 179, &trap179); 396 set_interrupt_gate(0, 180, &trap180); 397 set_interrupt_gate(0, 181, &trap181); 398 set_interrupt_gate(0, 182, &trap182); 399 set_interrupt_gate(0, 183, &trap183); 400 set_interrupt_gate(0, 184, &trap184); 401 set_interrupt_gate(0, 185, &trap185); 402 set_interrupt_gate(0, 186, &trap186); 403 set_interrupt_gate(0, 187, &trap187); 404 set_interrupt_gate(0, 188, &trap188); 405 set_interrupt_gate(0, 189, &trap189); 406 set_interrupt_gate(0, 190, &trap190); 407 set_interrupt_gate(0, 191, &trap191); 408 set_interrupt_gate(0, 192, &trap192); 409 set_interrupt_gate(0, 193, &trap193); 410 set_interrupt_gate(0, 194, &trap194); 411 set_interrupt_gate(0, 195, &trap195); 412 set_interrupt_gate(0, 196, &trap196); 413 set_interrupt_gate(0, 197, &trap197); 414 set_interrupt_gate(0, 198, &trap198); 415 set_interrupt_gate(0, 199, &trap199); 416 set_interrupt_gate(0, 200, &trap200); 417 set_interrupt_gate(0, 201, &trap201); 418 set_interrupt_gate(0, 202, &trap202); 419 set_interrupt_gate(0, 203, &trap203); 420 set_interrupt_gate(0, 204, &trap204); 421 set_interrupt_gate(0, 205, &trap205); 422 set_interrupt_gate(0, 206, &trap206); 423 set_interrupt_gate(0, 207, &trap207); 424 set_interrupt_gate(0, 208, &trap208); 425 set_interrupt_gate(0, 209, &trap209); 426 set_interrupt_gate(0, 210, &trap210); 427 set_interrupt_gate(0, 211, &trap211); 428 set_interrupt_gate(0, 212, &trap212); 429 set_interrupt_gate(0, 213, &trap213); 430 set_interrupt_gate(0, 214, &trap214); 431 set_interrupt_gate(0, 215, &trap215); 432 set_interrupt_gate(0, 216, &trap216); 433 set_interrupt_gate(0, 217, &trap217); 434 set_interrupt_gate(0, 218, &trap218); 435 set_interrupt_gate(0, 219, &trap219); 436 set_interrupt_gate(0, 220, &trap220); 437 set_interrupt_gate(0, 221, &trap221); 438 set_interrupt_gate(0, 222, &trap222); 439 set_interrupt_gate(0, 223, &trap223); 440 set_interrupt_gate(0, 224, &trap224); 441 set_interrupt_gate(0, 225, &trap225); 442 set_interrupt_gate(0, 226, &trap226); 443 set_interrupt_gate(0, 227, &trap227); 444 set_interrupt_gate(0, 228, &trap228); 445 set_interrupt_gate(0, 229, &trap229); 446 set_interrupt_gate(0, 230, &trap230); 447 set_interrupt_gate(0, 231, &trap231); 448 set_interrupt_gate(0, 232, &trap232); 449 set_interrupt_gate(0, 233, &trap233); 450 set_interrupt_gate(0, 234, &trap234); 451 set_interrupt_gate(0, 235, &trap235); 452 set_interrupt_gate(0, 236, &trap236); 453 set_interrupt_gate(0, 237, &trap237); 454 set_interrupt_gate(0, 238, &trap238); 455 set_interrupt_gate(0, 239, &trap239); 456 set_interrupt_gate(0, 240, &trap240); 457 set_interrupt_gate(0, 241, &trap241); 458 set_interrupt_gate(0, 242, &trap242); 459 set_interrupt_gate(0, 243, &trap243); 460 set_interrupt_gate(0, 244, &trap244); 461 set_interrupt_gate(0, 245, &trap245); 462 set_interrupt_gate(0, 246, &trap246); 463 set_interrupt_gate(0, 247, &trap247); 464 set_interrupt_gate(0, 248, &trap248); 465 set_interrupt_gate(0, 249, &trap249); 466 set_interrupt_gate(0, 250, &trap250); 467 468 // smp / apic local interrupts 469 set_interrupt_gate(0, 251, &trap251); 470 set_interrupt_gate(0, 252, &trap252); 471 set_interrupt_gate(0, 253, &trap253); 472 set_interrupt_gate(0, 254, &trap254); 473 set_interrupt_gate(0, 255, &trap255); 474 475 // init interrupt handler table 476 table = gInterruptHandlerTable; 477 478 // defaults 479 for (i = 0; i < ARCH_INTERRUPT_BASE; i++) 480 table[i] = x86_invalid_exception; 481 for (i = ARCH_INTERRUPT_BASE; i < kInterruptHandlerTableSize; i++) 482 table[i] = x86_hardware_interrupt; 483 484 table[0] = x86_unexpected_exception; // Divide Error Exception (#DE) 485 table[1] = x86_handle_debug_exception; // Debug Exception (#DB) 486 table[2] = x86_fatal_exception; // NMI Interrupt 487 table[3] = x86_handle_breakpoint_exception; // Breakpoint Exception (#BP) 488 table[4] = x86_unexpected_exception; // Overflow Exception (#OF) 489 table[5] = x86_unexpected_exception; // BOUND Range Exceeded Exception (#BR) 490 table[6] = x86_unexpected_exception; // Invalid Opcode Exception (#UD) 491 table[7] = x86_fatal_exception; // Device Not Available Exception (#NM) 492 table[8] = x86_double_fault_exception; // Double Fault Exception (#DF) 493 table[9] = x86_fatal_exception; // Coprocessor Segment Overrun 494 table[10] = x86_fatal_exception; // Invalid TSS Exception (#TS) 495 table[11] = x86_fatal_exception; // Segment Not Present (#NP) 496 table[12] = x86_fatal_exception; // Stack Fault Exception (#SS) 497 table[13] = x86_unexpected_exception; // General Protection Exception (#GP) 498 table[14] = x86_page_fault_exception; // Page-Fault Exception (#PF) 499 table[16] = x86_unexpected_exception; // x87 FPU Floating-Point Error (#MF) 500 table[17] = x86_unexpected_exception; // Alignment Check Exception (#AC) 501 table[18] = x86_fatal_exception; // Machine-Check Exception (#MC) 502 table[19] = x86_unexpected_exception; // SIMD Floating-Point Exception (#XF) 503 } 504 505 506 void 507 x86_descriptors_init_percpu(kernel_args* args, int cpu) 508 { 509 // load the TSS for this cpu 510 // note the main cpu gets initialized in x86_descriptors_init_post_vm() 511 if (cpu != 0) { 512 load_tss(cpu); 513 514 // set the IDT 515 struct { 516 uint16 limit; 517 void* address; 518 } _PACKED descriptor = { 519 256 * 8 - 1, // 256 descriptors, 8 bytes each (-1 for "limit") 520 sIDTs[cpu] 521 }; 522 523 asm volatile("lidt %0" : : "m"(descriptor)); 524 } 525 } 526 527 528 status_t 529 x86_descriptors_init_post_vm(kernel_args* args) 530 { 531 uint32 i; 532 533 // account for the segment descriptors 534 create_area("gdt", (void **)&gGDT, B_EXACT_ADDRESS, B_PAGE_SIZE, 535 B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 536 537 // create IDT area for the boot CPU 538 area_id area = create_area("idt", (void**)&sIDTs[0], B_EXACT_ADDRESS, 539 B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 540 if (area < B_OK) 541 return area; 542 543 // create IDTs for the off-boot CPU 544 size_t idtSize = 256 * 8; 545 // 256 8 bytes-sized descriptors 546 if (args->num_cpus > 0) { 547 size_t areaSize = ROUNDUP(args->num_cpus * idtSize, B_PAGE_SIZE); 548 interrupt_descriptor* idt; 549 virtual_address_restrictions virtualRestrictions = {}; 550 virtualRestrictions.address_specification = B_ANY_KERNEL_ADDRESS; 551 physical_address_restrictions physicalRestrictions = {}; 552 area = create_area_etc(B_SYSTEM_TEAM, "idt", areaSize, B_CONTIGUOUS, 553 B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT, 554 &virtualRestrictions, &physicalRestrictions, (void**)&idt); 555 if (area < 0) 556 return area; 557 558 for (i = 1; i < args->num_cpus; i++) { 559 sIDTs[i] = idt; 560 memcpy(idt, sIDTs[0], idtSize); 561 idt += 256; 562 // The CPU's IDTR will be set in arch_cpu_init_percpu(). 563 } 564 } 565 566 // setup task-state segments 567 for (i = 0; i < args->num_cpus; i++) { 568 // initialize the regular and double fault tss stored in the per-cpu 569 // structure 570 memset(&gCPU[i].arch.tss, 0, sizeof(struct tss)); 571 gCPU[i].arch.tss.ss0 = KERNEL_DATA_SEG; 572 gCPU[i].arch.tss.io_map_base = sizeof(struct tss); 573 574 // add TSS descriptor for this new TSS 575 set_tss_descriptor(&gGDT[TSS_SEGMENT(i)], (addr_t)&gCPU[i].arch.tss, 576 sizeof(struct tss)); 577 578 // initialize the double fault tss 579 init_double_fault(i); 580 } 581 582 // set the current hardware task on cpu 0 583 load_tss(0); 584 585 // setup TLS descriptors (one for every CPU) 586 587 for (i = 0; i < args->num_cpus; i++) { 588 set_segment_descriptor(&gGDT[TLS_BASE_SEGMENT + i], 0, TLS_SIZE, 589 DT_DATA_WRITEABLE, DPL_USER); 590 } 591 592 return B_OK; 593 } 594