revert between 56095 -> 55830 in arch
[AROS.git] / arch / all-pc / exec / platform_init.c
blobaa99f911de03d8096987a7b67f43b414e9a49d96
1 /*
2 Copyright © 2017, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/config.h>
8 #define DEBUG 0
9 #include <aros/debug.h>
11 #include <proto/exec.h>
13 #include <exec/memory.h>
14 #include <exec/tasks.h>
15 #include <exec/interrupts.h>
16 #include <exec/rawfmt.h>
18 #define __AROS_KERNEL__
20 #include "exec_intern.h"
22 extern void IdleTask(struct ExecBase *);
23 extern AROS_INTP(Exec_X86ShutdownHandler);
24 extern AROS_INTP(Exec_X86WarmResetHandler);
25 extern AROS_INTP(Exec_X86ColdResetHandler);
27 #if (__WORDSIZE==64)
28 #define EXCX_REGA regs->rax
29 #define EXCX_REGB regs->rbx
30 #define EXCX_REGC regs->rcx
31 #else
32 #define EXCX_REGA regs->eax
33 #define EXCX_REGB regs->ebx
34 #define EXCX_REGC regs->ecx
35 #endif
37 #define DSPIN(x)
39 #if defined(__AROSEXEC_SMP__)
40 struct Hook Exec_TaskSpinLockFailHook;
41 struct Hook Exec_TaskSpinLockForbidHook;
42 struct Hook Exec_TaskSpinLockDisableHook;
44 AROS_UFH3(void, Exec_TaskSpinLockFailFunc,
45 AROS_UFHA(struct Hook *, h, A0),
46 AROS_UFHA(spinlock_t *, spinLock, A1),
47 AROS_UFHA(void *, unused, A2))
49 AROS_USERFUNC_INIT
51 struct Task *spinTask = GET_THIS_TASK;
52 struct IntETask *thisET;
54 DSPIN(bug("[Exec:X86] %s()\n", __func__));
55 if (spinTask)
57 thisET = GetIntETask(spinTask);
58 if (thisET)
60 DSPIN(bug("[Exec:X86] %s: Setting task @ 0x%p to spinning...\n", __func__, spinTask));
62 /* tell the scheduler that the task is waiting on a spinlock */
63 spinTask->tc_State = TS_SPIN;
65 thisET->iet_SpinLock = spinLock;
69 DSPIN(bug("[Exec:X86] %s: Forcing Reschedule...\n", __func__));
71 /* schedule us away for now .. */
72 Reschedule();
74 AROS_USERFUNC_EXIT
77 AROS_UFH3(void, Exec_TaskSpinLockForbidFunc,
78 AROS_UFHA(struct Hook *, h, A0),
79 AROS_UFHA(spinlock_t *, spinLock, A1),
80 AROS_UFHA(void *, unused, A2))
82 AROS_USERFUNC_INIT
84 DSPIN(
85 struct Task *spinTask = GET_THIS_TASK;
86 bug("[Exec:X86] %s(0x%p)\n", __func__, spinTask);
89 Forbid();
91 DSPIN(bug("[Exec:X86] %s: done\n", __func__));
93 AROS_USERFUNC_EXIT
96 AROS_UFH3(void, Exec_TaskSpinLockDisableFunc,
97 AROS_UFHA(struct Hook *, h, A0),
98 AROS_UFHA(spinlock_t *, spinLock, A1),
99 AROS_UFHA(void *, unused, A2))
101 AROS_USERFUNC_INIT
103 DSPIN(
104 struct Task *spinTask = GET_THIS_TASK;
105 bug("[Exec:X86] %s(0x%p)\n", __func__, spinTask);
108 Disable();
110 DSPIN(bug("[Exec:X86] %s: done\n", __func__));
112 AROS_USERFUNC_EXIT
115 void Exec_TaskSpinUnlock(spinlock_t *spinLock)
117 #if (0)
118 struct Task *spinTask, *nxtTask;
119 struct IntETask *thisET;
120 #endif
121 DSPIN(bug("\n[Exec:X86] %s(0x%p)\n", __func__, spinLock));
123 #if (0)
124 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskSpinningLock, NULL, SPINLOCK_MODE_WRITE);
125 ForeachNodeSafe(&PrivExecBase(SysBase)->TaskSpinning, spinTask, nxtTask)
127 thisET = GetIntETask(spinTask);
128 if ((thisET) && (thisET->iet_SpinLock == spinLock))
130 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskReadySpinLock, NULL, SPINLOCK_MODE_WRITE);
131 Disable();
132 Remove(&spinTask->tc_Node);
133 Enqueue(&SysBase->TaskReady, &spinTask->tc_Node);
134 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskReadySpinLock);
135 Enable();
138 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskSpinningLock);
139 #endif
141 DSPIN(bug("[Exec:X86] %s: done\n\n", __func__));
144 void X86_HandleSpinLock(struct ExceptionContext *regs)
146 struct ExecSpinSCData *spinData = (struct ExecSpinSCData *)EXCX_REGB;
148 DSPIN(bug("[Exec:X86] %s(0x%p, 0x%p, %08x)\n", __func__, spinData->lock_ptr, spinData->lock_failhook, spinData->lock_mode));
150 EXEC_SPINLOCK_LOCK(spinData->lock_ptr, spinData->lock_failhook, spinData->lock_mode);
152 if (spinData->lock_obtainhook)
154 DSPIN(bug("[Exec:X86] %s: calling lock-obtained hook @ 0x%p ...\n", __func__, spinData->lock_obtainhook);)
155 CALLHOOKPKT(spinData->lock_obtainhook, (APTR)spinData->lock_ptr, 0);
158 EXCX_REGA = (IPTR)spinData->lock_ptr;
160 DSPIN(bug("[Exec:X86] %s: done\n", __func__));
162 return;
165 struct syscallx86_Handler x86_SCSpinLockHandler =
168 .ln_Name = (APTR)SC_X86CPUSPINLOCK
170 (APTR)X86_HandleSpinLock
173 spinlock_t *ExecSpinLockCall(spinlock_t *spinLock, struct Hook *hookObtained, struct Hook *hookFailed, ULONG spinMode)
175 struct ExecSpinSCData __spinData =
177 spinLock,
178 hookObtained,
179 hookFailed,
180 spinMode
182 spinlock_t *__retval;
183 DSPIN(bug("\n[Exec:X86] %s: attempting to lock 0x%p\n", __func__, spinLock));
184 __retval = krnSysCallSpinLock(&__spinData);
185 DSPIN(bug("[Exec:X86] %s: returning 0x%p\n\n", __func__, __retval));
186 return __retval;
188 #endif
190 #if defined(EXEC_REMTASK_NEEDSSWITCH)
191 void X86_HandleSwitch(struct ExceptionContext *regs)
193 D(bug("[Exec:X86] %s()\n", __func__));
195 cpu_Switch(regs);
197 return;
200 struct syscallx86_Handler x86_SCSwitchHandler =
203 .ln_Name = (APTR)SC_X86SWITCH
205 (APTR)X86_HandleSwitch
208 void X86_SetTaskState(struct Task *changeTask, ULONG newState, BOOL dolock)
210 #if defined(__AROSEXEC_SMP__)
211 spinlock_t *task_listlock = NULL;
212 #endif
213 struct List *task_list = NULL;
214 D(bug("[Exec:X86] %s(0x%p,%08x)\n", __func__, changeTask, newState));
216 changeTask->tc_State = newState;
218 switch (newState)
220 case TS_RUN:
221 #if defined(__AROSEXEC_SMP__)
222 task_listlock = &PrivExecBase(SysBase)->TaskRunningSpinLock;
223 task_list = &PrivExecBase(SysBase)->TaskRunning;
224 #endif
225 break;
226 case TS_READY:
227 #if defined(__AROSEXEC_SMP__)
228 task_listlock = &PrivExecBase(SysBase)->TaskReadySpinLock;
229 #endif
230 task_list = &SysBase->TaskReady;
231 break;
232 case TS_WAIT:
233 #if defined(__AROSEXEC_SMP__)
234 task_listlock = &PrivExecBase(SysBase)->TaskWaitSpinLock;
235 #endif
236 task_list = &SysBase->TaskWait;
237 break;
238 #if defined(__AROSEXEC_SMP__)
239 case TS_SPIN:
240 task_listlock = &PrivExecBase(SysBase)->TaskSpinningLock;
241 task_list = &PrivExecBase(SysBase)->TaskSpinning;
242 break;
243 #endif
244 default:
245 break;
247 if (task_list)
249 #if defined(__AROSEXEC_SMP__)
250 if (dolock && task_listlock) EXEC_SPINLOCK_LOCK(task_listlock, NULL, SPINLOCK_MODE_WRITE);
251 #endif
252 Enqueue(task_list, &changeTask->tc_Node);
253 #if defined(__AROSEXEC_SMP__)
254 if (dolock && task_listlock) EXEC_SPINLOCK_UNLOCK(task_listlock);
255 #endif
259 /* change a specified task's state */
260 void X86_HandleReschedTask(struct ExceptionContext *regs)
262 struct Task *reschTask = (struct Task *)EXCX_REGB;
263 ULONG reschState = (ULONG)EXCX_REGC;
264 #if defined(__AROSEXEC_SMP__)
265 spinlock_t *task_listlock = NULL;
266 #endif
268 D(bug("[Exec:X86] %s(0x%p,%08x)\n", __func__, reschTask, reschState));
270 /* Move to the ready list... */
271 #if defined(__AROSEXEC_SMP__)
272 switch (reschTask->tc_State)
274 case TS_RUN:
275 task_listlock = &PrivExecBase(SysBase)->TaskRunningSpinLock;
276 break;
277 case TS_READY:
278 task_listlock = &PrivExecBase(SysBase)->TaskReadySpinLock;
279 break;
280 case TS_WAIT:
281 task_listlock = &PrivExecBase(SysBase)->TaskWaitSpinLock;
282 break;
283 case TS_SPIN:
284 task_listlock = &PrivExecBase(SysBase)->TaskSpinningLock;
285 break;
286 default:
287 break;
289 if (task_listlock)
290 EXEC_SPINLOCK_LOCK(task_listlock, NULL, SPINLOCK_MODE_WRITE);
292 if ((reschTask->tc_State != TS_INVALID) && (reschTask->tc_State != TS_TOMBSTONED))
293 #else
294 if ((reschTask->tc_State != TS_INVALID) && (reschTask->tc_State != TS_RUN))
295 #endif
296 Remove(&reschTask->tc_Node);
297 #if defined(__AROSEXEC_SMP__)
298 switch (reschState)
300 case TS_UNSPIN:
302 #if (0)
303 struct Task *spinTask, *tmpTask;
304 struct IntETask *reschTaskIntET, *spinTaskIntET;
305 #endif
306 reschState = TS_READY;
307 #if (0)
308 reschTaskIntET = GetIntETask(reschTask);
310 EXEC_SPINLOCK_LOCK(&PrivExecBase(SysBase)->TaskSpinningLock, NULL, SPINLOCK_MODE_WRITE);
311 ForeachNodeSafe(&PrivExecBase(SysBase)->TaskSpinning, spinTask, tmpTask)
313 spinTaskIntET = GetIntETask(spinTask);
314 if ((spinTaskIntET) && (spinTaskIntET->iet_SpinLock == reschTaskIntET->iet_SpinLock))
316 bug("[Exec:X86] %s: enabling spinning task @ 0x%p\n", __func__, spinTask);
317 spinTaskIntET->iet_SpinLock=NULL;
318 X86_SetTaskState(spinTask, TS_READY, TRUE);
321 EXEC_SPINLOCK_UNLOCK(&PrivExecBase(SysBase)->TaskSpinningLock);
322 #endif
324 case TS_READY:
325 case TS_SPIN:
326 #endif
327 X86_SetTaskState(reschTask, reschState, (BOOL)(reschTask->tc_State != reschState));
328 #if defined(__AROSEXEC_SMP__)
329 break;
330 case TS_REMOVED:
331 reschTask->tc_State = TS_TOMBSTONED;
332 break;
335 if (task_listlock)
336 EXEC_SPINLOCK_UNLOCK(task_listlock);
337 #endif
339 return;
342 struct syscallx86_Handler x86_SCReschedTaskHandler =
345 .ln_Name = (APTR)SC_X86RESCHEDTASK
347 (APTR)X86_HandleReschedTask
349 #endif
351 struct Task *Exec_X86CreateIdleTask(APTR sysBase)
353 struct ExecBase *SysBase = (struct ExecBase *)sysBase;
354 struct Task *CPUIdleTask;
355 char *taskName;
356 #if defined(__AROSEXEC_SMP__)
357 struct KernelBase *KernelBase = __kernelBase;
358 int cpuNo = KrnGetCPUNumber();
359 IPTR idleNameArg[] =
361 cpuNo
363 struct MemList *ml;
364 void *cpuMask;
366 cpuMask = KrnAllocCPUMask();
368 if ((ml = AllocMem(sizeof(struct MemList), MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
370 bug("[Exec:X86.%03u] FATAL : Failed to allocate memory for idle task name info", cpuNo);
371 return NULL;
374 ml->ml_NumEntries = 1;
376 ml->ml_ME[0].me_Length = 15;
377 if ((ml->ml_ME[0].me_Addr = AllocMem(15, MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
379 bug("[Exec:X86.%03u] FATAL : Failed to allocate memory for task idle name", cpuNo);
380 FreeMem(ml, sizeof(struct MemList));
381 return NULL;
383 taskName = ml->ml_ME[0].me_Addr;
384 RawDoFmt("CPU #%03u Idle", (RAWARG)idleNameArg, RAWFMTFUNC_STRING, taskName);
386 KrnGetCPUMask(cpuNo, cpuMask);
388 #else
389 taskName = "CPU Idle";
390 #endif
391 CPUIdleTask = NewCreateTask(TASKTAG_NAME , taskName,
392 #if defined(__AROSEXEC_SMP__)
393 TASKTAG_AFFINITY , cpuMask,
394 #endif
395 TASKTAG_PRI , -128,
396 TASKTAG_PC , IdleTask,
397 TASKTAG_ARG1 , SysBase,
398 TAG_DONE);
400 if (CPUIdleTask)
403 bug("[Exec:X86] %s: '%s' Task created @ 0x%p\n", __func__, CPUIdleTask->tc_Node.ln_Name, CPUIdleTask);
404 #if defined(__AROSEXEC_SMP__)
405 bug("[Exec:X86] %s: CPU Affinity : %08x\n", __func__, IntETask(CPUIdleTask->tc_UnionETask.tc_ETask)->iet_CpuAffinity);
406 #endif
408 #if defined(__AROSEXEC_SMP__)
409 AddTail(&CPUIdleTask->tc_MemEntry, &ml->ml_Node);
410 #endif
412 #if defined(__AROSEXEC_SMP__)
413 else
415 FreeMem(ml->ml_ME[0].me_Addr, 15);
416 FreeMem(ml, sizeof(struct MemList));
418 #endif
419 return CPUIdleTask;
422 int Exec_X86Init(struct ExecBase *SysBase)
424 struct IntExecBase *sysBase = (struct IntExecBase *)SysBase;
425 #if defined(__AROSEXEC_SMP__) || defined(EXEC_REMTASK_NEEDSSWITCH)
426 struct KernelBase *KernelBase = __kernelBase;
427 #endif
429 D(bug("[Exec:X86] %s()\n", __func__));
430 D(bug("[Exec:X86] %s: KernelBase @ 0x%p\n", __func__, __kernelBase));
431 D(bug("[Exec:X86] %s: PlatformData @ 0x%p\n", __func__, &sysBase->PlatformData));
433 /* Install The default Power Management handlers */
434 sysBase->ColdResetHandler.is_Node.ln_Pri = -64;
435 sysBase->ColdResetHandler.is_Node.ln_Name = "Keyboard Controller Reset";
436 sysBase->ColdResetHandler.is_Code = (VOID_FUNC)Exec_X86ColdResetHandler;
437 sysBase->ColdResetHandler.is_Data = &sysBase->ColdResetHandler;
438 AddResetCallback(&sysBase->ColdResetHandler);
440 sysBase->WarmResetHandler.is_Node.ln_Pri = -64;
441 sysBase->WarmResetHandler.is_Node.ln_Name = "System Reset";
442 sysBase->WarmResetHandler.is_Code = (VOID_FUNC)Exec_X86WarmResetHandler;
443 sysBase->WarmResetHandler.is_Data = &sysBase->WarmResetHandler;
444 AddResetCallback(&sysBase->WarmResetHandler);
446 sysBase->ShutdownHandler.is_Node.ln_Pri = -128;
447 sysBase->ShutdownHandler.is_Node.ln_Name = "System Shutdown";
448 sysBase->ShutdownHandler.is_Code = (VOID_FUNC)Exec_X86ShutdownHandler;
449 sysBase->ShutdownHandler.is_Data = &sysBase->ShutdownHandler;
450 AddResetCallback(&sysBase->ShutdownHandler);
452 D(bug("[Exec:X86] %s: Default Handlers Registered\n", __func__));
454 #if defined(EXEC_REMTASK_NEEDSSWITCH)
455 krnAddSysCallHandler(KernelBase->kb_PlatformData, &x86_SCSwitchHandler, TRUE, TRUE);
456 krnAddSysCallHandler(KernelBase->kb_PlatformData, &x86_SCReschedTaskHandler, TRUE, TRUE);
457 #endif
458 #if defined(__AROSEXEC_SMP__)
459 /* register the task spinlock syscall */
460 krnAddSysCallHandler(KernelBase->kb_PlatformData, &x86_SCSpinLockHandler, TRUE, TRUE);
461 sysBase->PlatformData.SpinLockCall = ExecSpinLockCall;
463 /* set up the task spinning hooks */
464 Exec_TaskSpinLockForbidHook.h_Entry = (HOOKFUNC)Exec_TaskSpinLockForbidFunc;
465 Exec_TaskSpinLockDisableHook.h_Entry = (HOOKFUNC)Exec_TaskSpinLockDisableFunc;
466 Exec_TaskSpinLockFailHook.h_Entry = (HOOKFUNC)Exec_TaskSpinLockFailFunc;
467 D(bug("[Exec:X86] %s: SpinLock Fail Hook @ 0x%p, Handler @ 0x%p\n", __func__, &Exec_TaskSpinLockFailHook, Exec_TaskSpinLockFailFunc));
468 D(bug("[Exec:X86] %s: SpinLock Forbid Hook @ 0x%p, Handler @ 0x%p\n", __func__, &Exec_TaskSpinLockForbidHook, Exec_TaskSpinLockForbidFunc));
469 #endif
471 Exec_X86CreateIdleTask(SysBase);
473 return TRUE;
476 ADD2INITLIB(Exec_X86Init, -127)