x86: Let each CPU have its own GDT
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user