diff --git a/headers/private/kernel/arch/x86/32/descriptors.h b/headers/private/kernel/arch/x86/32/descriptors.h index e09b849e3a..3bdc8c3310 100644 --- a/headers/private/kernel/arch/x86/32/descriptors.h +++ b/headers/private/kernel/arch/x86/32/descriptors.h @@ -9,30 +9,40 @@ #define _KERNEL_ARCH_X86_32_DESCRIPTORS_H -#define KERNEL_CODE_SEG 0x8 -#define KERNEL_DATA_SEG 0x10 +// Segments common for all CPUs. +#define KERNEL_CODE_SEGMENT 1 +#define KERNEL_DATA_SEGMENT 2 -#define USER_CODE_SEG 0x1b -#define USER_DATA_SEG 0x23 +#define USER_CODE_SEGMENT 3 +#define USER_DATA_SEGMENT 4 -#define APM_CODE32_SEGMENT 0x28 -#define APM_CODE16_SEGMENT 0x30 -#define APM_DATA_SEGMENT 0x38 +#define APM_CODE32_SEGMENT 5 +#define APM_CODE16_SEGMENT 6 +#define APM_DATA_SEGMENT 7 -#define BIOS_DATA_SEGMENT 0x40 +#define BIOS_DATA_SEGMENT 8 + +// Per-CPU segments. +#define TSS_SEGMENT 9 +#define DOUBLE_FAULT_TSS_SEGMENT 10 +#define KERNEL_TLS_SEGMENT 11 +#define USER_TLS_SEGMENT 12 +#define APM_SEGMENT 13 + +#define GDT_SEGMENT_COUNT 14 + + +#define KERNEL_CODE_SELECTOR ((KERNEL_CODE_SEGMENT << 3) | DPL_KERNEL) +#define KERNEL_DATA_SELECTOR ((KERNEL_DATA_SEGMENT << 3) | DPL_KERNEL) + +#define USER_CODE_SELECTOR ((USER_CODE_SEGMENT << 3) | DPL_USER) +#define USER_DATA_SELECTOR ((USER_DATA_SEGMENT << 3) | DPL_USER) #ifndef _ASSEMBLER // this file can also be included from assembler as well // (and is in arch_interrupts.S) -#define DOUBLE_FAULT_TSS_BASE_SEGMENT 9 -#define TSS_BASE_SEGMENT (DOUBLE_FAULT_TSS_BASE_SEGMENT + smp_get_num_cpus()) -#define TLS_BASE_SEGMENT (TSS_BASE_SEGMENT + smp_get_num_cpus()) -#define APM_BASE_SEGMENT (TLS_BASE_SEGMENT + smp_get_num_cpus()) - -#define TSS_SEGMENT(cpu) (TSS_BASE_SEGMENT + cpu) - // defines entries in the GDT/LDT struct segment_descriptor { @@ -73,6 +83,9 @@ struct tss { uint16 io_map_base; }; +typedef segment_descriptor global_descriptor_table[GDT_SEGMENT_COUNT]; +extern global_descriptor_table gGDTs[]; + static inline void clear_segment_descriptor(segment_descriptor* desc) @@ -141,6 +154,13 @@ set_tss_descriptor(segment_descriptor* desc, addr_t base, uint32 limit) } +static inline segment_descriptor* +get_gdt(int32 cpu) +{ + return gGDTs[cpu]; +} + + #endif /* _ASSEMBLER */ #endif /* _KERNEL_ARCH_X86_32_DESCRIPTORS_H */ diff --git a/headers/private/kernel/arch/x86/32/iframe.h b/headers/private/kernel/arch/x86/32/iframe.h index 47c423826f..8362b75d83 100644 --- a/headers/private/kernel/arch/x86/32/iframe.h +++ b/headers/private/kernel/arch/x86/32/iframe.h @@ -37,7 +37,7 @@ struct iframe { uint32 user_ss; }; -#define IFRAME_IS_USER(f) ((f)->cs == USER_CODE_SEG \ +#define IFRAME_IS_USER(f) ((f)->cs == USER_CODE_SELECTOR \ || ((f)->flags & 0x20000) != 0) diff --git a/headers/private/kernel/arch/x86/64/descriptors.h b/headers/private/kernel/arch/x86/64/descriptors.h index 3f05196586..fc9e5d0177 100644 --- a/headers/private/kernel/arch/x86/64/descriptors.h +++ b/headers/private/kernel/arch/x86/64/descriptors.h @@ -8,19 +8,28 @@ // Segment definitions. // Note that the ordering of these is important to SYSCALL/SYSRET. -#define KERNEL_CODE_SEG 0x08 -#define KERNEL_DATA_SEG 0x10 -#define USER_DATA_SEG 0x1b -#define USER_CODE_SEG 0x23 +#define KERNEL_CODE_SEGMENT 1 +#define KERNEL_DATA_SEGMENT 2 +#define USER_DATA_SEGMENT 3 +#define USER_CODE_SEGMENT 4 + +#define TSS_BASE_SEGMENT 5 + +#define TSS_SEGMENT(cpu) (TSS_BASE_SEGMENT + cpu * 2) + +#define GDT_SEGMENT_COUNT (TSS_BASE_SEGMENT + SMP_MAX_CPUS * 2) + + +#define KERNEL_CODE_SELECTOR ((KERNEL_CODE_SEGMENT << 3) | DPL_KERNEL) +#define KERNEL_DATA_SELECTOR ((KERNEL_DATA_SEGMENT << 3) | DPL_KERNEL) + +#define USER_CODE_SELECTOR ((USER_CODE_SEGMENT << 3) | DPL_USER) +#define USER_DATA_SELECTOR ((USER_DATA_SEGMENT << 3) | DPL_USER) #ifndef _ASSEMBLER -#define TSS_BASE_SEGMENT 5 -#define TSS_SEGMENT(cpu) (TSS_BASE_SEGMENT + cpu * 2) - - // Structure of a segment descriptor. struct segment_descriptor { uint32 limit0 : 16; diff --git a/headers/private/kernel/arch/x86/arch_cpu.h b/headers/private/kernel/arch/x86/arch_cpu.h index 502b33b6c2..516b5fc52d 100644 --- a/headers/private/kernel/arch/x86/arch_cpu.h +++ b/headers/private/kernel/arch/x86/arch_cpu.h @@ -335,6 +335,7 @@ typedef struct arch_cpu_info { struct tss tss; #ifndef __x86_64__ struct tss double_fault_tss; + void* kernel_tls; #endif } arch_cpu_info; diff --git a/headers/private/kernel/arch/x86/descriptors.h b/headers/private/kernel/arch/x86/descriptors.h index 30dc9f657f..5b16ab7754 100644 --- a/headers/private/kernel/arch/x86/descriptors.h +++ b/headers/private/kernel/arch/x86/descriptors.h @@ -9,6 +9,10 @@ #define _KERNEL_ARCH_x86_DESCRIPTORS_H +#define DPL_KERNEL 0 +#define DPL_USER 3 + + #ifndef _ASSEMBLER @@ -18,11 +22,6 @@ struct kernel_args; -enum descriptor_privilege_levels { - DPL_KERNEL = 0, - DPL_USER = 3, -}; - enum descriptor_types { // segment types DT_CODE_EXECUTE_ONLY = 0x8, @@ -48,6 +47,7 @@ enum gate_types { }; +void x86_descriptors_preboot_init_percpu(kernel_args* args, int cpu); void x86_descriptors_init(kernel_args* args); void x86_descriptors_init_percpu(kernel_args* args, int cpu); status_t x86_descriptors_init_post_vm(kernel_args* args); diff --git a/src/system/boot/platform/bios_ia32/interrupts.cpp b/src/system/boot/platform/bios_ia32/interrupts.cpp index 2d5d0fa596..92f6d6f7f9 100644 --- a/src/system/boot/platform/bios_ia32/interrupts.cpp +++ b/src/system/boot/platform/bios_ia32/interrupts.cpp @@ -96,7 +96,8 @@ set_interrupt_gate(int n, void (*function)()) if (n >= DEBUG_IDT_SLOT_COUNT) return; - sDebugIDT[n].a = (KERNEL_CODE_SEG << 16) | (0x0000ffff & (addr_t)function); + sDebugIDT[n].a + = (KERNEL_CODE_SELECTOR << 16) | (0x0000ffff & (addr_t)function); sDebugIDT[n].b = (0xffff0000 & (addr_t)function) | 0x8e00; } diff --git a/src/system/boot/platform/bios_ia32/long.cpp b/src/system/boot/platform/bios_ia32/long.cpp index 3db5220e36..990bcdd546 100644 --- a/src/system/boot/platform/bios_ia32/long.cpp +++ b/src/system/boot/platform/bios_ia32/long.cpp @@ -74,13 +74,13 @@ long_gdt_init() clear_segment_descriptor(&gdt[0]); // Set up code/data segments (TSS segments set up later in the kernel). - set_segment_descriptor(&gdt[KERNEL_CODE_SEG / 8], DT_CODE_EXECUTE_ONLY, + set_segment_descriptor(&gdt[KERNEL_CODE_SEGMENT], DT_CODE_EXECUTE_ONLY, DPL_KERNEL); - set_segment_descriptor(&gdt[KERNEL_DATA_SEG / 8], DT_DATA_WRITEABLE, + set_segment_descriptor(&gdt[KERNEL_DATA_SEGMENT], DT_DATA_WRITEABLE, DPL_KERNEL); - set_segment_descriptor(&gdt[USER_CODE_SEG / 8], DT_CODE_EXECUTE_ONLY, + set_segment_descriptor(&gdt[USER_CODE_SEGMENT], DT_CODE_EXECUTE_ONLY, DPL_USER); - set_segment_descriptor(&gdt[USER_DATA_SEG / 8], DT_DATA_WRITEABLE, + set_segment_descriptor(&gdt[USER_DATA_SEGMENT], DT_DATA_WRITEABLE, DPL_USER); // Used by long_enter_kernel(). diff --git a/src/system/boot/platform/bios_ia32/long_asm.S b/src/system/boot/platform/bios_ia32/long_asm.S index 72b30c26cf..0ee9b8e9be 100644 --- a/src/system/boot/platform/bios_ia32/long_asm.S +++ b/src/system/boot/platform/bios_ia32/long_asm.S @@ -58,12 +58,12 @@ FUNCTION(long_enter_kernel): movl %ecx, %cr0 // Jump into the 64-bit code segment. - ljmp $KERNEL_CODE_SEG, $.Llmode + ljmp $KERNEL_CODE_SELECTOR, $.Llmode .align 8 .code64 .Llmode: // Set data segments. - mov $KERNEL_DATA_SEG, %ax + mov $KERNEL_DATA_SELECTOR, %ax mov %ax, %ss xor %ax, %ax mov %ax, %ds diff --git a/src/system/boot/platform/bios_ia32/mmu.cpp b/src/system/boot/platform/bios_ia32/mmu.cpp index 93eaed5423..8bfe21ec09 100644 --- a/src/system/boot/platform/bios_ia32/mmu.cpp +++ b/src/system/boot/platform/bios_ia32/mmu.cpp @@ -577,20 +577,20 @@ mmu_init_for_kernel(void) clear_segment_descriptor(&virtualGDT[0]); // seg 0x08 - kernel 4GB code - set_segment_descriptor(&virtualGDT[1], 0, 0xffffffff, DT_CODE_READABLE, - DPL_KERNEL); + set_segment_descriptor(&virtualGDT[KERNEL_CODE_SEGMENT], 0, 0xffffffff, + DT_CODE_READABLE, DPL_KERNEL); // seg 0x10 - kernel 4GB data - set_segment_descriptor(&virtualGDT[2], 0, 0xffffffff, DT_DATA_WRITEABLE, - DPL_KERNEL); + set_segment_descriptor(&virtualGDT[KERNEL_DATA_SEGMENT], 0, 0xffffffff, + DT_DATA_WRITEABLE, DPL_KERNEL); // seg 0x1b - ring 3 user 4GB code - set_segment_descriptor(&virtualGDT[3], 0, 0xffffffff, DT_CODE_READABLE, - DPL_USER); + set_segment_descriptor(&virtualGDT[USER_CODE_SEGMENT], 0, 0xffffffff, + DT_CODE_READABLE, DPL_USER); // seg 0x23 - ring 3 user 4GB data - set_segment_descriptor(&virtualGDT[4], 0, 0xffffffff, DT_DATA_WRITEABLE, - DPL_USER); + set_segment_descriptor(&virtualGDT[USER_DATA_SEGMENT], 0, 0xffffffff, + DT_DATA_WRITEABLE, DPL_USER); // virtualGDT[5] and above will be filled later by the kernel // to contain the TSS descriptors, and for TLS (one for every CPU) diff --git a/src/system/kernel/arch/x86/32/apm.cpp b/src/system/kernel/arch/x86/32/apm.cpp index 1c6b72b178..c5174485da 100644 --- a/src/system/kernel/arch/x86/32/apm.cpp +++ b/src/system/kernel/arch/x86/32/apm.cpp @@ -33,7 +33,6 @@ #define CARRY_FLAG 0x01 -extern segment_descriptor *gGDT; extern void *gDmaAddress; extern addr_t gBiosBase; @@ -314,49 +313,52 @@ apm_init(kernel_args *args) // (the first 640kB are mapped as DMA area in arch_vm_init()). addr_t biosData = (addr_t)gDmaAddress + 0x400; - set_segment_descriptor(&gGDT[BIOS_DATA_SEGMENT >> 3], - biosData, B_PAGE_SIZE - biosData, - DT_DATA_WRITEABLE, DPL_KERNEL); + for (uint32 i = 0; i < args->num_cpus; i++) { + segment_descriptor* gdt = get_gdt(i); - // TODO: test if APM segments really are in the BIOS ROM area (especially the - // data segment) + set_segment_descriptor(&gdt[BIOS_DATA_SEGMENT], biosData, + B_PAGE_SIZE - biosData, DT_DATA_WRITEABLE, DPL_KERNEL); - // Setup APM GDTs + // TODO: test if APM segments really are in the BIOS ROM area + // (especially the data segment) - // We ignore their length, and just set their segments to 64 kB which - // shouldn't cause any headaches + // Setup APM GDTs - set_segment_descriptor(&gGDT[APM_CODE32_SEGMENT >> 3], - gBiosBase + (info.code32_segment_base << 4) - 0xe0000, 0xffff, - DT_CODE_READABLE, DPL_KERNEL); - set_segment_descriptor(&gGDT[APM_CODE16_SEGMENT >> 3], - gBiosBase + (info.code16_segment_base << 4) - 0xe0000, 0xffff, - DT_CODE_READABLE, DPL_KERNEL); - gGDT[APM_CODE16_SEGMENT >> 3].d_b = 0; - // 16-bit segment + // We ignore their length, and just set their segments to 64 kB which + // shouldn't cause any headaches - if ((info.data_segment_base << 4) < 0xe0000) { - // use the BIOS data segment as data segment for APM + set_segment_descriptor(&gdt[APM_CODE32_SEGMENT], + gBiosBase + (info.code32_segment_base << 4) - 0xe0000, 0xffff, + DT_CODE_READABLE, DPL_KERNEL); + set_segment_descriptor(&gdt[APM_CODE16_SEGMENT], + gBiosBase + (info.code16_segment_base << 4) - 0xe0000, 0xffff, + DT_CODE_READABLE, DPL_KERNEL); + gdt[APM_CODE16_SEGMENT].d_b = 0; + // 16-bit segment - if (info.data_segment_length == 0) { - args->platform_args.apm.data_segment_length = B_PAGE_SIZE - - info.data_segment_base; + if ((info.data_segment_base << 4) < 0xe0000) { + // use the BIOS data segment as data segment for APM + + if (info.data_segment_length == 0) { + args->platform_args.apm.data_segment_length = B_PAGE_SIZE + - info.data_segment_base; + } + + set_segment_descriptor(&gdt[APM_DATA_SEGMENT], + (addr_t)gDmaAddress + (info.data_segment_base << 4), + info.data_segment_length, + DT_DATA_WRITEABLE, DPL_KERNEL); + } else { + // use the BIOS area as data segment + set_segment_descriptor(&gdt[APM_DATA_SEGMENT], + gBiosBase + (info.data_segment_base << 4) - 0xe0000, 0xffff, + DT_DATA_WRITEABLE, DPL_KERNEL); } - - set_segment_descriptor(&gGDT[APM_DATA_SEGMENT >> 3], - (addr_t)gDmaAddress + (info.data_segment_base << 4), - info.data_segment_length, - DT_DATA_WRITEABLE, DPL_KERNEL); - } else { - // use the BIOS area as data segment - set_segment_descriptor(&gGDT[APM_DATA_SEGMENT >> 3], - gBiosBase + (info.data_segment_base << 4) - 0xe0000, 0xffff, - DT_DATA_WRITEABLE, DPL_KERNEL); } // setup APM entry point - sAPMBiosEntry.segment = APM_CODE32_SEGMENT; + sAPMBiosEntry.segment = (APM_CODE32_SEGMENT << 3) | DPL_KERNEL; sAPMBiosEntry.offset = info.code32_segment_offset; apm_driver_version(info.version); diff --git a/src/system/kernel/arch/x86/32/descriptors.cpp b/src/system/kernel/arch/x86/32/descriptors.cpp index 53b60e4df8..fef30fa3d4 100644 --- a/src/system/kernel/arch/x86/32/descriptors.cpp +++ b/src/system/kernel/arch/x86/32/descriptors.cpp @@ -1,4 +1,5 @@ /* + * Copyright 2013, Paweł Dziepak, pdziepak@quarnos.org. * Copyright 2008-2011, Michael Lotz, mmlr@mlotz.ch. * Copyright 2010, Clemens Zeidler, haiku@clemens-zeidler.de. * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de. @@ -28,16 +29,20 @@ #include "interrupts.h" -static interrupt_descriptor* sIDTs[SMP_MAX_CPUS]; +#define IDT_GATES_COUNT 256 + + +typedef interrupt_descriptor interrupt_descriptor_table[IDT_GATES_COUNT]; + +global_descriptor_table gGDTs[SMP_MAX_CPUS]; +static interrupt_descriptor_table sIDTs[SMP_MAX_CPUS]; // table with functions handling respective interrupts typedef void interrupt_handler_function(struct iframe* frame); -static const uint32 kInterruptHandlerTableSize = 256; +static const uint32 kInterruptHandlerTableSize = IDT_GATES_COUNT; interrupt_handler_function* gInterruptHandlerTable[kInterruptHandlerTableSize]; -segment_descriptor* gGDT; - /*! Initializes a descriptor in an IDT. */ @@ -47,7 +52,7 @@ set_gate(interrupt_descriptor *gate_addr, addr_t addr, int type, int dpl) unsigned int gate1; // first byte of gate desc unsigned int gate2; // second byte of gate desc - gate1 = (KERNEL_CODE_SEG << 16) | (0x0000ffff & addr); + gate1 = (KERNEL_CODE_SELECTOR << 16) | (0x0000ffff & addr); gate2 = (0xffff0000 & addr) | 0x8000 | (dpl << 13) | (type << 8); gate_addr->a = gate1; @@ -95,9 +100,9 @@ set_task_gate(int32 cpu, int32 n, int32 segment) static void -load_tss(int cpu) +load_tss() { - short seg = (TSS_SEGMENT(cpu) << 3) | DPL_KERNEL; + short seg = (TSS_SEGMENT << 3) | DPL_KERNEL; asm("ltr %%ax" : : "a" (seg)); } @@ -179,304 +184,389 @@ init_double_fault(int cpuNum) size_t stackSize; tss->sp0 = (addr_t)x86_get_double_fault_stack(cpuNum, &stackSize); tss->sp0 += stackSize; - tss->ss0 = KERNEL_DATA_SEG; + tss->ss0 = KERNEL_DATA_SELECTOR; tss->cr3 = x86_read_cr3(); // copy the current cr3 to the double fault cr3 tss->eip = (uint32)&double_fault; - tss->es = KERNEL_DATA_SEG; - tss->cs = KERNEL_CODE_SEG; - tss->ss = KERNEL_DATA_SEG; + tss->es = KERNEL_DATA_SELECTOR; + tss->cs = KERNEL_CODE_SELECTOR; + tss->ss = KERNEL_DATA_SELECTOR; tss->esp = tss->sp0; - tss->ds = KERNEL_DATA_SEG; - tss->fs = KERNEL_DATA_SEG; - tss->gs = KERNEL_DATA_SEG; + tss->ds = KERNEL_DATA_SELECTOR; + tss->fs = KERNEL_DATA_SELECTOR; + tss->gs = KERNEL_DATA_SELECTOR; tss->ldt_seg_selector = 0; tss->io_map_base = sizeof(struct tss); // add TSS descriptor for this new TSS - uint16 tssSegmentDescriptorIndex = DOUBLE_FAULT_TSS_BASE_SEGMENT + cpuNum; - set_tss_descriptor(&gGDT[tssSegmentDescriptorIndex], - (addr_t)tss, sizeof(struct tss)); + set_tss_descriptor(&gGDTs[cpuNum][DOUBLE_FAULT_TSS_SEGMENT], (addr_t)tss, + sizeof(struct tss)); - set_task_gate(cpuNum, 8, tssSegmentDescriptorIndex << 3); + set_task_gate(cpuNum, 8, DOUBLE_FAULT_TSS_SEGMENT << 3); +} + + +static void +load_gdt(int cpu) +{ + struct { + uint16 limit; + void* address; + } _PACKED gdt_descriptor = { + GDT_SEGMENT_COUNT * sizeof(segment_descriptor) - 1, + gGDTs[cpu] + }; + + asm volatile("lgdt %0" : : "m" (gdt_descriptor)); +} + + +static void +init_gdt_percpu(kernel_args* args, int cpu) +{ + STATIC_ASSERT(GDT_SEGMENT_COUNT <= 8192); + + segment_descriptor* gdt = get_gdt(cpu); + + clear_segment_descriptor(&gdt[0]); + + set_segment_descriptor(&gdt[KERNEL_CODE_SEGMENT], 0, addr_t(-1), + DT_CODE_READABLE, DPL_KERNEL); + set_segment_descriptor(&gdt[KERNEL_DATA_SEGMENT], 0, addr_t(-1), + DT_DATA_WRITEABLE, DPL_KERNEL); + + set_segment_descriptor(&gdt[USER_CODE_SEGMENT], 0, addr_t(-1), + DT_CODE_READABLE, DPL_USER); + set_segment_descriptor(&gdt[USER_DATA_SEGMENT], 0, addr_t(-1), + DT_DATA_WRITEABLE, DPL_USER); + + // initialize the regular and double fault tss stored in the per-cpu + // structure + memset(&gCPU[cpu].arch.tss, 0, sizeof(struct tss)); + gCPU[cpu].arch.tss.ss0 = (KERNEL_DATA_SEGMENT << 3) | DPL_KERNEL; + gCPU[cpu].arch.tss.io_map_base = sizeof(struct tss); + + // add TSS descriptor for this new TSS + set_tss_descriptor(&gdt[TSS_SEGMENT], (addr_t)&gCPU[cpu].arch.tss, + sizeof(struct tss)); + + // initialize the double fault tss + init_double_fault(cpu); + + set_segment_descriptor(&gdt[KERNEL_TLS_SEGMENT], + (addr_t)&gCPU[cpu].arch.kernel_tls, sizeof(void*), DT_DATA_WRITEABLE, + DPL_KERNEL); + set_segment_descriptor(&gdt[USER_TLS_SEGMENT], 0, TLS_SIZE, + DT_DATA_WRITEABLE, DPL_USER); + + load_gdt(cpu); + + load_tss(); + + // set kernel TLS segment + asm volatile("movw %0, %%gs" : : "r" (KERNEL_TLS_SEGMENT << 3)); +} + + +static void +load_idt(int cpu) +{ + struct { + uint16 limit; + void* address; + } _PACKED idt_descriptor = { + IDT_GATES_COUNT * sizeof(interrupt_descriptor) - 1, + &sIDTs[cpu] + }; + + asm volatile("lidt %0" : : "m" (idt_descriptor)); +} + + +static void +init_idt_percpu(kernel_args* args, int cpu) +{ + set_interrupt_gate(cpu, 0, &trap0); + set_interrupt_gate(cpu, 1, &trap1); + set_interrupt_gate(cpu, 2, &trap2); + set_trap_gate(cpu, 3, &trap3); + set_interrupt_gate(cpu, 4, &trap4); + set_interrupt_gate(cpu, 5, &trap5); + set_interrupt_gate(cpu, 6, &trap6); + set_interrupt_gate(cpu, 7, &trap7); + // trap8 (double fault) is set in init_double_fault(). + set_interrupt_gate(cpu, 9, &trap9); + set_interrupt_gate(cpu, 10, &trap10); + set_interrupt_gate(cpu, 11, &trap11); + set_interrupt_gate(cpu, 12, &trap12); + set_interrupt_gate(cpu, 13, &trap13); + set_interrupt_gate(cpu, 14, &trap14); + //set_interrupt_gate(cpu, 15, &trap15); + set_interrupt_gate(cpu, 16, &trap16); + set_interrupt_gate(cpu, 17, &trap17); + set_interrupt_gate(cpu, 18, &trap18); + set_interrupt_gate(cpu, 19, &trap19); + + // legacy or ioapic interrupts + set_interrupt_gate(cpu, 32, &trap32); + set_interrupt_gate(cpu, 33, &trap33); + set_interrupt_gate(cpu, 34, &trap34); + set_interrupt_gate(cpu, 35, &trap35); + set_interrupt_gate(cpu, 36, &trap36); + set_interrupt_gate(cpu, 37, &trap37); + set_interrupt_gate(cpu, 38, &trap38); + set_interrupt_gate(cpu, 39, &trap39); + set_interrupt_gate(cpu, 40, &trap40); + set_interrupt_gate(cpu, 41, &trap41); + set_interrupt_gate(cpu, 42, &trap42); + set_interrupt_gate(cpu, 43, &trap43); + set_interrupt_gate(cpu, 44, &trap44); + set_interrupt_gate(cpu, 45, &trap45); + set_interrupt_gate(cpu, 46, &trap46); + set_interrupt_gate(cpu, 47, &trap47); + + // additional ioapic interrupts + set_interrupt_gate(cpu, 48, &trap48); + set_interrupt_gate(cpu, 49, &trap49); + set_interrupt_gate(cpu, 50, &trap50); + set_interrupt_gate(cpu, 51, &trap51); + set_interrupt_gate(cpu, 52, &trap52); + set_interrupt_gate(cpu, 53, &trap53); + set_interrupt_gate(cpu, 54, &trap54); + set_interrupt_gate(cpu, 55, &trap55); + + // configurable msi or msi-x interrupts + set_interrupt_gate(cpu, 56, &trap56); + set_interrupt_gate(cpu, 57, &trap57); + set_interrupt_gate(cpu, 58, &trap58); + set_interrupt_gate(cpu, 59, &trap59); + set_interrupt_gate(cpu, 60, &trap60); + set_interrupt_gate(cpu, 61, &trap61); + set_interrupt_gate(cpu, 62, &trap62); + set_interrupt_gate(cpu, 63, &trap63); + set_interrupt_gate(cpu, 64, &trap64); + set_interrupt_gate(cpu, 65, &trap65); + set_interrupt_gate(cpu, 66, &trap66); + set_interrupt_gate(cpu, 67, &trap67); + set_interrupt_gate(cpu, 68, &trap68); + set_interrupt_gate(cpu, 69, &trap69); + set_interrupt_gate(cpu, 70, &trap70); + set_interrupt_gate(cpu, 71, &trap71); + set_interrupt_gate(cpu, 72, &trap72); + set_interrupt_gate(cpu, 73, &trap73); + set_interrupt_gate(cpu, 74, &trap74); + set_interrupt_gate(cpu, 75, &trap75); + set_interrupt_gate(cpu, 76, &trap76); + set_interrupt_gate(cpu, 77, &trap77); + set_interrupt_gate(cpu, 78, &trap78); + set_interrupt_gate(cpu, 79, &trap79); + set_interrupt_gate(cpu, 80, &trap80); + set_interrupt_gate(cpu, 81, &trap81); + set_interrupt_gate(cpu, 82, &trap82); + set_interrupt_gate(cpu, 83, &trap83); + set_interrupt_gate(cpu, 84, &trap84); + set_interrupt_gate(cpu, 85, &trap85); + set_interrupt_gate(cpu, 86, &trap86); + set_interrupt_gate(cpu, 87, &trap87); + set_interrupt_gate(cpu, 88, &trap88); + set_interrupt_gate(cpu, 89, &trap89); + set_interrupt_gate(cpu, 90, &trap90); + set_interrupt_gate(cpu, 91, &trap91); + set_interrupt_gate(cpu, 92, &trap92); + set_interrupt_gate(cpu, 93, &trap93); + set_interrupt_gate(cpu, 94, &trap94); + set_interrupt_gate(cpu, 95, &trap95); + set_interrupt_gate(cpu, 96, &trap96); + set_interrupt_gate(cpu, 97, &trap97); + + set_trap_gate(cpu, 98, &trap98); // for performance testing only + set_trap_gate(cpu, 99, &trap99); // syscall interrupt + + // configurable msi or msi-x interrupts + set_interrupt_gate(cpu, 100, &trap100); + set_interrupt_gate(cpu, 101, &trap101); + set_interrupt_gate(cpu, 102, &trap102); + set_interrupt_gate(cpu, 103, &trap103); + set_interrupt_gate(cpu, 104, &trap104); + set_interrupt_gate(cpu, 105, &trap105); + set_interrupt_gate(cpu, 106, &trap106); + set_interrupt_gate(cpu, 107, &trap107); + set_interrupt_gate(cpu, 108, &trap108); + set_interrupt_gate(cpu, 109, &trap109); + set_interrupt_gate(cpu, 110, &trap110); + set_interrupt_gate(cpu, 111, &trap111); + set_interrupt_gate(cpu, 112, &trap112); + set_interrupt_gate(cpu, 113, &trap113); + set_interrupt_gate(cpu, 114, &trap114); + set_interrupt_gate(cpu, 115, &trap115); + set_interrupt_gate(cpu, 116, &trap116); + set_interrupt_gate(cpu, 117, &trap117); + set_interrupt_gate(cpu, 118, &trap118); + set_interrupt_gate(cpu, 119, &trap119); + set_interrupt_gate(cpu, 120, &trap120); + set_interrupt_gate(cpu, 121, &trap121); + set_interrupt_gate(cpu, 122, &trap122); + set_interrupt_gate(cpu, 123, &trap123); + set_interrupt_gate(cpu, 124, &trap124); + set_interrupt_gate(cpu, 125, &trap125); + set_interrupt_gate(cpu, 126, &trap126); + set_interrupt_gate(cpu, 127, &trap127); + set_interrupt_gate(cpu, 128, &trap128); + set_interrupt_gate(cpu, 129, &trap129); + set_interrupt_gate(cpu, 130, &trap130); + set_interrupt_gate(cpu, 131, &trap131); + set_interrupt_gate(cpu, 132, &trap132); + set_interrupt_gate(cpu, 133, &trap133); + set_interrupt_gate(cpu, 134, &trap134); + set_interrupt_gate(cpu, 135, &trap135); + set_interrupt_gate(cpu, 136, &trap136); + set_interrupt_gate(cpu, 137, &trap137); + set_interrupt_gate(cpu, 138, &trap138); + set_interrupt_gate(cpu, 139, &trap139); + set_interrupt_gate(cpu, 140, &trap140); + set_interrupt_gate(cpu, 141, &trap141); + set_interrupt_gate(cpu, 142, &trap142); + set_interrupt_gate(cpu, 143, &trap143); + set_interrupt_gate(cpu, 144, &trap144); + set_interrupt_gate(cpu, 145, &trap145); + set_interrupt_gate(cpu, 146, &trap146); + set_interrupt_gate(cpu, 147, &trap147); + set_interrupt_gate(cpu, 148, &trap148); + set_interrupt_gate(cpu, 149, &trap149); + set_interrupt_gate(cpu, 150, &trap150); + set_interrupt_gate(cpu, 151, &trap151); + set_interrupt_gate(cpu, 152, &trap152); + set_interrupt_gate(cpu, 153, &trap153); + set_interrupt_gate(cpu, 154, &trap154); + set_interrupt_gate(cpu, 155, &trap155); + set_interrupt_gate(cpu, 156, &trap156); + set_interrupt_gate(cpu, 157, &trap157); + set_interrupt_gate(cpu, 158, &trap158); + set_interrupt_gate(cpu, 159, &trap159); + set_interrupt_gate(cpu, 160, &trap160); + set_interrupt_gate(cpu, 161, &trap161); + set_interrupt_gate(cpu, 162, &trap162); + set_interrupt_gate(cpu, 163, &trap163); + set_interrupt_gate(cpu, 164, &trap164); + set_interrupt_gate(cpu, 165, &trap165); + set_interrupt_gate(cpu, 166, &trap166); + set_interrupt_gate(cpu, 167, &trap167); + set_interrupt_gate(cpu, 168, &trap168); + set_interrupt_gate(cpu, 169, &trap169); + set_interrupt_gate(cpu, 170, &trap170); + set_interrupt_gate(cpu, 171, &trap171); + set_interrupt_gate(cpu, 172, &trap172); + set_interrupt_gate(cpu, 173, &trap173); + set_interrupt_gate(cpu, 174, &trap174); + set_interrupt_gate(cpu, 175, &trap175); + set_interrupt_gate(cpu, 176, &trap176); + set_interrupt_gate(cpu, 177, &trap177); + set_interrupt_gate(cpu, 178, &trap178); + set_interrupt_gate(cpu, 179, &trap179); + set_interrupt_gate(cpu, 180, &trap180); + set_interrupt_gate(cpu, 181, &trap181); + set_interrupt_gate(cpu, 182, &trap182); + set_interrupt_gate(cpu, 183, &trap183); + set_interrupt_gate(cpu, 184, &trap184); + set_interrupt_gate(cpu, 185, &trap185); + set_interrupt_gate(cpu, 186, &trap186); + set_interrupt_gate(cpu, 187, &trap187); + set_interrupt_gate(cpu, 188, &trap188); + set_interrupt_gate(cpu, 189, &trap189); + set_interrupt_gate(cpu, 190, &trap190); + set_interrupt_gate(cpu, 191, &trap191); + set_interrupt_gate(cpu, 192, &trap192); + set_interrupt_gate(cpu, 193, &trap193); + set_interrupt_gate(cpu, 194, &trap194); + set_interrupt_gate(cpu, 195, &trap195); + set_interrupt_gate(cpu, 196, &trap196); + set_interrupt_gate(cpu, 197, &trap197); + set_interrupt_gate(cpu, 198, &trap198); + set_interrupt_gate(cpu, 199, &trap199); + set_interrupt_gate(cpu, 200, &trap200); + set_interrupt_gate(cpu, 201, &trap201); + set_interrupt_gate(cpu, 202, &trap202); + set_interrupt_gate(cpu, 203, &trap203); + set_interrupt_gate(cpu, 204, &trap204); + set_interrupt_gate(cpu, 205, &trap205); + set_interrupt_gate(cpu, 206, &trap206); + set_interrupt_gate(cpu, 207, &trap207); + set_interrupt_gate(cpu, 208, &trap208); + set_interrupt_gate(cpu, 209, &trap209); + set_interrupt_gate(cpu, 210, &trap210); + set_interrupt_gate(cpu, 211, &trap211); + set_interrupt_gate(cpu, 212, &trap212); + set_interrupt_gate(cpu, 213, &trap213); + set_interrupt_gate(cpu, 214, &trap214); + set_interrupt_gate(cpu, 215, &trap215); + set_interrupt_gate(cpu, 216, &trap216); + set_interrupt_gate(cpu, 217, &trap217); + set_interrupt_gate(cpu, 218, &trap218); + set_interrupt_gate(cpu, 219, &trap219); + set_interrupt_gate(cpu, 220, &trap220); + set_interrupt_gate(cpu, 221, &trap221); + set_interrupt_gate(cpu, 222, &trap222); + set_interrupt_gate(cpu, 223, &trap223); + set_interrupt_gate(cpu, 224, &trap224); + set_interrupt_gate(cpu, 225, &trap225); + set_interrupt_gate(cpu, 226, &trap226); + set_interrupt_gate(cpu, 227, &trap227); + set_interrupt_gate(cpu, 228, &trap228); + set_interrupt_gate(cpu, 229, &trap229); + set_interrupt_gate(cpu, 230, &trap230); + set_interrupt_gate(cpu, 231, &trap231); + set_interrupt_gate(cpu, 232, &trap232); + set_interrupt_gate(cpu, 233, &trap233); + set_interrupt_gate(cpu, 234, &trap234); + set_interrupt_gate(cpu, 235, &trap235); + set_interrupt_gate(cpu, 236, &trap236); + set_interrupt_gate(cpu, 237, &trap237); + set_interrupt_gate(cpu, 238, &trap238); + set_interrupt_gate(cpu, 239, &trap239); + set_interrupt_gate(cpu, 240, &trap240); + set_interrupt_gate(cpu, 241, &trap241); + set_interrupt_gate(cpu, 242, &trap242); + set_interrupt_gate(cpu, 243, &trap243); + set_interrupt_gate(cpu, 244, &trap244); + set_interrupt_gate(cpu, 245, &trap245); + set_interrupt_gate(cpu, 246, &trap246); + set_interrupt_gate(cpu, 247, &trap247); + set_interrupt_gate(cpu, 248, &trap248); + set_interrupt_gate(cpu, 249, &trap249); + set_interrupt_gate(cpu, 250, &trap250); + + // smp / apic local interrupts + set_interrupt_gate(cpu, 251, &trap251); + set_interrupt_gate(cpu, 252, &trap252); + set_interrupt_gate(cpu, 253, &trap253); + set_interrupt_gate(cpu, 254, &trap254); + set_interrupt_gate(cpu, 255, &trap255); + + load_idt(cpu); } // #pragma mark - +void +x86_descriptors_preboot_init_percpu(kernel_args* args, int cpu) +{ + init_idt_percpu(args, cpu); + init_gdt_percpu(args, cpu); +} + + void x86_descriptors_init(kernel_args* args) { - uint32 i; - interrupt_handler_function** table; - - // Get the GDT and boot CPU IDT set up by the boot loader. - gGDT = (segment_descriptor*)args->arch_args.vir_gdt; - sIDTs[0] = (interrupt_descriptor *)(addr_t)args->arch_args.vir_idt; - - set_interrupt_gate(0, 0, &trap0); - set_interrupt_gate(0, 1, &trap1); - set_interrupt_gate(0, 2, &trap2); - set_trap_gate(0, 3, &trap3); - set_interrupt_gate(0, 4, &trap4); - set_interrupt_gate(0, 5, &trap5); - set_interrupt_gate(0, 6, &trap6); - set_interrupt_gate(0, 7, &trap7); - // trap8 (double fault) is set in init_double_fault(). - set_interrupt_gate(0, 9, &trap9); - set_interrupt_gate(0, 10, &trap10); - set_interrupt_gate(0, 11, &trap11); - set_interrupt_gate(0, 12, &trap12); - set_interrupt_gate(0, 13, &trap13); - set_interrupt_gate(0, 14, &trap14); -// set_interrupt_gate(0, 15, &trap15); - set_interrupt_gate(0, 16, &trap16); - set_interrupt_gate(0, 17, &trap17); - set_interrupt_gate(0, 18, &trap18); - set_interrupt_gate(0, 19, &trap19); - - // legacy or ioapic interrupts - set_interrupt_gate(0, 32, &trap32); - set_interrupt_gate(0, 33, &trap33); - set_interrupt_gate(0, 34, &trap34); - set_interrupt_gate(0, 35, &trap35); - set_interrupt_gate(0, 36, &trap36); - set_interrupt_gate(0, 37, &trap37); - set_interrupt_gate(0, 38, &trap38); - set_interrupt_gate(0, 39, &trap39); - set_interrupt_gate(0, 40, &trap40); - set_interrupt_gate(0, 41, &trap41); - set_interrupt_gate(0, 42, &trap42); - set_interrupt_gate(0, 43, &trap43); - set_interrupt_gate(0, 44, &trap44); - set_interrupt_gate(0, 45, &trap45); - set_interrupt_gate(0, 46, &trap46); - set_interrupt_gate(0, 47, &trap47); - - // additional ioapic interrupts - set_interrupt_gate(0, 48, &trap48); - set_interrupt_gate(0, 49, &trap49); - set_interrupt_gate(0, 50, &trap50); - set_interrupt_gate(0, 51, &trap51); - set_interrupt_gate(0, 52, &trap52); - set_interrupt_gate(0, 53, &trap53); - set_interrupt_gate(0, 54, &trap54); - set_interrupt_gate(0, 55, &trap55); - - // configurable msi or msi-x interrupts - set_interrupt_gate(0, 56, &trap56); - set_interrupt_gate(0, 57, &trap57); - set_interrupt_gate(0, 58, &trap58); - set_interrupt_gate(0, 59, &trap59); - set_interrupt_gate(0, 60, &trap60); - set_interrupt_gate(0, 61, &trap61); - set_interrupt_gate(0, 62, &trap62); - set_interrupt_gate(0, 63, &trap63); - set_interrupt_gate(0, 64, &trap64); - set_interrupt_gate(0, 65, &trap65); - set_interrupt_gate(0, 66, &trap66); - set_interrupt_gate(0, 67, &trap67); - set_interrupt_gate(0, 68, &trap68); - set_interrupt_gate(0, 69, &trap69); - set_interrupt_gate(0, 70, &trap70); - set_interrupt_gate(0, 71, &trap71); - set_interrupt_gate(0, 72, &trap72); - set_interrupt_gate(0, 73, &trap73); - set_interrupt_gate(0, 74, &trap74); - set_interrupt_gate(0, 75, &trap75); - set_interrupt_gate(0, 76, &trap76); - set_interrupt_gate(0, 77, &trap77); - set_interrupt_gate(0, 78, &trap78); - set_interrupt_gate(0, 79, &trap79); - set_interrupt_gate(0, 80, &trap80); - set_interrupt_gate(0, 81, &trap81); - set_interrupt_gate(0, 82, &trap82); - set_interrupt_gate(0, 83, &trap83); - set_interrupt_gate(0, 84, &trap84); - set_interrupt_gate(0, 85, &trap85); - set_interrupt_gate(0, 86, &trap86); - set_interrupt_gate(0, 87, &trap87); - set_interrupt_gate(0, 88, &trap88); - set_interrupt_gate(0, 89, &trap89); - set_interrupt_gate(0, 90, &trap90); - set_interrupt_gate(0, 91, &trap91); - set_interrupt_gate(0, 92, &trap92); - set_interrupt_gate(0, 93, &trap93); - set_interrupt_gate(0, 94, &trap94); - set_interrupt_gate(0, 95, &trap95); - set_interrupt_gate(0, 96, &trap96); - set_interrupt_gate(0, 97, &trap97); - - set_trap_gate(0, 98, &trap98); // for performance testing only - set_trap_gate(0, 99, &trap99); // syscall interrupt - reserve_io_interrupt_vectors(2, 98, INTERRUPT_TYPE_SYSCALL); - // configurable msi or msi-x interrupts - set_interrupt_gate(0, 100, &trap100); - set_interrupt_gate(0, 101, &trap101); - set_interrupt_gate(0, 102, &trap102); - set_interrupt_gate(0, 103, &trap103); - set_interrupt_gate(0, 104, &trap104); - set_interrupt_gate(0, 105, &trap105); - set_interrupt_gate(0, 106, &trap106); - set_interrupt_gate(0, 107, &trap107); - set_interrupt_gate(0, 108, &trap108); - set_interrupt_gate(0, 109, &trap109); - set_interrupt_gate(0, 110, &trap110); - set_interrupt_gate(0, 111, &trap111); - set_interrupt_gate(0, 112, &trap112); - set_interrupt_gate(0, 113, &trap113); - set_interrupt_gate(0, 114, &trap114); - set_interrupt_gate(0, 115, &trap115); - set_interrupt_gate(0, 116, &trap116); - set_interrupt_gate(0, 117, &trap117); - set_interrupt_gate(0, 118, &trap118); - set_interrupt_gate(0, 119, &trap119); - set_interrupt_gate(0, 120, &trap120); - set_interrupt_gate(0, 121, &trap121); - set_interrupt_gate(0, 122, &trap122); - set_interrupt_gate(0, 123, &trap123); - set_interrupt_gate(0, 124, &trap124); - set_interrupt_gate(0, 125, &trap125); - set_interrupt_gate(0, 126, &trap126); - set_interrupt_gate(0, 127, &trap127); - set_interrupt_gate(0, 128, &trap128); - set_interrupt_gate(0, 129, &trap129); - set_interrupt_gate(0, 130, &trap130); - set_interrupt_gate(0, 131, &trap131); - set_interrupt_gate(0, 132, &trap132); - set_interrupt_gate(0, 133, &trap133); - set_interrupt_gate(0, 134, &trap134); - set_interrupt_gate(0, 135, &trap135); - set_interrupt_gate(0, 136, &trap136); - set_interrupt_gate(0, 137, &trap137); - set_interrupt_gate(0, 138, &trap138); - set_interrupt_gate(0, 139, &trap139); - set_interrupt_gate(0, 140, &trap140); - set_interrupt_gate(0, 141, &trap141); - set_interrupt_gate(0, 142, &trap142); - set_interrupt_gate(0, 143, &trap143); - set_interrupt_gate(0, 144, &trap144); - set_interrupt_gate(0, 145, &trap145); - set_interrupt_gate(0, 146, &trap146); - set_interrupt_gate(0, 147, &trap147); - set_interrupt_gate(0, 148, &trap148); - set_interrupt_gate(0, 149, &trap149); - set_interrupt_gate(0, 150, &trap150); - set_interrupt_gate(0, 151, &trap151); - set_interrupt_gate(0, 152, &trap152); - set_interrupt_gate(0, 153, &trap153); - set_interrupt_gate(0, 154, &trap154); - set_interrupt_gate(0, 155, &trap155); - set_interrupt_gate(0, 156, &trap156); - set_interrupt_gate(0, 157, &trap157); - set_interrupt_gate(0, 158, &trap158); - set_interrupt_gate(0, 159, &trap159); - set_interrupt_gate(0, 160, &trap160); - set_interrupt_gate(0, 161, &trap161); - set_interrupt_gate(0, 162, &trap162); - set_interrupt_gate(0, 163, &trap163); - set_interrupt_gate(0, 164, &trap164); - set_interrupt_gate(0, 165, &trap165); - set_interrupt_gate(0, 166, &trap166); - set_interrupt_gate(0, 167, &trap167); - set_interrupt_gate(0, 168, &trap168); - set_interrupt_gate(0, 169, &trap169); - set_interrupt_gate(0, 170, &trap170); - set_interrupt_gate(0, 171, &trap171); - set_interrupt_gate(0, 172, &trap172); - set_interrupt_gate(0, 173, &trap173); - set_interrupt_gate(0, 174, &trap174); - set_interrupt_gate(0, 175, &trap175); - set_interrupt_gate(0, 176, &trap176); - set_interrupt_gate(0, 177, &trap177); - set_interrupt_gate(0, 178, &trap178); - set_interrupt_gate(0, 179, &trap179); - set_interrupt_gate(0, 180, &trap180); - set_interrupt_gate(0, 181, &trap181); - set_interrupt_gate(0, 182, &trap182); - set_interrupt_gate(0, 183, &trap183); - set_interrupt_gate(0, 184, &trap184); - set_interrupt_gate(0, 185, &trap185); - set_interrupt_gate(0, 186, &trap186); - set_interrupt_gate(0, 187, &trap187); - set_interrupt_gate(0, 188, &trap188); - set_interrupt_gate(0, 189, &trap189); - set_interrupt_gate(0, 190, &trap190); - set_interrupt_gate(0, 191, &trap191); - set_interrupt_gate(0, 192, &trap192); - set_interrupt_gate(0, 193, &trap193); - set_interrupt_gate(0, 194, &trap194); - set_interrupt_gate(0, 195, &trap195); - set_interrupt_gate(0, 196, &trap196); - set_interrupt_gate(0, 197, &trap197); - set_interrupt_gate(0, 198, &trap198); - set_interrupt_gate(0, 199, &trap199); - set_interrupt_gate(0, 200, &trap200); - set_interrupt_gate(0, 201, &trap201); - set_interrupt_gate(0, 202, &trap202); - set_interrupt_gate(0, 203, &trap203); - set_interrupt_gate(0, 204, &trap204); - set_interrupt_gate(0, 205, &trap205); - set_interrupt_gate(0, 206, &trap206); - set_interrupt_gate(0, 207, &trap207); - set_interrupt_gate(0, 208, &trap208); - set_interrupt_gate(0, 209, &trap209); - set_interrupt_gate(0, 210, &trap210); - set_interrupt_gate(0, 211, &trap211); - set_interrupt_gate(0, 212, &trap212); - set_interrupt_gate(0, 213, &trap213); - set_interrupt_gate(0, 214, &trap214); - set_interrupt_gate(0, 215, &trap215); - set_interrupt_gate(0, 216, &trap216); - set_interrupt_gate(0, 217, &trap217); - set_interrupt_gate(0, 218, &trap218); - set_interrupt_gate(0, 219, &trap219); - set_interrupt_gate(0, 220, &trap220); - set_interrupt_gate(0, 221, &trap221); - set_interrupt_gate(0, 222, &trap222); - set_interrupt_gate(0, 223, &trap223); - set_interrupt_gate(0, 224, &trap224); - set_interrupt_gate(0, 225, &trap225); - set_interrupt_gate(0, 226, &trap226); - set_interrupt_gate(0, 227, &trap227); - set_interrupt_gate(0, 228, &trap228); - set_interrupt_gate(0, 229, &trap229); - set_interrupt_gate(0, 230, &trap230); - set_interrupt_gate(0, 231, &trap231); - set_interrupt_gate(0, 232, &trap232); - set_interrupt_gate(0, 233, &trap233); - set_interrupt_gate(0, 234, &trap234); - set_interrupt_gate(0, 235, &trap235); - set_interrupt_gate(0, 236, &trap236); - set_interrupt_gate(0, 237, &trap237); - set_interrupt_gate(0, 238, &trap238); - set_interrupt_gate(0, 239, &trap239); - set_interrupt_gate(0, 240, &trap240); - set_interrupt_gate(0, 241, &trap241); - set_interrupt_gate(0, 242, &trap242); - set_interrupt_gate(0, 243, &trap243); - set_interrupt_gate(0, 244, &trap244); - set_interrupt_gate(0, 245, &trap245); - set_interrupt_gate(0, 246, &trap246); - set_interrupt_gate(0, 247, &trap247); - set_interrupt_gate(0, 248, &trap248); - set_interrupt_gate(0, 249, &trap249); - set_interrupt_gate(0, 250, &trap250); - - // smp / apic local interrupts - set_interrupt_gate(0, 251, &trap251); - set_interrupt_gate(0, 252, &trap252); - set_interrupt_gate(0, 253, &trap253); - set_interrupt_gate(0, 254, &trap254); - set_interrupt_gate(0, 255, &trap255); - // init interrupt handler table - table = gInterruptHandlerTable; + interrupt_handler_function** table = gInterruptHandlerTable; // defaults + uint32 i; for (i = 0; i < ARCH_INTERRUPT_BASE; i++) table[i] = x86_invalid_exception; for (i = ARCH_INTERRUPT_BASE; i < kInterruptHandlerTableSize; i++) @@ -505,90 +595,14 @@ x86_descriptors_init(kernel_args* args) void -x86_descriptors_init_percpu(kernel_args* args, int cpu) +x86_descriptors_init_percpu(kernel_args* /* args */, int /* cpu */) { - // load the TSS for this cpu - // note the main cpu gets initialized in x86_descriptors_init_post_vm() - if (cpu != 0) { - load_tss(cpu); - - // set the IDT - struct { - uint16 limit; - void* address; - } _PACKED descriptor = { - 256 * 8 - 1, // 256 descriptors, 8 bytes each (-1 for "limit") - sIDTs[cpu] - }; - - asm volatile("lidt %0" : : "m"(descriptor)); - } } status_t -x86_descriptors_init_post_vm(kernel_args* args) +x86_descriptors_init_post_vm(kernel_args* /* args */) { - uint32 i; - - // account for the segment descriptors - create_area("gdt", (void **)&gGDT, B_EXACT_ADDRESS, B_PAGE_SIZE, - B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); - - // create IDT area for the boot CPU - area_id area = create_area("idt", (void**)&sIDTs[0], B_EXACT_ADDRESS, - B_PAGE_SIZE, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); - if (area < B_OK) - return area; - - // create IDTs for the off-boot CPU - size_t idtSize = 256 * 8; - // 256 8 bytes-sized descriptors - if (args->num_cpus > 0) { - size_t areaSize = ROUNDUP(args->num_cpus * idtSize, B_PAGE_SIZE); - interrupt_descriptor* idt; - virtual_address_restrictions virtualRestrictions = {}; - virtualRestrictions.address_specification = B_ANY_KERNEL_ADDRESS; - physical_address_restrictions physicalRestrictions = {}; - area = create_area_etc(B_SYSTEM_TEAM, "idt", areaSize, B_CONTIGUOUS, - B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, CREATE_AREA_DONT_WAIT, - 0, &virtualRestrictions, &physicalRestrictions, (void**)&idt); - if (area < 0) - return area; - - for (i = 1; i < args->num_cpus; i++) { - sIDTs[i] = idt; - memcpy(idt, sIDTs[0], idtSize); - idt += 256; - // The CPU's IDTR will be set in arch_cpu_init_percpu(). - } - } - - // setup task-state segments - for (i = 0; i < args->num_cpus; i++) { - // initialize the regular and double fault tss stored in the per-cpu - // structure - memset(&gCPU[i].arch.tss, 0, sizeof(struct tss)); - gCPU[i].arch.tss.ss0 = KERNEL_DATA_SEG; - gCPU[i].arch.tss.io_map_base = sizeof(struct tss); - - // add TSS descriptor for this new TSS - set_tss_descriptor(&gGDT[TSS_SEGMENT(i)], (addr_t)&gCPU[i].arch.tss, - sizeof(struct tss)); - - // initialize the double fault tss - init_double_fault(i); - } - - // set the current hardware task on cpu 0 - load_tss(0); - - // setup TLS descriptors (one for every CPU) - - for (i = 0; i < args->num_cpus; i++) { - set_segment_descriptor(&gGDT[TLS_BASE_SEGMENT + i], 0, TLS_SIZE, - DT_DATA_WRITEABLE, DPL_USER); - } - return B_OK; } + diff --git a/src/system/kernel/arch/x86/32/interrupts.S b/src/system/kernel/arch/x86/32/interrupts.S index 912c583cb9..917ca79cf9 100644 --- a/src/system/kernel/arch/x86/32/interrupts.S +++ b/src/system/kernel/arch/x86/32/interrupts.S @@ -223,7 +223,7 @@ FUNCTION(double_fault): pushl $-1; // user-ss pushl $-1; // user-esp pushl $-1; // flags - pushl $KERNEL_CODE_SEG; // cs + pushl $KERNEL_CODE_SELECTOR // cs pushl $-1; // eip pushl $0; // error-code pushl $8; @@ -516,7 +516,7 @@ STATIC_FUNCTION(int_bottom): // exception. orl $0x10000, IFRAME_flags(%ebp); - cmp $USER_CODE_SEG, IFRAME_cs(%ebp) // user mode + cmpw $USER_CODE_SELECTOR, IFRAME_cs(%ebp) // user mode je int_bottom_user // We need to recheck user mode using the thread's in_kernel flag, since @@ -540,7 +540,7 @@ FUNCTION_END(int_bottom) STATIC_FUNCTION(int_bottom_user): - movl $KERNEL_DATA_SEG,%eax + movl $KERNEL_DATA_SELECTOR, %eax cld movl %eax,%ds movl %eax,%es @@ -564,7 +564,7 @@ STATIC_FUNCTION(int_bottom_user): // were already/still prepared for userland), since the iframe in this case // will be a kernel iframe and e.g. trying to set up a signal stack will not // be a very healthy endeavor. - cmp $USER_CODE_SEG, IFRAME_cs(%ebp) + cmpw $USER_CODE_SELECTOR, IFRAME_cs(%ebp) jne 1f testl $(THREAD_FLAGS_DEBUGGER_INSTALLED | THREAD_FLAGS_SIGNALS_PENDING \ @@ -603,7 +603,7 @@ STATIC_FUNCTION(handle_syscall): // save %eax, the number of the syscall movl %eax, %esi - movl $KERNEL_DATA_SEG,%eax + movl $KERNEL_DATA_SELECTOR, %eax cld movl %eax,%ds movl %eax,%es @@ -759,11 +759,11 @@ FUNCTION(x86_sysenter): movl %dr3, %edx // push the iframe - pushl $USER_DATA_SEG // user_ss + pushl $USER_DATA_SELECTOR // user_ss pushl %ecx // user_esp pushfl // eflags orl $(1 << 9), (%esp) // set the IF (interrupts) bit - pushl $USER_CODE_SEG // user cs + pushl $USER_CODE_SELECTOR // user cs // user_eip movl THREAD_team(%edx), %edx diff --git a/src/system/kernel/arch/x86/32/syscalls.cpp b/src/system/kernel/arch/x86/32/syscalls.cpp index 5b007e61e1..c3ca4e1a24 100644 --- a/src/system/kernel/arch/x86/32/syscalls.cpp +++ b/src/system/kernel/arch/x86/32/syscalls.cpp @@ -55,7 +55,7 @@ set_intel_syscall_stack(addr_t stackTop) static void init_intel_syscall_registers(void* dummy, int cpuNum) { - x86_write_msr(IA32_MSR_SYSENTER_CS, KERNEL_CODE_SEG); + x86_write_msr(IA32_MSR_SYSENTER_CS, KERNEL_CODE_SELECTOR); x86_write_msr(IA32_MSR_SYSENTER_ESP, 0); x86_write_msr(IA32_MSR_SYSENTER_EIP, (addr_t)x86_sysenter); diff --git a/src/system/kernel/arch/x86/32/thread.cpp b/src/system/kernel/arch/x86/32/thread.cpp index 7bed6a0f4d..a62575590b 100644 --- a/src/system/kernel/arch/x86/32/thread.cpp +++ b/src/system/kernel/arch/x86/32/thread.cpp @@ -69,7 +69,6 @@ class RestartSyscall : public AbstractTraceEntry { // from arch_cpu.cpp extern bool gHasSSE; -extern segment_descriptor* gGDT; static struct arch_thread sInitialState _ALIGNED(16); // the fpu_state must be aligned on a 16 byte boundary, so that fxsave can use it @@ -103,10 +102,10 @@ x86_restart_syscall(struct iframe* frame) void x86_set_tls_context(Thread *thread) { - int entry = smp_get_current_cpu() + TLS_BASE_SEGMENT; - - set_segment_descriptor_base(&gGDT[entry], thread->user_local_storage); - set_fs_register((entry << 3) | DPL_USER); + segment_descriptor* gdt = get_gdt(smp_get_current_cpu()); + set_segment_descriptor_base(&gdt[USER_TLS_SEGMENT], + thread->user_local_storage); + set_fs_register((USER_TLS_SEGMENT << 3) | DPL_USER); } @@ -197,7 +196,7 @@ arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, // save the stack position thread->arch_info.current_stack.esp = stackTop; - thread->arch_info.current_stack.ss = (addr_t*)KERNEL_DATA_SEG; + thread->arch_info.current_stack.ss = (addr_t*)KERNEL_DATA_SELECTOR; } @@ -242,16 +241,16 @@ arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, // prepare the user iframe iframe frame = {}; frame.type = IFRAME_TYPE_SYSCALL; - frame.gs = USER_DATA_SEG; + frame.gs = USER_DATA_SELECTOR; // frame.fs not used, we call x86_set_tls_context() on context switch - frame.es = USER_DATA_SEG; - frame.ds = USER_DATA_SEG; + frame.es = USER_DATA_SELECTOR; + frame.ds = USER_DATA_SELECTOR; frame.ip = entry; - frame.cs = USER_CODE_SEG; + frame.cs = USER_CODE_SELECTOR; frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT); frame.user_sp = stackTop; - frame.user_ss = USER_DATA_SEG; + frame.user_ss = USER_DATA_SELECTOR; // return to userland x86_initial_return_to_userland(thread, &frame); diff --git a/src/system/kernel/arch/x86/64/descriptors.cpp b/src/system/kernel/arch/x86/64/descriptors.cpp index 955f96c1e4..3e6878eb64 100644 --- a/src/system/kernel/arch/x86/64/descriptors.cpp +++ b/src/system/kernel/arch/x86/64/descriptors.cpp @@ -60,6 +60,12 @@ x86_64_general_protection_fault(iframe* frame) // #pragma mark - +void +x86_descriptors_preboot_init_percpu(kernel_args* /* args */, int /* cpu */) +{ +} + + void x86_descriptors_init(kernel_args* args) { @@ -83,7 +89,7 @@ x86_descriptors_init(kernel_args* args) uint32 dpl = (i == 3) ? DPL_USER : DPL_KERNEL; set_interrupt_descriptor(&sIDT[i], (addr_t)&isr_array[i], - GATE_INTERRUPT, KERNEL_CODE_SEG, dpl, ist); + GATE_INTERRUPT, KERNEL_CODE_SELECTOR, dpl, ist); } // Initialize the interrupt handler table. diff --git a/src/system/kernel/arch/x86/64/interrupts.S b/src/system/kernel/arch/x86/64/interrupts.S index 71a0d106db..db73a4fba4 100644 --- a/src/system/kernel/arch/x86/64/interrupts.S +++ b/src/system/kernel/arch/x86/64/interrupts.S @@ -302,10 +302,10 @@ FUNCTION(x86_64_syscall_entry): movq %gs:ARCH_THREAD_syscall_rsp, %rsp // Set up an iframe on the stack (R11 = saved RFLAGS, RCX = saved RIP). - push $USER_DATA_SEG // ss + push $USER_DATA_SELECTOR // ss push %gs:ARCH_THREAD_user_rsp // rsp push %r11 // flags - push $USER_CODE_SEG // cs + push $USER_CODE_SELECTOR // cs push %rcx // ip push $0 // error_code push $99 // vector diff --git a/src/system/kernel/arch/x86/64/syscalls.cpp b/src/system/kernel/arch/x86/64/syscalls.cpp index 4407498aa2..174755f5a0 100644 --- a/src/system/kernel/arch/x86/64/syscalls.cpp +++ b/src/system/kernel/arch/x86/64/syscalls.cpp @@ -38,12 +38,12 @@ init_syscall_registers(void* dummy, int cpuNum) // - CS is set to IA32_STAR[63:48] + 16 // - SS is set to IA32_STAR[63:48] + 8 // From this we get: - // - Entry CS = KERNEL_CODE_SEG - // - Entry SS = KERNEL_CODE_SEG + 8 = KERNEL_DATA_SEG - // - Return CS = KERNEL_DATA_SEG + 16 = USER_CODE_SEG - // - Return SS = KERNEL_DATA_SEG + 8 = USER_DATA_SEG - x86_write_msr(IA32_MSR_STAR, ((uint64)(KERNEL_DATA_SEG | 3) << 48) - | ((uint64)KERNEL_CODE_SEG << 32)); + // - Entry CS = KERNEL_CODE_SELECTOR + // - Entry SS = KERNEL_CODE_SELECTOR + 8 = KERNEL_DATA_SELECTOR + // - Return CS = KERNEL_DATA_SELECTOR + 16 = USER_CODE_SELECTOR + // - Return SS = KERNEL_DATA_SELECTOR + 8 = USER_DATA_SLECTORG + x86_write_msr(IA32_MSR_STAR, ((uint64)(KERNEL_DATA_SELECTOR | 3) << 48) + | ((uint64)KERNEL_CODE_SELECTOR << 32)); } diff --git a/src/system/kernel/arch/x86/64/thread.cpp b/src/system/kernel/arch/x86/64/thread.cpp index 59db5028e4..5ee839a711 100644 --- a/src/system/kernel/arch/x86/64/thread.cpp +++ b/src/system/kernel/arch/x86/64/thread.cpp @@ -238,11 +238,11 @@ arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, frame.si = (uint64)args2; frame.di = (uint64)args1; frame.ip = entry; - frame.cs = USER_CODE_SEG; + frame.cs = USER_CODE_SELECTOR; frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT); frame.sp = stackTop; - frame.ss = USER_DATA_SEG; + frame.ss = USER_DATA_SELECTOR; // Return to userland. Never returns. x86_initial_return_to_userland(thread, &frame); diff --git a/src/system/kernel/arch/x86/arch_cpu.cpp b/src/system/kernel/arch/x86/arch_cpu.cpp index 2046f2f176..f4cc5ffba3 100644 --- a/src/system/kernel/arch/x86/arch_cpu.cpp +++ b/src/system/kernel/arch/x86/arch_cpu.cpp @@ -1008,6 +1008,8 @@ arch_cpu_preboot_init_percpu(kernel_args* args, int cpu) x86_write_msr(IA32_MSR_TSC, 0); } + x86_descriptors_preboot_init_percpu(args, cpu); + return B_OK; } @@ -1049,7 +1051,6 @@ detect_amdc1e_noarat() status_t arch_cpu_init_percpu(kernel_args* args, int cpu) { - // Load descriptor tables for this CPU. x86_descriptors_init_percpu(args, cpu); detect_cpu(cpu);