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
|
global clear_tss
global switch_to
global set_tss
extern cstate
extern ctask
extern ctaskn
extern gdt
extern save_state
; void switch_to(int n, struct task_struct *task);
switch_to:
push ebp
mov ebp, esp
; abort if we're switching to the current task
mov ebx, [ctask]
cmp ebx, [ebp+12]
jne .skip
pop ebp
ret
.skip:
; clear the busy flag in the current TSS
mov eax, 0
str ax
add ax, gdt+5
mov byte [eax], 0x89
; set the current TSS to null so it won't be overwritten by the switch
mov ax, 0
ltr ax
; copy the saved state into the previous TSS
call save_state
; update ctask and ctaskn
mov ebx, [ebp+12]
mov [ctask], ebx
mov ebx, [ebp+8]
mov [ctaskn], ebx
; calculate the task segment index and jump to it
mov ebx, [ebp+8]
add ebx, 5
shl ebx, 3
mov [.tmp+4], bx
jmp far [.tmp]
.tmp:
dq 0
; void set_tss(unsigned int n, void *tss);
set_tss:
push ebp
mov ebp, esp
push ebx
mov eax, [ebp+12]
mov ebx, [ebp+8]
shl ebx, 3
add ebx, gdt+40
mov [ebx+2], ax
shr eax, 16
mov [ebx+4], al
mov [ebx+7], ah
mov eax, 103 ; limit - 1
mov [ebx], ax
shr eax, 16
and al, 0x0F
mov [ebx+6], al
mov byte [ebx+5], 0x89
pop ebx
pop ebp
ret
; void clear_tss(unsigned int n);
clear_tss:
push ebp
mov ebp, esp
push ebx
mov ebx, [ebp+8]
shl ebx, 3
add ebx, gdt+40
mov byte [ebx+5], 0
pop ebx
pop ebp
ret
|