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);