diff --git a/arch/x86/boot/head.S b/arch/x86/boot/head.S index e30b1734..8c435cdf 100644 --- a/arch/x86/boot/head.S +++ b/arch/x86/boot/head.S @@ -100,5 +100,13 @@ _boot_stack: .skip BOOT_STACK_SIZE GLOBAL(_boot_stack_top) +_boot_stack_ist: + .skip BOOT_STACK_SIZE +GLOBAL(_boot_stack_ist_top) + +_boot_stack_df: + .skip BOOT_STACK_SIZE +GLOBAL(_boot_stack_df_top) + #define XEN_ELFNOTE_PHYS32_ENTRY 18 ELF_NOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .long, _start) diff --git a/arch/x86/boot/segment.c b/arch/x86/boot/segment.c index 307e88b0..24ae3afc 100644 --- a/arch/x86/boot/segment.c +++ b/arch/x86/boot/segment.c @@ -25,9 +25,17 @@ */ #include #include +#include +#include #include -gdt_desc_t boot_gdt[] __aligned(16) __data_init = { +extern uint8_t *_boot_stack_ist_top; +extern uint8_t *_boot_stack_df_top; + +x86_tss_t __data_init boot_tss __aligned(16); +x86_tss_t __data_init boot_tss_df __aligned(16); + +gdt_desc_t __data_init boot_gdt[NR_BOOT_GDT_ENTRIES] __aligned(16) = { /* clang-format off */ [GDT_NULL].desc = GDT_ENTRY(0x0, 0x0, 0x0), [GDT_KERN_CS32].desc = GDT_ENTRY(DESC_FLAGS(GR, SZ, P, DPL0, S, CODE, R, A), 0x0, 0xfffff), @@ -36,7 +44,85 @@ gdt_desc_t boot_gdt[] __aligned(16) __data_init = { /* clang-format on */ }; -gdt_ptr_t boot_gdt_ptr __data_init = { +gdt_ptr_t __data_init boot_gdt_ptr = { .size = sizeof(boot_gdt) - 1, .addr = _ul(&boot_gdt), }; + +idt_entry_t __data_init boot_idt[256]; + +idt_ptr_t boot_idt_ptr __data_init = { + .size = sizeof(boot_idt) - 1, + .addr = _ul(&boot_idt), +}; + +static void __text_init init_boot_tss(void) { +#if defined(__i386__) + boot_tss_df.iopb = sizeof(boot_tss_df); + boot_tss_df.esp0 = _ul(_boot_stack_df_top); + boot_tss_df.ss = __KERN_DS; + boot_tss_df.ds = __KERN_DS; + boot_tss_df.es = __KERN_DS; + boot_tss_df.fs = __KERN_DS; + boot_tss_df.gs = __KERN_DS; + boot_tss_df.eip = _ul(entry_DF); + boot_tss_df.cs = __KERN_CS; + boot_tss_df.cr3 = read_cr3(); + + /* Assign identity mapping of the tss_df, because GDT has only 32-bit base. */ + boot_gdt[GDT_BOOT_TSS_DF].desc = + GDT_ENTRY(DESC_FLAGS(SZ, P, CODE, A), _ul(&boot_tss_df), sizeof(boot_tss_df) - 1); + + /* FIXME */ + boot_tss.esp0 = _ul(_boot_stack_ist_top); + boot_tss.ss0 = __KERN_DS; + boot_tss.cr3 = read_cr3(); +#elif defined(__x86_64__) + boot_tss.rsp0 = _ul(_boot_stack_ist_top); + boot_tss.ist[0] = _ul(_boot_stack_df_top); +#endif + boot_tss.iopb = sizeof(boot_tss); + + /* Assign identity mapping of the tss, because GDT has only 32-bit base. */ + boot_gdt[GDT_BOOT_TSS].desc = + GDT_ENTRY(DESC_FLAGS(SZ, P, CODE, A), _ul(&boot_tss), sizeof(boot_tss) - 1); +#if defined(__x86_64__) + boot_gdt[GDT_BOOT_TSS + 1].desc = GDT_ENTRY(0x0, 0x0, 0x0); +#endif + + barrier(); + ltr(GDT_BOOT_TSS << 3); +} + +void __text_init init_boot_traps(void) { + /* clang-format off */ + set_intr_gate(&boot_idt[X86_EX_DE], __KERN_CS, _ul(entry_DE), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_DB], __KERN_CS, _ul(entry_DB), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_NMI], __KERN_CS, _ul(entry_NMI), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_BP], __KERN_CS, _ul(entry_BP), GATE_DPL3, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_OF], __KERN_CS, _ul(entry_OF), GATE_DPL3, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_BR], __KERN_CS, _ul(entry_BR), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_UD], __KERN_CS, _ul(entry_UD), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_NM], __KERN_CS, _ul(entry_NM), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_CS], __KERN_CS, _ul(entry_CS), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_TS], __KERN_CS, _ul(entry_TS), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_NP], __KERN_CS, _ul(entry_NP), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_SS], __KERN_CS, _ul(entry_SS), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_GP], __KERN_CS, _ul(entry_GP), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_PF], __KERN_CS, _ul(entry_PF), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_MF], __KERN_CS, _ul(entry_MF), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_AC], __KERN_CS, _ul(entry_AC), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_MC], __KERN_CS, _ul(entry_MC), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_XM], __KERN_CS, _ul(entry_XM), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_VE], __KERN_CS, _ul(entry_VE), GATE_DPL0, GATE_PRESENT, 0); + set_intr_gate(&boot_idt[X86_EX_SE], __KERN_CS, _ul(entry_SE), GATE_DPL0, GATE_PRESENT, 0); +#if defined(__x86_64__) + set_intr_gate(&boot_idt[X86_EX_DF], __KERN_CS, _ul(entry_DF), GATE_DPL0, GATE_PRESENT, 1); +#endif + /* clang-format on */ + + barrier(); + lidt(&boot_idt_ptr); + + init_boot_tss(); +} \ No newline at end of file diff --git a/common/setup.c b/common/setup.c index 29a1b895..ae51e17d 100644 --- a/common/setup.c +++ b/common/setup.c @@ -88,6 +88,8 @@ void __noreturn __text_init kernel_start(uint32_t multiboot_magic, /* Initialize console early */ init_console(); + init_boot_traps(); + if (multiboot_magic == MULTIBOOT_BOOTLOADER_MAGIC) { /* Indentity mapping is still on, so fill in multiboot structures */ init_multiboot(mbi, &kernel_cmdline); diff --git a/include/arch/x86/segment.h b/include/arch/x86/segment.h index b98514e9..6afca0b9 100644 --- a/include/arch/x86/segment.h +++ b/include/arch/x86/segment.h @@ -34,6 +34,9 @@ #define GDT_KERN_DS32 0x2 #define GDT_KERN_CS64 0x3 +#define GDT_BOOT_TSS 0x4 +#define GDT_BOOT_TSS_DF 0x5 + #define GDT_USER_CS32 0x4 #define GDT_USER_DS32 0x5 #define GDT_USER_CS64 0x6 @@ -43,7 +46,8 @@ #define GDT_PERCPU 0x9 -#define NR_GDT_ENTRIES 10 +#define NR_BOOT_GDT_ENTRIES 6 +#define NR_GDT_ENTRIES 10 #define __KERN_CS32 (GDT_KERN_CS32 << 3) #define __KERN_DS32 (GDT_KERN_DS32 << 3) diff --git a/include/arch/x86/traps.h b/include/arch/x86/traps.h index fbf395c9..a0b90782 100644 --- a/include/arch/x86/traps.h +++ b/include/arch/x86/traps.h @@ -33,6 +33,7 @@ #ifndef __ASSEMBLY__ extern void init_traps(unsigned int cpu); +extern void init_boot_traps(void); #endif /* __ASSEMBLY__ */ diff --git a/include/setup.h b/include/setup.h index 1994f0c0..153fb2ea 100644 --- a/include/setup.h +++ b/include/setup.h @@ -25,8 +25,6 @@ #ifndef KTF_SETUP_H #define KTF_SETUP_H -#define KERN_STACK_SIZE (5 * PAGE_SIZE) - #ifndef __ASSEMBLY__ #include #include