From 413b46e2f380b5802fd9d25064f0dd2476b1be10 Mon Sep 17 00:00:00 2001 From: Pawel Wieczorkiewicz Date: Mon, 26 Oct 2020 16:28:13 +0100 Subject: [PATCH] rmode: add real mode accessible TSS/TSS_DF structure The real mode GDT will hold descriptors for the TSS and TSS_DF. Signed-off-by: Pawel Wieczorkiewicz --- arch/x86/segment.c | 41 ++++++++++++++++++++++++++++++++++++++ include/arch/x86/segment.h | 3 +++ 2 files changed, 44 insertions(+) diff --git a/arch/x86/segment.c b/arch/x86/segment.c index bdbbb457..565ca0da 100644 --- a/arch/x86/segment.c +++ b/arch/x86/segment.c @@ -56,6 +56,11 @@ idt_ptr_t boot_idt_ptr __data_init = { .addr = _ul(&boot_idt), }; +extern uint8_t *rmode_stack_ist_top; +extern uint8_t *rmode_stack_df_top; + +x86_tss_t __data_rmode rmode_tss __aligned(16); +x86_tss_t __data_rmode rmode_tss_df __aligned(16); gdt_desc_t __data_rmode rmode_gdt[NR_RMODE_GDT_ENTRIES] __aligned(16) = { /* clang-format off */ @@ -151,6 +156,41 @@ void __text_init init_boot_traps(void) { init_boot_tss(); } +static void __text_init init_rmode_tss(void) { +#if defined(__i386__) + rmode_tss_df.iopb = sizeof(rmode_tss_df); + rmode_tss_df.esp0 = _ul(rmode_stack_df_top); + rmode_tss_df.ss = __KERN_DS; + rmode_tss_df.ds = __KERN_DS; + rmode_tss_df.es = __KERN_DS; + rmode_tss_df.fs = __KERN_DS; + rmode_tss_df.gs = __KERN_DS; + rmode_tss_df.eip = _ul(entry_DF); + rmode_tss_df.cs = __KERN_CS; + rmode_tss_df.cr3 = read_cr3(); + + /* Assign identity mapping of the tss_df, because GDT has only 32-bit base. */ + rmode_gdt[GDT_RMODE_TSS_DF].desc = GDT_ENTRY( + DESC_FLAGS(SZ, P, CODE, A), _ul(&rmode_tss_df), sizeof(rmode_tss_df) - 1); + + /* FIXME */ + rmode_tss.esp0 = _ul(rmode_stack_ist_top); + rmode_tss.ss0 = __KERN_DS; + rmode_tss.cr3 = read_cr3(); +#elif defined(__x86_64__) + rmode_tss.rsp0 = _ul(rmode_stack_ist_top); + rmode_tss.ist[0] = _ul(rmode_stack_df_top); +#endif + rmode_tss.iopb = sizeof(rmode_tss); + + /* Assign identity mapping of the tss, because GDT has only 32-bit base. */ + rmode_gdt[GDT_RMODE_TSS].desc = + GDT_ENTRY(DESC_FLAGS(SZ, P, CODE, A), _ul(&rmode_tss), sizeof(rmode_tss) - 1); +#if defined(__x86_64__) + rmode_gdt[GDT_RMODE_TSS + 1].desc = GDT_ENTRY(0x0, 0x0, 0x0); +#endif +} + void __text_init init_rmode_traps(void) { /* clang-format off */ set_intr_gate(&rmode_idt[X86_EX_DE], __KERN_CS, _ul(rmode_exception), GATE_DPL0, GATE_PRESENT, 0); @@ -178,4 +218,5 @@ void __text_init init_rmode_traps(void) { #endif /* clang-format on */ + init_rmode_tss(); } diff --git a/include/arch/x86/segment.h b/include/arch/x86/segment.h index c1e51dea..6deb4ffe 100644 --- a/include/arch/x86/segment.h +++ b/include/arch/x86/segment.h @@ -47,6 +47,9 @@ #define GDT_TSS 0x7 #define GDT_TSS_DF 0x8 +#define GDT_RMODE_TSS 0x6 +#define GDT_RMODE_TSS_DF 0x7 + #define GDT_PERCPU 0x9 #define NR_BOOT_GDT_ENTRIES 6