This repository has been archived by the owner on Mar 19, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
tss.c
83 lines (72 loc) · 1.93 KB
/
tss.c
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
83
#include <system.h>
#include <task.h>
#include <tss.h>
tss_t sys_tss;
/* Refreshs the TSS location within the GDT so the
* processor knows where to find it */
extern void _tss_flush();
/* Sets the kernel stack */
void tss_set_kernel_stack(unsigned int stack)
{
sys_tss.esp0 = stack;
}
/* Installs the TSS and user mode descriptors into the
* GDT */
void tss_install(signed int num, unsigned short ss0, unsigned short esp0)
{
/* Computer the base and limit of our entry into
* the GDT */
addr base = (addr)&sys_tss;
addr size = base + sizeof(tss_t);
/* Add the TSS's descriptor to the GDT */
gdt_set_gate(num, base, size, 0xE9, 0x00);
/* Ensure the descriptor is initially zero */
memset(&sys_tss, 0, sizeof(sys_tss));
/* Set the default kernel stack segments and
* pointer positions */
sys_tss.ss0 = ss0;
sys_tss.esp0 = esp0;
/* Here we should set the cs, ss, ds, es, fs and gs
* entries in the TSS. These specify what segemnts
* should be loaded when the processor switches to
* kernel mode. Therefore, they are just our normal
* kernel code/data segments - 0x08 and 0x10
* respectively, but with the last two bits set,
* making 0x0b and 0x13. The setting of these bits
* sets the RPL (requested privilege level) to 3,
* meaning that this TSS can be used to switch to
* kernel mode from ring 3 */
sys_tss.cs = 0x0B;
sys_tss.ss = sys_tss.ds = sys_tss.es = sys_tss.fs = sys_tss.gs = 0x13;
}
/* Extern definition to access the current task */
extern volatile struct task* current_task;
/* Jumps the system to user mode */
void tss_switch()
{
// Set up the kernel stack.
tss_set_kernel_stack(current_task->kernel_stack + KERNEL_STACK_SIZE);
// Jump into user mode.
asm volatile("\
cli; \
mov $0x23, %ax; \
mov %ax, %ds; \
mov %ax, %es; \
mov %ax, %fs; \
mov %ax, %gs; \
\
mov %esp, %eax; \
pushl $0x23; \
pushl %eax; \
pushf; \
\
pop %eax; \
or $0x200, %eax; \
push %eax; \
\
pushl $0x1B; \
push $1f; \
iret; \
1: \
");
}