Indentation fix, cleanup.
[AROS.git] / arch / i386-pc / kernel / kernel_cpu.c
blob0f50b8621f726985c8b04cc5eb85bc2f9d329458
1 /*
2 Copyright © 2011-2015, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: i386 native CPU supplementals for task scheduler
6 Lang: english
7 */
9 #include <exec/lists.h>
10 #include <exec/tasks.h>
11 #include <exec/execbase.h>
12 #include <hardware/intbits.h>
13 #include <proto/exec.h>
15 #include "etask.h"
17 #include "kernel_base.h"
18 #include "kernel_debug.h"
19 #include "kernel_intern.h"
20 #include "kernel_intr.h"
21 #include "kernel_scheduler.h"
23 #include "apic.h"
25 #define D(x)
27 static inline unsigned long long RDTSC() {
28 unsigned long long _tsc;
29 asm volatile (".byte 0x0f, 0x31" : "=A" (_tsc));
30 return _tsc;
33 void cpu_Dispatch(struct ExceptionContext *regs)
35 struct Task *task;
36 struct ExceptionContext *ctx;
38 /*
39 * Is the list of ready tasks empty? Well, increment the idle switch count and halt CPU.
40 * It should be extended by some plugin mechanism which would put CPU and whole machine
41 * into some more sophisticated sleep states (ACPI?)
43 while (!(task = core_Dispatch()))
45 /* Sleep almost forever ;) */
46 __asm__ __volatile__("sti; hlt; cli");
48 if (SysBase->SysFlags & SFF_SoftInt)
49 core_Cause(INTB_SOFTINT, 1l << INTB_SOFTINT);
52 /* TODO: Handle exception
53 if (task->tc_Flags & TF_EXCEPT)
54 Exception(); */
56 /* Get task's context */
57 ctx = task->tc_UnionETask.tc_ETask->et_RegFrame;
58 D(bug("[Kernel] Dispatch task %s, context 0x%p\n", task->tc_Node.ln_Name, ctx));
60 /* Restore GPRs first. CopyMemQuick() may use SSE. */
61 CopyMemQuick(ctx, regs, offsetof(struct ExceptionContext, FPData));
62 /* Then FPU */
63 if (ctx->Flags & ECF_FPX)
66 * We have SSE state, restore it.
67 * SSE context includes 8087, so we don't have to care about
68 * it separately after this.
70 asm volatile("fxrstor (%0)"::"r"(ctx->FXData));
72 else if (ctx->Flags & ECF_FPU)
74 /* No SSE, plain 8087 */
75 asm volatile("frstor (%0)"::"r"(ctx->FPData));
78 /* Store the launch time */
79 GetIntETask(task)->iet_private1 = RDTSC();
82 void cpu_Switch(struct ExceptionContext *regs)
84 struct Task *task = SysBase->ThisTask;
85 struct ExceptionContext *ctx = task->tc_UnionETask.tc_ETask->et_RegFrame;
87 D(bug("[Kernel] cpu_Switch(), task %s\n", task->tc_Node.ln_Name));
89 /*
90 * Copy the fpu, mmx, xmm state.
91 * Do this before CopyMemQuick(), because this function
92 * can use SSE itself.
94 if (KernelBase->kb_ContextFlags & ECF_FPX)
95 asm volatile("fxsave (%0)"::"r"(ctx->FXData));
96 if (KernelBase->kb_ContextFlags & ECF_FPU)
97 asm volatile("fnsave (%0)"::"r"(ctx->FPData));
100 * Copy current task's context into the ETask structure. Note that context on stack
101 * misses SSE data pointer.
103 CopyMemQuick(regs, ctx, offsetof(struct ExceptionContext, FPData));
104 /* We have the complete data now */
105 ctx->Flags = ECF_SEGMENTS | KernelBase->kb_ContextFlags;
106 /* Set task's tc_SPReg */
107 task->tc_SPReg = (APTR)regs->esp;
109 /* FIXME */
110 #if (0)
111 GetIntETask(task)->iet_CpuTime += (RDTSC() - GetIntETask(task)->iet_private1);
112 #endif
114 core_Switch();