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 void cpu_Dispatch(struct ExceptionContext
*regs
)
30 struct ExceptionContext
*ctx
;
33 * Is the list of ready tasks empty? Well, increment the idle switch count and halt CPU.
34 * It should be extended by some plugin mechanism which would put CPU and whole machine
35 * into some more sophisticated sleep states (ACPI?)
37 while (!(task
= core_Dispatch()))
39 /* Sleep almost forever ;) */
40 __asm__
__volatile__("sti; hlt; cli");
42 if (SysBase
->SysFlags
& SFF_SoftInt
)
43 core_Cause(INTB_SOFTINT
, 1l << INTB_SOFTINT
);
46 /* TODO: Handle exception
47 if (task->tc_Flags & TF_EXCEPT)
50 /* Get task's context */
51 ctx
= task
->tc_UnionETask
.tc_ETask
->et_RegFrame
;
52 D(bug("[Kernel] Dispatch task %s, context 0x%p\n", task
->tc_Node
.ln_Name
, ctx
));
54 /* Restore GPRs first. CopyMemQuick() may use SSE. */
55 CopyMemQuick(ctx
, regs
, offsetof(struct ExceptionContext
, FPData
));
57 if (ctx
->Flags
& ECF_FPX
)
60 * We have SSE state, restore it.
61 * SSE context includes 8087, so we don't have to care about
62 * it separately after this.
64 asm volatile("fxrstor (%0)"::"r"(ctx
->FXData
));
66 else if (ctx
->Flags
& ECF_FPU
)
68 /* No SSE, plain 8087 */
69 asm volatile("frstor (%0)"::"r"(ctx
->FPData
));
72 /* Store the launch time */
73 GetIntETask(task
)->iet_private1
= RDTSC();
76 void cpu_Switch(struct ExceptionContext
*regs
)
78 struct Task
*task
= SysBase
->ThisTask
;
79 struct ExceptionContext
*ctx
= task
->tc_UnionETask
.tc_ETask
->et_RegFrame
;
81 D(bug("[Kernel] cpu_Switch(), task %s\n", task
->tc_Node
.ln_Name
));
84 * Copy the fpu, mmx, xmm state.
85 * Do this before CopyMemQuick(), because this function
88 if (KernelBase
->kb_ContextFlags
& ECF_FPX
)
89 asm volatile("fxsave (%0)"::"r"(ctx
->FXData
));
90 if (KernelBase
->kb_ContextFlags
& ECF_FPU
)
91 asm volatile("fnsave (%0)"::"r"(ctx
->FPData
));
94 * Copy current task's context into the ETask structure. Note that context on stack
95 * misses SSE data pointer.
97 CopyMemQuick(regs
, ctx
, offsetof(struct ExceptionContext
, FPData
));
98 /* We have the complete data now */
99 ctx
->Flags
= ECF_SEGMENTS
| KernelBase
->kb_ContextFlags
;
100 /* Set task's tc_SPReg */
101 task
->tc_SPReg
= (APTR
)regs
->esp
;
105 GetIntETask(task
)->iet_CpuTime
+= (RDTSC() - GetIntETask(task
)->iet_private1
);