X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fthreads%2Fgdt.c;h=7a6005f2de5c9457e9194721e1891672a0d4e599;hb=c9d103e3fc1f398acb10bbaa66bf5a61318d26e9;hp=2fd6948021e5b83c550d5066747b93a4e4903bf9;hpb=c9c283cb3e26a5b6d918ee47dcf8efe28522b18d;p=pintos-anon diff --git a/src/threads/gdt.c b/src/threads/gdt.c index 2fd6948..7a6005f 100644 --- a/src/threads/gdt.c +++ b/src/threads/gdt.c @@ -2,7 +2,53 @@ #include "debug.h" #include "mmu.h" #include "palloc.h" +#include "tss.h" +/* The Global Descriptor Table (GDT). + + The GDT, an x86-specific structure, defines segments that can + potentially be used by all processes in a system, subject to + their permissions. There is also a per-process Local + Descriptor Table (LDT) but that is not used by modern + operating systems. + + Each entry in the GDT, which is known by its byte offset in + the table, identifies a segment. For our purposes only three + types of segments are of interest: code, data, and TSS or + Task-State Segment descriptors. The former two types are + exactly what they sound like. The TSS is used primarily for + stack switching on interrupts. + + For more information on the GDT as used here, refer to + [IA32-v3] sections 3.2 through 3.5. */ +static uint64_t gdt[SEL_CNT]; + +/* Creating descriptors. */ +static uint64_t make_code_desc (int dpl); +static uint64_t make_data_desc (int dpl); +static uint64_t make_tss_desc (void *laddr); + +/* Sets up a proper GDT. The bootstrap loader's GDT didn't + include user-mode selectors or a TSS, but we need both now. */ +void +gdt_init (void) +{ + uint64_t gdtr_operand; + + /* Initialize GDT. */ + gdt[SEL_NULL / sizeof *gdt] = 0; + gdt[SEL_KCSEG / sizeof *gdt] = make_code_desc (0); + gdt[SEL_KDSEG / sizeof *gdt] = make_data_desc (0); + gdt[SEL_UCSEG / sizeof *gdt] = make_code_desc (3); + gdt[SEL_UDSEG / sizeof *gdt] = make_data_desc (3); + gdt[SEL_TSS / sizeof *gdt] = make_tss_desc (tss_get ()); + + /* Load GDTR, TR. */ + gdtr_operand = make_dtr_operand (sizeof gdt - 1, gdt); + asm volatile ("lgdt %0" :: "m" (gdtr_operand)); + asm volatile ("ltr %w0" :: "r" (SEL_TSS)); +} + /* System segment or code/data segment? */ enum seg_class { @@ -85,35 +131,3 @@ make_tss_desc (void *laddr) return make_seg_desc ((uint32_t) laddr, 0x67, CLS_SYSTEM, 9, 0, GRAN_BYTE); } -static uint64_t gdt[SEL_CNT]; - -struct tss *tss; - -/* Sets up a proper GDT. The bootstrap loader's GDT didn't - include user-mode selectors or a TSS. */ -void -gdt_init (void) -{ - uint64_t gdtr_operand; - - /* Our TSS is never used in a call gate or task gate, so only a - few fields of it are ever referenced, and those are the only - ones we initialize. */ - tss = palloc_get (PAL_ASSERT | PAL_ZERO); - tss->esp0 = (uint32_t) ptov(0x20000); - tss->ss0 = SEL_KDSEG; - tss->bitmap = 0xdfff; - - /* Initialize GDT. */ - gdt[SEL_NULL / sizeof *gdt] = 0; - gdt[SEL_KCSEG / sizeof *gdt] = make_code_desc (0); - gdt[SEL_KDSEG / sizeof *gdt] = make_data_desc (0); - gdt[SEL_UCSEG / sizeof *gdt] = make_code_desc (3); - gdt[SEL_UDSEG / sizeof *gdt] = make_data_desc (3); - gdt[SEL_TSS / sizeof *gdt] = make_tss_desc (tss); - - /* Load GDTR, TR. */ - gdtr_operand = make_dtr_operand (sizeof gdt - 1, gdt); - asm volatile ("lgdt %0" :: "m" (gdtr_operand)); - asm volatile ("ltr %w0" :: "r" (SEL_TSS)); -}