The original syscall implementation utilized the TCB (Thread Control Block) to store the syscall stack address. On each context switch, the FS segment register would be reset to point to the thread-specific TCB where syscall handler would fetch its stack address.
In order to support statically linked executables that allocate and use their own TCB, OSv needs to be able to switch the FS register between the user and kernel address when handling syscalls. The syscall handler can no longer fetch its stack address from kernel TCB because the FS register points to the app TCB. In order to break this dependency, this patch changes all relevant code to move the syscall stack address and syscall caller stack pointer to the per-CPU memory area addressed by the GS segment register.
To that end, we define a new structure - syscall_stack_descriptor - that describes a syscall stack: its top and SYSCALL caller stack pointer. Then, we add a new field _syscall_stack_descriptor to the thread_state to store each thread-allocated syscall stack information.
In addition, we add a new field _current_syscall_stack_descriptor to the per-cpu structure arch_cpu and initialize each cpu GS register to point to it. Finally, the thread::switch_to() is changed to update the stack_top and caller_stack_pointer fields of _current_syscall_stack_descriptor on each context switch so that the syscall handler can fetch syscall stack address using GS segment.
The original syscall implementation utilized the TCB (Thread Control Block) to store the syscall stack address. On each context switch, the FS segment register would be reset to point to the thread-specific TCB where syscall handler would fetch its stack address.
In order to support statically linked executables that allocate and use their own TCB, OSv needs to be able to switch the FS register between the user and kernel address when handling syscalls. The syscall handler can no longer fetch its stack address from kernel TCB because the FS register points to the app TCB. In order to break this dependency, this patch changes all relevant code to move the syscall stack address and syscall caller stack pointer to the per-CPU memory area addressed by the GS segment register.
To that end, we define a new structure -
syscall_stack_descriptor
- that describes a syscall stack: its top andSYSCALL
caller stack pointer. Then, we add a new field_syscall_stack_descriptor
to thethread_state
to store each thread-allocated syscall stack information.In addition, we add a new field
_current_syscall_stack_descriptor
to the per-cpu structurearch_cpu
and initialize each cpu GS register to point to it. Finally, thethread::switch_to()
is changed to update thestack_top
andcaller_stack_pointer
fields of_current_syscall_stack_descriptor
on each context switch so that the syscall handler can fetch syscall stack address using GS segment.