THREADS_SRC = start.S # Must be linked first.
THREADS_SRC += init.c # Main program.
THREADS_SRC += gdt.c # GDT initialization.
+THREADS_SRC += tss.c # TSS management.
THREADS_SRC += thread.c # Thread management core.
THREADS_SRC += switch.S # Thread switch routine.
THREADS_SRC += interrupt.c # Interrupt core.
#include "debug.h"
#include "mmu.h"
#include "palloc.h"
+#include "tss.h"
/* System segment or code/data segment? */
enum seg_class
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
{
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);
+ gdt[SEL_TSS / sizeof *gdt] = make_tss_desc (tss_get ());
/* Load GDTR, TR. */
gdtr_operand = make_dtr_operand (sizeof gdt - 1, gdt);
#ifndef __ASSEMBLER__
#include <stdint.h>
-struct tss
- {
- uint16_t back_link, :16;
- uint32_t esp0;
- uint16_t ss0, :16;
- uint32_t esp1;
- uint16_t ss1, :16;
- uint32_t esp2;
- uint16_t ss2, :16;
- uint32_t cr3;
- uint32_t eip;
- uint32_t eflags;
- uint32_t eax, ecx, edx, ebx;
- uint32_t esp, ebp, esi, edi;
- uint16_t es, :16;
- uint16_t cs, :16;
- uint16_t ss, :16;
- uint16_t ds, :16;
- uint16_t fs, :16;
- uint16_t gs, :16;
- uint16_t ldt, :16;
- uint16_t trace, bitmap;
- };
-
-
static inline uint64_t
make_dtr_operand (uint16_t limit, void *base)
{
return limit | ((uint64_t) (uint32_t) base << 16);
}
-extern struct tss *tss;
-
void gdt_init (void);
#endif
#include "serial.h"
#include "thread.h"
#include "timer.h"
+#include "tss.h"
#include "vga.h"
#ifdef FILESYS
#include "filesys.h"
/* Initialize memory system. */
palloc_init ();
paging_init ();
+ tss_init ();
gdt_init ();
malloc_init ();
--- /dev/null
+#include "tss.h"
+#include <stddef.h>
+#include "debug.h"
+#include "gdt.h"
+#include "mmu.h"
+#include "palloc.h"
+
+struct tss
+ {
+ uint16_t back_link, :16;
+ void *esp0;
+ uint16_t ss0, :16;
+ void *esp1;
+ uint16_t ss1, :16;
+ void *esp2;
+ uint16_t ss2, :16;
+ uint32_t cr3;
+ void (*eip) (void);
+ uint32_t eflags;
+ uint32_t eax, ecx, edx, ebx;
+ uint32_t esp, ebp, esi, edi;
+ uint16_t es, :16;
+ uint16_t cs, :16;
+ uint16_t ss, :16;
+ uint16_t ds, :16;
+ uint16_t fs, :16;
+ uint16_t gs, :16;
+ uint16_t ldt, :16;
+ uint16_t trace, bitmap;
+ };
+
+static struct tss *tss;
+
+void
+tss_init (void)
+{
+ /* 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 = ptov(0x20000);
+ tss->ss0 = SEL_KDSEG;
+ tss->bitmap = 0xdfff;
+}
+
+struct tss *
+tss_get (void)
+{
+ ASSERT (tss != NULL);
+ return tss;
+}
+
+void
+tss_set_esp0 (uint8_t *esp0)
+{
+ ASSERT (tss != NULL);
+ tss->esp0 = esp0;
+}
--- /dev/null
+#ifndef HEADER_TSS_H
+#define HEADER_TSS_H
+
+#include <stdint.h>
+
+struct tss;
+void tss_init (void);
+struct tss *tss_get (void);
+void tss_set_esp0 (uint8_t *);
+
+#endif /* tss.h */
#include "debug.h"
#include "file.h"
#include "filesys.h"
-#include "gdt.h"
#include "init.h"
#include "lib.h"
#include "mmu.h"
#include "paging.h"
#include "palloc.h"
#include "thread.h"
+#include "tss.h"
/* We load ELF binaries. The following definitions are taken
from the ELF specification more-or-less verbatim. */
if (t->pagedir != NULL)
pagedir_activate (t->pagedir);
- tss->esp0 = (uint32_t) t + PGSIZE;
+ tss_set_esp0 ((uint8_t *) t + PGSIZE);
}