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);
|
||||
|
||||
Reference in New Issue
Block a user