x86: Let each CPU have its own GDT

This commit is contained in:
Pawel Dziepak
2013-12-17 03:57:20 +01:00
parent 7b9668170c
commit 611376fef7
19 changed files with 522 additions and 469 deletions
@@ -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 */
+1 -1
View File
@@ -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)
@@ -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;
@@ -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;
@@ -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);
@@ -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;
}
+4 -4
View File
@@ -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().
@@ -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
+8 -8
View File
@@ -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)
+35 -33
View File
@@ -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);
+375 -361
View File
@@ -1,4 +1,5 @@
/*
* Copyright 2013, Paweł Dziepak, [email protected].
* Copyright 2008-2011, Michael Lotz, [email protected].
* Copyright 2010, Clemens Zeidler, [email protected].
* Copyright 2009-2011, Ingo Weinhold, [email protected].
@@ -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;
}
+7 -7
View File
@@ -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
+1 -1
View File
@@ -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);
+10 -11
View File
@@ -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);
@@ -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.
+2 -2
View File
@@ -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
+6 -6
View File
@@ -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));
}
+2 -2
View File
@@ -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);
+2 -1
View File
@@ -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);