2 Copyright © 2011-2015, The AROS Development Team. All rights reserved.
5 Desc: i386 native CPU supplementals for task scheduler
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>
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"
27 static inline unsigned long long RDTSC() {
28 unsigned long long _tsc
;
29 asm volatile (".byte 0x0f, 0x31" : "=A" (_tsc
));
33 void cpu_Dispatch(struct ExceptionContext
*regs
)
36 struct ExceptionContext
*ctx
;
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)
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
));
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
));
90 * Copy the fpu, mmx, xmm state.
91 * Do this before CopyMemQuick(), because this function
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
;
111 GetIntETask(task
)->iet_CpuTime
+= (RDTSC() - GetIntETask(task
)->iet_private1
);