forked from tarequeh/kmux
-
Notifications
You must be signed in to change notification settings - Fork 0
/
kern_entry.S
129 lines (112 loc) · 3.45 KB
/
kern_entry.S
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
#include <asm/asm-offsets.h>
#include <asm/segment.h>
#include <asm/errno.h>
#include <asm/thread_info.h>
#include <linux/linkage.h>
#define ASM_PAGE_MASK (~(4096-1))
/* from entry.S */
EBX = 0x00
ECX = 0x04
EDX = 0x08
ESI = 0x0C
EDI = 0x10
EBP = 0x14
EAX = 0x18
DS = 0x1C
ES = 0x20
FS = 0x24
GS = 0x28
ORIG_EAX = 0x2C
EIP = 0x30
CS = 0x34
EFLAGS = 0x38
OLDESP = 0x3C
OLDSS = 0x40
CF_MASK = 0x00000001
TF_MASK = 0x00000100
IF_MASK = 0x00000200
DF_MASK = 0x00000400
NT_MASK = 0x00004000
VM_MASK = 0x00020000
#define SAVE_ALL \
cld; \
pushl %gs; \
pushl %fs; \
pushl %es; \
pushl %ds; \
pushl %eax; \
pushl %ebp; \
pushl %edi; \
pushl %esi; \
pushl %edx; \
pushl %ecx; \
pushl %ebx; \
movl $(__USER_DS), %edx; \
movl %edx, %ds; \
movl %edx, %es; \
movl $(__KERNEL_PERCPU), %edx; \
movl %edx, %fs; \
movl $(__KERNEL_STACK_CANARY), %edx; \
movl %edx, %gs
#define RESTORE_INT_REGS \
popl %ebx; \
popl %ecx; \
popl %edx; \
popl %esi; \
popl %edi; \
popl %ebp; \
popl %eax
#define RESTORE_REGS \
RESTORE_INT_REGS; \
popl %ds; \
popl %es; \
popl %fs; \
popl %gs
.text
ALIGN
ENTRY(save_syscall_environment)
movl TSS_sysenter_sp0(%esp), %esp
/*
* Push current_thread_info()->sysenter_return to the stack.
* A tiny bit of offset fixup is necessary - 4xN means the N words
* pushed above; +8 corresponds to copy_thread's esp0 setting.
*/
pushl (TI_sysenter_return-THREAD_SIZE+8+4*0)(%esp)
# Create space on stack to receive TSS
pushl $0
SAVE_ALL
movl %esp, %eax
# TODO: Load original %ebp value. Linux stores original %ebp on user stack and then loads user stack address in %ebp
call kmux_syscall_handler
RESTORE_REGS
cmpl $0, %eax
jl exit_syscall_environment
host_syscall_environment:
# Restore TSS
movl (%esp), %esp
# Jump to IP in TSS containing host kernel or exit address
jmp *0x04(%esp)
exit_syscall_environment:
/*
# 32 bit exit routine form Linux
PT_EIP (48) -> User IP
movl PT_EIP(%esp), %edx
PT_OLDESP (60) -> User Stack Pointer %ebp
movl PT_OLDESP(%esp), %ecx
xorl %ebp,%ebp
TRACE_IRQS_ON
PT_FS (36) -> Original %ds
1: mov PT_FS(%esp), %fs
PTGS_TO_GS
ENABLE_INTERRUPTS_SYSEXIT
*/
# Load FS with DS
movl %ds, %edx
movl %edx, %fs
# Load User IP form stack in %edx
movl 4(%esp), %edx
# Load User Stack Pointer into %ecx
movl %ebp, %ecx
xorl %ebp, %ebp
sti
sysexit