summaryrefslogtreecommitdiff
path: root/kernel/cpu/tss.c
blob: 100525b7979bd694c4c4e9d13ce61b76a09bdae3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include "lib/kstring.h"
#include <stdint.h>

#include "tss.h"

struct sys_seg_descriptor {
	uint64_t limit0_15 : 16;
	uint64_t base0_15 : 16;
	uint64_t base16_23 : 8;
	uint64_t type : 4;
	uint64_t : 1;
	uint64_t DPL : 2;
	uint64_t present : 1;
	uint64_t limit16_19 : 4;
	uint64_t available : 1;
	uint64_t : 1;
	uint64_t : 1;
	uint64_t gran : 1;
	uint64_t base24_31 : 8;
	uint64_t base32_63 : 32;
	uint64_t : 32;
} __attribute__((packed));

struct tss {
	uint64_t : 32;
	uint64_t rsp0 : 64;
	uint64_t rsp1 : 64;
	uint64_t rsp2 : 64;
	uint64_t : 64;
	uint64_t ist1 : 64;
	uint64_t ist2 : 64;
	uint64_t ist3 : 64;
	uint64_t ist4 : 64;
	uint64_t ist5 : 64;
	uint64_t ist6 : 64;
	uint64_t ist7 : 64;
	uint64_t : 64;
	uint64_t : 16;
	uint64_t iopb : 16;
} __attribute__((packed));

// tss entry
static volatile struct tss tss;

// gdt entries
extern volatile uint8_t GDT[];
static volatile struct sys_seg_descriptor *GDT_TSS;

// kernel stack pointer
extern char kern_stack_end[];

void tss_init(void)
{
	uint64_t base = (uint64_t)&tss;
	uint64_t limit = sizeof tss - 1;

	// setup tss entry
	memsetv(&tss, 0, sizeof(struct tss));
	tss.rsp0 = (uint64_t)kern_stack_end;

	// map tss into gdt
	GDT_TSS = (volatile struct sys_seg_descriptor *)(GDT + 0x28);
	memsetv(GDT_TSS, 0, sizeof(struct sys_seg_descriptor));
	GDT_TSS->limit0_15 = limit & 0xFFFF;
	GDT_TSS->base0_15 = base & 0xFFFF;
	GDT_TSS->base16_23 = (base >> 16) & 0xFF;
	GDT_TSS->type = 0x9;
	GDT_TSS->DPL = 0;
	GDT_TSS->present = 1;
	GDT_TSS->limit16_19 = (limit >> 16) & 0xF;
	GDT_TSS->available = 0;
	GDT_TSS->gran = 0;
	GDT_TSS->base24_31 = (base >> 24) & 0xFF;
	GDT_TSS->base32_63 = (base >> 32) & 0xFFFFFFFF;

	tss_flush();
}

void tss_set_stack(uint64_t stack)
{
	tss.rsp0 = stack;
}