You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

54 lines
2.2 KiB
ArmAsm

/* Copyright (C) 2021,2022 fef <owo@fef.moe>. All rights reserved. */
#include <asm/common.h>
/*
* Alright, a lot of stuff that is not immediately obvious to someone who hasn't
* done this sort of thing before is going on here, and since i'm totally new to
* x86 myself, here is some excessive documentation of the entire process (which
* will hopefully also help other newcomers in understanding the actual switching
* mechanism). I think the main reason this particular function might seem a
* little confusing is that it returns to a different place than where it came
* from, which is kind of the whole point if you think about it.
*
* This routine is called from within kernel space, and will perform a switch to
* another task that also runs in kernel space. So, this has nothing to do with
* changing ring levels. When another task switches back to the original task,
* that original task just returns to where it called this function as if
* nothing happened in the meantime.
* As per the System V amd64 ABI, the two arguments `new' and `old' are passed
* using the scratch registers %rdi and %rsi respectively, and the return
* address is stored on the stack.
*
* What we need to do now is store all caller saved registers (which critically
* include the stack pointer) into `old', set their values to the ones from
* `new' (again, including the stack pointer) and then just return.
* The new stack pointer will point to the same stack layout shown above, but
* this time that of the new task we are going to switch to. Since the stack
* also includes the %rip from when the new task called arch_switch_to(), we
* automatically switch to that task when returning.
*/
.text
/* void arch_switch_to(tcb_t *new, tcb_t *old); */
ASM_ENTRY(arch_switch_to)
movq %rsp, (%rsi) /* old->rsp = %rsp */
movq %rbx, 8(%rsi) /* old->rbx = %rbx */
movq %rbp, 16(%rsi) /* ... */
movq %r12, 24(%rsi)
movq %r13, 32(%rsi)
movq %r14, 40(%rsi)
movq %r15, 48(%rsi)
movq (%rdi), %rsp /* %rsp = new->rsp */
movq 8(%rdi), %rbx /* %rbx = new->rbx */
movq 16(%rdi), %rbp /* ... */
movq 24(%rdi), %r12
movq 32(%rdi), %r13
movq 40(%rdi), %r14
movq 48(%rdi), %r15
retq
ASM_END(arch_switch_to)