summaryrefslogtreecommitdiff
path: root/src/kernel/arch/amd64/sysenter.s
blob: 8d91c4aa581fa76cacc2d90a39e294e10cdf9473 (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
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
// 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

// temporarily used for IRET
	.skip 8
	.skip 8
	.skip 8
	.skip 8
	.skip 8
dumb_stack:

.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

	/* 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. */
	// TODO will probably end up fucking something up in a hard to debug way
	// sorry, future me. hopefully you have learned something from this
	fxrstor (_sysexit_regs + 128)
	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 (stored_rsp)

	pop %rbx
	pop %rdx
	pop %rcx
	pop %rax

	// enable paging
	mov (pagedir_current), %rsp
	mov %rsp, %cr3

	mov $dumb_stack, %rsp
	push $(SEG_r3data << 3 | 3) /* SS */
	push (stored_rsp) /* SP */
	push %r11 /* FLAGS */
	push $(SEG_r3code << 3 | 3) /* CS */
	push %rcx /* IP */
	iretq

sysenter_stage1:
	cli

	mov %rsp, (stored_rsp)

	mov $pml4_identity, %rsp
	mov %rsp, %cr3

	fxsave (_sysexit_regs + 128)
	mov $(_sysexit_regs + 128), %rsp
	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