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
|
#include <kernel/arch/generic.h>
#include <kernel/proc.h>
struct registers_pushad _sysexit_regs; // a hack
extern void _sysexit_real();
void sysexit(struct registers regs) {
_sysexit_regs = (struct registers_pushad) {
.eax = regs.eax,
.ebx = regs.ebx,
.ebp = regs.ebp,
.esi = regs.esi,
.edi = regs.edi,
// sysexit args
.ecx = regs.esp,
.edx = regs.eip,
// ESP doesn't matter
};
_sysexit_real();
}
void sysenter_stage2(int edi, int esi, void *ebp, void *esp,
int ebx, int edx, int ecx, int eax)
{
uint64_t val;
process_current->regs = (struct registers) {
// EAX and EDX will get overriden with the return value later on
.eax = eax,
.ecx = ecx,
.edx = edx,
.ebx = ebx,
.esi = esi,
.edi = edi,
.esp = (void*) ecx, // not a typo, part of my calling convention
.eip = (void*) edx, // ^
.ebp = ebp,
};
val = syscall_handler(eax, ebx, esi, edi);
regs_savereturn(&process_current->regs, val);
process_switch(process_current); // TODO process_resume
}
|