summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/proc/scheduler.c
blob: 6c748c7637ab0ee449252a8aa949b7fc0ec3893f (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
#include "proc/scheduler.h"
#include "arch/x86_64/hal/gdt.h"
#include "arch/x86_64/hal/obj.h"
#include "lib/printf.h"
#include "lib/string.h"
#include "process.h"
#include "../hal/smp.h"
#include "../proc/process.h"

void
_scheduler_switch_pcb_arch(pcb_t *target)
{
    processor_t *proc = processor_current();
    proc->syscall_page = target->interrupt_page;
    proc->interrupt_page = target->interrupt_page;

    proc->tss.rsp[0] = __interrupt_stack + 0xFF8;

    if(target->iopb) {
        proc->tss.iopb = sizeof(struct tss);
        jove_owned_obj_t *iopb_obj = obj_take(target->iopb);
        if(obj_gettype(iopb_obj) != JOVE_OBJ_IOPB) {
            memcpy(proc->iopb, obj_deref(iopb_obj), sizeof(proc->iopb));
        }
        obj_release(iopb_obj);
    }else{
        proc->tss.iopb = 0xff;
    }
}

__attribute__((naked))
void scheduler_switch(void *this_sp, void *other_sp, void *new_cr3)
{
    __asm__ volatile("\
            movq %%rsp, (%%rdi); \
            movq %%rsi, %%rsp; \
            movq %%cr3, %%rax; \
            cmp %%rax, %%rdx; \
            je .nocr3swap; \
            movq %%rdx, %%cr3; \
            .nocr3swap: \
            movq %%gs:%c[syscall_page], %%rax; \
            movq %%rax, __syscall_stack_mapping; \
            movq (__syscall_stack), %%rax; \
            invlpg (%%rax); \
            movq %%gs:%c[interrupt_page], %%rax; \
            movq %%rax, __interrupt_stack_mapping; \
            movq (__interrupt_stack), %%rax; \
            invlpg (%%rax); \
            retq"::
            [syscall_page] "i"(offsetof(processor_t, syscall_page)),
            [interrupt_page] "i"(offsetof(processor_t, interrupt_page)));
}