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