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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
// gdt.h
.set SEG_r0code, 1
.set SEG_r3code32, 3
.set SEG_r3data, 4
.set SEG_r3code, 5
.set IA32_STAR, 0xC0000081
.set IA32_LSTAR, 0xC0000082
.set IA32_CSTAR, 0xC0000083
.set IA32_FMASK, 0xC0000084
.section .text
.global sysenter_setup
.type sysenter_setup, @function
sysenter_setup:
// the intel docs don't mention the lower 32 bits
mov $0, %eax
mov $( ((SEG_r3code32 << 3 | 3) << 16) | (SEG_r0code << 3) ), %edx
mov $IA32_STAR, %rcx
wrmsr
mov $sysenter_stage1, %eax
mov $0, %edx
mov $IA32_LSTAR, %rcx
wrmsr
// hoping that the default RFLAGS mask is fine...
ret
.section .shared
.global stored_rsp
stored_rsp:
.skip 8
.global pagedir_current
// TODO make into an argument of sysexit
pagedir_current:
.skip 8
/* fake stack used for IRET */
.align 8
iret_stack:
iret_ip:
.skip 8
iret_cs:
.quad SEG_r3code << 3 | 3
iret_flags:
.skip 8
iret_sp:
.skip 8
iret_ss:
.quad SEG_r3data << 3 | 3
.global _sysexit_real
.type _sysexit_real, @function
_sysexit_real:
mov $(SEG_r3data << 3 | 3), %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov $_sysexit_regs, %rsp
pop %r15
pop %r14
pop %r13
pop %r12
pop %r11
pop %r10
pop %r9
pop %r8
pop %rdi
pop %rsi
pop %rbp
pop (iret_sp)
pop %rbx
pop %rdx
pop %rcx
pop %rax
pop (iret_ip)
pop (iret_flags)
/* The state image referenced with an FXRSTOR instruction must have
* been saved using an FXSAVE instruction or be in the same format
* as required [...] will result in an incorrect state restoration. */
fxrstor (%rsp)
mov (pagedir_current), %rsp
mov %rsp, %cr3
mov $iret_stack, %rsp
iretq
sysenter_stage1:
cli
mov %rsp, (stored_rsp)
mov $pml4_identity, %rsp
mov %rsp, %cr3
mov $(_sysexit_regs + 144), %rsp
fxsave (%rsp)
push %r11 /* flags */
push %rcx /* ip */
push %rax
push %rcx
push %rdx
push %rbx
push (stored_rsp)
push %rbp
push %rsi
push %rdi
push %r8
push %r9
push %r10
push %r11
push %r12
push %r13
push %r14
push %r15
mov $_bss_end, %rsp
push $0 // for stacktraces
jmp sysenter_stage2
|