From c3e5fde3a2df05f7ba1b23e3e38b199bb6ae71e5 Mon Sep 17 00:00:00 2001 From: tkchia Date: Sat, 24 Sep 2022 07:24:02 +0000 Subject: [PATCH] Bare metal: reserve 2 GDT slots for TSS --- ape/ape.S | 25 ++++++++++++++++++------- ape/ape.lds | 3 +++ ape/macros.internal.h | 23 +++++++++++++++++++++++ libc/runtime/pc.internal.h | 1 + 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/ape/ape.S b/ape/ape.S index aada551aa..7728a9fc2 100644 --- a/ape/ape.S +++ b/ape/ape.S @@ -1137,12 +1137,17 @@ sconf: .short 1843200/*hz*/ / 16/*wut*/ / 9600/*baud*/ .endobj sconf,global,hidden // Global Descriptor Table -// -// @note address portion only concern legacy modes .align 8 -gdt: .short 2f-1f # table byte length - .long REAL(1f),0 # table address - .zero 2 +_gdtrphy: + .short 2f-1f-1 # table byte length + .long REAL(1f) # table address (physical space) + .endobj _gdtrphy,global,hidden +_gdtr: + .short 2f-1f-1 # table byte length + .quad 1f # table address (final virtual space) + .endobj _gdtr,global,hidden + .align 8 +_gdt: 1: // ┌G:granularity (1 → limit *= 0x1000) // │┌D/B:default operation size (0 = 16|64bit, 1 = 32-bit) @@ -1172,7 +1177,9 @@ gdt: .short 2f-1f # table byte length .quad 0b0000000011001111100100100000000000000000000000001111111111111111 #32 .quad 0b0000000010101111100110110000000000000000000000001111111111111111 #40 .quad 0b0000000010101111100100110000000000000000000000001111111111111111 #48 -2: .endobj gdt,global,hidden +.tssdescstub _tss #56,64 +2: + .endobj _gdt,global,hidden /*─────────────────────────────────────────────────────────────────────────────╗ │ αcτµαlly pδrταblε εxεcµταblε § real mode │ @@ -1433,7 +1440,7 @@ golong: cli rdmsr or $EFER_LME|EFER_SCE,%eax wrmsr - lgdt REAL(gdt) + lgdt REAL(_gdtrphy) mov %cr0,%eax or $CR0_PE|CR0_PG|CR0_MP,%eax and $~CR0_EM,%eax @@ -1451,6 +1458,8 @@ long: xor %eax,%eax mov %eax,%fs mov %eax,%gs mov $0x80000,%esp + mov $GDT_LONG_TSS,%al + ltr %ax xor %r12d,%r12d xor %r13d,%r13d xor %r14d,%r14d @@ -1464,6 +1473,8 @@ long: xor %eax,%eax call __map_phdrs push $0x037f fldcw (%rsp) + lgdt _gdtr # reload GDTR for + # virtual memory space movabs $kernel,%rax jmp *%rax .endfn long diff --git a/ape/ape.lds b/ape/ape.lds index 05cee5ba1..a756c9340 100644 --- a/ape/ape.lds +++ b/ape/ape.lds @@ -572,6 +572,9 @@ HIDDEN(v_ape_realslacksectors = HIDDEN(v_ape_realpages = v_ape_realsectors / (4096 / 512)); HIDDEN(v_ape_highsectors = (ROUNDUP(RVA(_edata), 512) / 512) - v_ape_realsectors); +PROVIDE_HIDDEN(_tss = 0); +PROVIDE_HIDDEN(_tss_end = 0); +TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0); #endif /* ZIP End of Central Directory header */ diff --git a/ape/macros.internal.h b/ape/macros.internal.h index c17344116..7ba52bafa 100644 --- a/ape/macros.internal.h +++ b/ape/macros.internal.h @@ -180,6 +180,12 @@ .stub \name\()_bcs\n,long .endm +// Task State Segment Descriptor Entries. +.macro .tssdescstub name:req + .stub \name\()_desc_ent0,quad + .stub \name\()_desc_ent1,quad +.endm + /* clang-format on */ #elif defined(__LINKER__) @@ -257,5 +263,22 @@ (X) % 10 * 0x1000000 \ : 0xffffffffffffffff) +/** + * Laying out the GDT entries for a TSS for bare metal operation. + */ +#define TSSDESCSTUB2(SYM, BASE, LIM) \ + HIDDEN(SYM##_desc_ent0 = TSSDESC_ENT0(BASE, LIM)); \ + HIDDEN(SYM##_desc_ent1 = TSSDESC_ENT1(BASE)); \ + ASSERT((LIM) >= 0 && (LIM) <= 0xffff, "bare metal TSS is suspiciously fat") +#define TSSDESC_ENT0(BASE, LIM) \ + (((LIM) << 0 & 0x000000000000ffff) | \ + ((BASE) << 16 & 0x000000ffffff0000) | \ + 0x89 << 40 | \ + ((LIM) >> 16 << 48 & 0x000f000000000000) | \ + 0x2 << 52 | \ + ((BASE) >> 24 << 56 & 0xff00000000000000)) +#define TSSDESC_ENT1(BASE) \ + ((BASE) >> 32 << 0 & 0x00000000ffffffff) + #endif /* __ASSEMBLER__ */ #endif /* APE_MACROS_H_ */ diff --git a/libc/runtime/pc.internal.h b/libc/runtime/pc.internal.h index 45ca8d919..6ff21bfdf 100644 --- a/libc/runtime/pc.internal.h +++ b/libc/runtime/pc.internal.h @@ -120,6 +120,7 @@ #define GDT_LEGACY_DATA 32 #define GDT_LONG_CODE 40 #define GDT_LONG_DATA 48 +#define GDT_LONG_TSS 56 #define PIC1 0x20 /* IO base address for master PIC */ #define PIC2 0xA0 /* IO base address for slave PIC */