summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/proc/scheduler.c
blob: 49a0c4dbf3fab5c139229cc2a9259d9a04afcd45 (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
#include "proc/scheduler.h"
#include "arch/x86_64/hal/gdt.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;

    if(target->iopb) {
        proc->tss.iopb = sizeof(struct tss);
        jove_owned_obj_t *iopb_obj = obj_take(target->iopb);
        memcpy(proc->iopb, obj_deref(iopb_obj), sizeof(proc->iopb));
    }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)));
}