X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=kitten%2Farch%2Fx86_64%2Fkernel%2Fsched.c;fp=kitten%2Farch%2Fx86_64%2Fkernel%2Fsched.c;h=522d6685f19ce686b7fd0e606e054eeb2c6f39be;hb=6299cb929a586fd8debcc316c1ede714d5b95979;hp=0000000000000000000000000000000000000000;hpb=e9e3ee43cb302909917b5919f6043347b73c6995;p=palacios.releases.git diff --git a/kitten/arch/x86_64/kernel/sched.c b/kitten/arch/x86_64/kernel/sched.c new file mode 100644 index 0000000..522d668 --- /dev/null +++ b/kitten/arch/x86_64/kernel/sched.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include + +struct task_struct * +__arch_context_switch(struct task_struct *prev_p, struct task_struct *next_p) +{ + struct thread_struct *prev = &prev_p->arch.thread; + struct thread_struct *next = &next_p->arch.thread; + id_t cpu = this_cpu; + struct tss_struct *tss = &per_cpu(tss, cpu); + + /* Update TSS */ + tss->rsp0 = next->rsp0; + + /* Switch DS and ES segment registers */ + asm volatile("mov %%es,%0" : "=m" (prev->es)); + if (unlikely(next->es | prev->es)) + loadsegment(es, next->es); + asm volatile("mov %%ds,%0" : "=m" (prev->ds)); + if (unlikely(next->ds | prev->ds)) + loadsegment(ds, next->ds); + + /* Load FS and GS segment registers (used for thread local storage) */ + { + unsigned int fsindex; + asm volatile("movl %%fs,%0" : "=r" (fsindex)); + if (unlikely(fsindex | next->fsindex | prev->fs)) { + loadsegment(fs, next->fsindex); + if (fsindex) + prev->fs = 0; + } + if (next->fs) + wrmsrl(MSR_FS_BASE, next->fs); + prev->fsindex = fsindex; + } + { + unsigned int gsindex; + asm volatile("movl %%gs,%0" : "=r" (gsindex)); + if (unlikely(gsindex | next->gsindex | prev->gs)) { + load_gs_index(next->gsindex); + if (gsindex) + prev->gs = 0; + } + if (next->gs) + wrmsrl(MSR_KERNEL_GS_BASE, next->gs); + prev->gsindex = gsindex; + } + + /* Update the CPU's PDA (per-CPU data area) */ + write_pda(pcurrent, next_p); + + /* If necessary, save and restore floating-point state */ + if (prev_p->arch.flags & TF_USED_FPU) + fpu_save_state(prev_p); + if (next_p->arch.flags & TF_USED_FPU) { + clts(); + fpu_restore_state(next_p); + } else { + /* + * Set the TS flag of CR0 so that FPU/MMX/SSE instructions + * will cause a "Device not available" exception. The exception + * handler will then initialize the FPU state and set the + * task's TF_USED_FPU flag. From that point on, the task + * should never experience another "Device not available" + * exception. + */ + stts(); + } + + return prev_p; +} + +void +arch_idle_task_loop_body(void) +{ + /* Issue HALT instruction, + * which should put CPU in a lower power mode */ + halt(); +}