icealys wrote:so does the processor somehow push the parameters onto the stack when it calls the interrupt handler? I thought that would be impossible since you need to implement a push operation in code by calling a function like this ...int somefunc(param1,param2);. So my question is, can the processor push the parameters on its own when it calls the interrupt handler?
There are basically 3 parts for system call:
1. gathering parameters in user-space
2. invoke the kernel
3. get those parameters in kernel-space
3.5 system handler stub invoke C/C++/Higher level handlers
Generally you need to define how to pass parameters from (1) to (3), the CPU won't do anything magically except those defined in the manual.
Most design just pass parameters on registers, i.e.
In step 1 your user-space syscall function may do:
- preserve registers requested by ABI
- put parameters to registers, in some design you may also pass parameters on stack or indirect pointer to memory
Then, for (2) invoke the kernel with INT, SYSENTER, SYSCALL or other ridiculous ways. Note that some mechanic involve stack switch.
In (3), the stub would:
- preserve registers requested by syscall ABI, or just preserve none, or all.
- extract the parameters
- invoke high-level handlers according to ABI
Now this seems bloated, but on smartly designed ABI like AMD x86_64, all the register preservation is eliminated and things reduced to:
Code: Select all
; USER SPACE API
; int open ( const char * file, int flags, int mode );
open:
mov eax, 2
mov r10, rcx ; rcx is used by syscall
syscall
ret
-----------------------------------------
KERNEL STUB (simplified)
_syscall_stub:
cmp rax, 12
ja .fault
mov r10, rsp
mov rsp, qword [k_TSS + tss64_rsp0] ; switch to kernel stack
sti
push rcx ; userspace rip
push r11 ; rflags
push r10 ; user stack
mov r11, qword syscall_table
mov rcx, r9 ; 4th parameter
; invoke handler
call qword [r11 + rax*8]
pop r10
pop r11
pop rcx
cli
mov rsp, r10
db 0x48 ; REX.w
sysret
.fault:
mov eax, -1
db 0x48 ; REX.w
sysret
-----------------------------------------
KERNEL HANDLER (simplified)
int kservice_open(const char * file, int flags, int mode) {
kprintf ( "SYSCALL : open(%s, %X, %X)\n", file, flags, mode );
return -1;
}