Main Question: How can I save a kernel thread's frame on a kernel function call like it is done in syscalls from userspace? I want to schedule kthread from time to time and want it to continue execution from where it left.
Longer: I have implemented a 64bit kernel which can do multi-threading based on JOS framework. I want to add kernel threads to do swap operations in background. In order to schedule a kernel thread as other tasks, I want to save the kthread's frame on kernel function calls. My initial solution was to use INT as done from user space. How can I do a ring 0 to ring 0 system call interrupt (with INT/IRETQ) while saving the frame and changing it to use kernel stack?
The kernel thread operates in ring 0. When using existing system call code (shown below) with INT instruction, I am able to do a system call, but the operation is done on the calling kthread's stack because the %RSP value is the same. Basically, the thread calls INT 0x80, it goes to corresponding function in kernel space(it was already in kernel space), but all these operations are done on kernel thread's stack.
.global do_ksyscall
do_ksyscall:
pushq %rbp
movq 0x10(%rsp), %rbp
int $INT_SYSCALL
popq %rbp
retq
The use case of this is shown below:
void kthread_swap() {
page = get_page();
disk_write(page);
// Yielding now
// With current implementation of do_ksyscall
// this will go to correct function
// but the RSP will be the same of this thread
// instead it should change to kernel stack somehow
sched_yield(); // Don't block while waiting
// Should continue from here
int res = disk_poll();
if res ok kill(0);
else throw err;
}
If this is not clear, please point out. Thanks!