about summary refs log tree commit diff
path: root/src/internal/i386/syscall.s
blob: 0ebf221842159ad2aeda5abc8753f9340abf1014 (plain) (blame)
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
.hidden __sysinfo

# The calling convention for __vsyscall has the syscall number
# and 5 args arriving as:  eax, edx, ecx, edi, esi, 4(%esp).
# This ensures that the inline asm in the C code never has to touch
# ebx or ebp (which are unavailable in PIC and frame-pointer-using
# code, respectively), and optimizes for size/simplicity in the caller.

.global __vsyscall
.hidden __vsyscall
.type __vsyscall,@function
__vsyscall:
	push %edi
	push %ebx
	mov %edx,%ebx
	mov %edi,%edx
	mov 12(%esp),%edi
	push %eax
	call 1f
2:	mov %ebx,%edx
	pop %ebx
	pop %ebx
	pop %edi
	ret

1:	mov (%esp),%eax
	add $[__sysinfo-2b],%eax
	mov (%eax),%eax
	test %eax,%eax
	jz 1f
	push %eax
	mov 8(%esp),%eax
	ret                     # tail call to kernel vsyscall entry
1:	mov 4(%esp),%eax
	int $128
	ret

# The __vsyscall6 entry point is used only for 6-argument syscalls.
# Instead of passing the 5th argument on the stack, a pointer to the
# 5th and 6th arguments is passed. This is ugly, but there are no
# register constraints the inline asm could use that would make it
# possible to pass two arguments on the stack.

.global __vsyscall6
.hidden __vsyscall6
.type __vsyscall6,@function
__vsyscall6:
	push %ebp
	push %eax
	mov 12(%esp), %ebp
	mov (%ebp), %eax
	mov 4(%ebp), %ebp
	push %eax
	mov 4(%esp),%eax
	call __vsyscall
	pop %ebp
	pop %ebp
	pop %ebp
	ret

.global __syscall
.hidden __syscall
.type __syscall,@function
__syscall:
	lea 24(%esp),%eax
	push %esi
	push %edi
	push %eax
	mov 16(%esp),%eax
	mov 20(%esp),%edx
	mov 24(%esp),%ecx
	mov 28(%esp),%edi
	mov 32(%esp),%esi
	call __vsyscall6
	pop %edi
	pop %edi
	pop %esi
	ret