2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
5 Desc: Sets up the ExecBase a bit. (Mostly clearing).
11 #include <aros/asmcall.h>
12 #include <aros/debug.h>
13 #include <aros/kernel.h>
14 #include <clib/macros.h>
15 #include <exec/types.h>
16 #include <exec/lists.h>
17 #include <exec/memory.h>
18 #include <exec/memheaderext.h>
19 #include <exec/resident.h>
20 #include <exec/execbase.h>
21 #include <exec/libraries.h>
22 #include <aros/arossupportbase.h>
26 #include <proto/alib.h>
27 #include <proto/exec.h>
29 #include LC_LIBDEFS_FILE
32 #include "exec_util.h"
33 #include "exec_debug.h"
34 #include "exec_intern.h"
36 #undef kprintf /* This can't be used in the code here */
38 #if defined(__AROSEXEC_SMP__)
39 extern struct Library
*ExecLock__PrepareBase(struct MemHeader
*);
42 extern void *LIBFUNCTABLE
[];
44 extern struct Resident Exec_resident
; /* Need this for lib_IdString */
46 extern void Exec_TrapHandler(ULONG trapNum
, struct ExceptionContext
*ctx
);
47 AROS_LD3(ULONG
, MakeFunctions
,
48 AROS_LDA(APTR
, target
, A0
),
49 AROS_LDA(CONST_APTR
, functionArray
, A1
),
50 AROS_LDA(CONST_APTR
, funcDispBase
, A2
),
51 struct ExecBase
*, SysBase
, 15, Exec
);
53 /* Default finaliser. */
54 static void Exec_TaskFinaliser(void)
56 /* Get rid of current task. */
57 RemTask(GET_THIS_TASK
);
64 void _aros_not_implemented(char *X
)
66 kprintf("Unsupported function at offset -0x%h in %s\n",
67 ABS(*(WORD
*)((&X
)[-1]-2)),
68 ((struct Library
*)(&X
)[-2])->lib_Node
.ln_Name
);
71 struct Library
*PrepareAROSSupportBase (struct MemHeader
*mh
)
73 struct AROSSupportBase
*AROSSupportBase
;
75 AROSSupportBase
= Allocate(mh
, sizeof(struct AROSSupportBase
));
77 AROSSupportBase
->kprintf
= (void *)kprintf
;
78 AROSSupportBase
->rkprintf
= (void *)rkprintf
;
79 AROSSupportBase
->vkprintf
= (void *)vkprintf
;
81 AROSSupportBase
->StdOut
= NULL
;
82 AROSSupportBase
->DebugConfig
= NULL
;
84 return (struct Library
*)AROSSupportBase
;
87 BOOL
IsSysBaseValid(struct ExecBase
*sysbase
)
92 if (((IPTR
)sysbase
) & 0x80000001)
95 if (sysbase
->ChkBase
!= ~(IPTR
)sysbase
)
97 if (sysbase
->SoftVer
!= VERSION_NUMBER
)
100 return GetSysBaseChkSum(sysbase
) == 0xffff;
103 UWORD
GetSysBaseChkSum(struct ExecBase
*sysbase
)
106 UWORD
*p
= (UWORD
*)&sysbase
->SoftVer
;
107 while (p
<= &sysbase
->ChkSum
)
112 void SetSysBaseChkSum(void)
114 SysBase
->ChkBase
=~(IPTR
)SysBase
;
116 SysBase
->ChkSum
= GetSysBaseChkSum(SysBase
) ^ 0xffff;
119 static APTR
allocmem(struct MemHeader
*mh
, ULONG size
, ULONG attributes
)
123 if (IsManagedMem(mh
))
125 struct MemHeaderExt
*mhe
= (struct MemHeaderExt
*)mh
;
128 ret
= mhe
->mhe_Alloc(mhe
, size
, &attributes
);
134 ret
= stdAlloc(mh
, NULL
, size
, attributes
, NULL
, NULL
);
141 * PrepareExecBase() will initialize the ExecBase to default values.
142 * MemHeader and ExecBase itself will already be added to appropriate
143 * lists. You don't need to do this yourself.
145 * WARNING: this routine intentionally sets up global SysBase.
146 * This is done because:
147 * 1. PrepareAROSSupportBase() calls Allocate() which relies on functional SysBase
148 * 2. After PrepareAROSSupportBase() it is possible to call debug output functions
149 * (kprintf() etc). Yes, KernelBase is not set up yet, but remember that kernel.resource
150 * may have patched functions in AROSSupportBase so that KernelBase is not needed there.
151 * 3. Existing ports (at least UNIX-hosted and Windows-hosted) rely on the fact that SysBase is
154 * Resume: please be extremely careful, study existing code, and think five times if you decide to
155 * change this. You WILL break existing ports if you do not modify their code accordingly. There's
156 * nothing really bad in the fact that global SysBase is touched here and changing this does not
157 * really win something.
158 * Pavel Fedin <pavel_fedin@mail.ru>
160 struct ExecBase
*PrepareExecBase(struct MemHeader
*mh
, struct TagItem
*msg
)
163 VOID
**fp
= LIBFUNCTABLE
;
164 APTR ColdCapture
= NULL
, CoolCapture
= NULL
, WarmCapture
= NULL
;
165 APTR KickMemPtr
= NULL
, KickTagPtr
= NULL
, KickCheckSum
= NULL
;
170 D(bug("[Exec] %s()\n", __func__
));
173 * Copy reset proof pointers if old SysBase is valid.
174 * Additional platform-specific code is needed in order to test
175 * address validity. This routine should zero out SysBase if it is invalid.
177 if (IsSysBaseValid(SysBase
))
179 ColdCapture
= SysBase
->ColdCapture
;
180 CoolCapture
= SysBase
->CoolCapture
;
181 WarmCapture
= SysBase
->WarmCapture
;
182 KickMemPtr
= SysBase
->KickMemPtr
;
183 KickTagPtr
= SysBase
->KickTagPtr
;
184 KickCheckSum
= SysBase
->KickCheckSum
;
187 /* Calculate the size of the vector table */
188 while (*fp
++ != (VOID
*) -1) negsize
+= LIB_VECTSIZE
;
190 /* Align library base */
191 negsize
= AROS_ALIGN(negsize
);
193 /* Allocate memory for library base */
194 mem
= allocmem(mh
, negsize
+ sizeof(struct IntExecBase
), MEMF_CLEAR
);
198 SysBase
= mem
+ negsize
;
200 #ifdef HAVE_PREPAREPLATFORM
201 /* Setup platform-specific data */
202 if (!Exec_PreparePlatform(&PD(SysBase
), msg
))
206 /* Setup function vectors */
207 AROS_CALL3(ULONG
, AROS_SLIB_ENTRY(MakeFunctions
, Exec
, 15),
208 AROS_UFCA(APTR
, SysBase
, A0
),
209 AROS_UFCA(CONST_APTR
, LIBFUNCTABLE
, A1
),
210 AROS_UFCA(CONST_APTR
, NULL
, A2
),
211 struct ExecBase
*, SysBase
);
213 /* Set default values */
214 SysBase
->LibNode
.lib_Node
.ln_Type
= NT_LIBRARY
;
215 SysBase
->LibNode
.lib_Node
.ln_Pri
= -100;
216 SysBase
->LibNode
.lib_Node
.ln_Name
= (char *)Exec_resident
.rt_Name
;
217 SysBase
->LibNode
.lib_IdString
= (char *)Exec_resident
.rt_IdString
;
218 SysBase
->LibNode
.lib_Version
= VERSION_NUMBER
;
219 SysBase
->LibNode
.lib_Revision
= REVISION_NUMBER
;
220 SysBase
->LibNode
.lib_OpenCnt
= 1;
221 SysBase
->LibNode
.lib_NegSize
= negsize
;
222 SysBase
->LibNode
.lib_PosSize
= sizeof(struct IntExecBase
);
223 SysBase
->LibNode
.lib_Flags
= LIBF_CHANGED
| LIBF_SUMUSED
;
225 #if defined(__AROSEXEC_SMP__)
226 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase
)->MemListSpinLock
);
228 NEWLIST(&SysBase
->MemList
);
229 SysBase
->MemList
.lh_Type
= NT_MEMORY
;
231 #if defined(__AROSEXEC_SMP__)
232 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase
)->ResourceListSpinLock
);
234 NEWLIST(&SysBase
->ResourceList
);
235 SysBase
->ResourceList
.lh_Type
= NT_RESOURCE
;
237 #if defined(__AROSEXEC_SMP__)
238 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase
)->DeviceListSpinLock
);
240 NEWLIST(&SysBase
->DeviceList
);
241 SysBase
->DeviceList
.lh_Type
= NT_DEVICE
;
243 #if defined(__AROSEXEC_SMP__)
244 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase
)->IntrListSpinLock
);
246 NEWLIST(&SysBase
->IntrList
);
247 SysBase
->IntrList
.lh_Type
= NT_INTERRUPT
;
249 #if defined(__AROSEXEC_SMP__)
250 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase
)->LibListSpinLock
);
252 NEWLIST(&SysBase
->LibList
);
253 SysBase
->LibList
.lh_Type
= NT_LIBRARY
;
255 /* Add exec.library to system library list */
256 ADDHEAD(&SysBase
->LibList
, &SysBase
->LibNode
.lib_Node
);
258 #if defined(__AROSEXEC_SMP__)
259 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase
)->PortListSpinLock
);
261 NEWLIST(&SysBase
->PortList
);
262 SysBase
->PortList
.lh_Type
= NT_MSGPORT
;
264 #if defined(__AROSEXEC_SMP__)
265 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase
)->TaskRunningSpinLock
);
266 NEWLIST(&PrivExecBase(SysBase
)->TaskRunning
);
267 PrivExecBase(SysBase
)->TaskRunning
.lh_Type
= NT_TASK
;
269 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase
)->TaskSpinningLock
);
270 NEWLIST(&PrivExecBase(SysBase
)->TaskSpinning
);
271 PrivExecBase(SysBase
)->TaskSpinning
.lh_Type
= NT_TASK
;
273 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase
)->TaskReadySpinLock
);
275 NEWLIST(&SysBase
->TaskReady
);
276 SysBase
->TaskReady
.lh_Type
= NT_TASK
;
278 #if defined(__AROSEXEC_SMP__)
279 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase
)->TaskWaitSpinLock
);
281 NEWLIST(&SysBase
->TaskWait
);
282 SysBase
->TaskWait
.lh_Type
= NT_TASK
;
284 #if defined(__AROSEXEC_SMP__)
285 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase
)->SemListSpinLock
);
287 NEWLIST(&SysBase
->SemaphoreList
);
288 SysBase
->SemaphoreList
.lh_Type
= NT_SEMAPHORE
;
290 NEWLIST(&SysBase
->ex_MemHandlers
);
292 for (i
= 0; i
< 5; i
++)
294 NEWLIST(&SysBase
->SoftInts
[i
].sh_List
);
295 SysBase
->SoftInts
[i
].sh_List
.lh_Type
= NT_INTERRUPT
;
298 NEWLIST(&PrivExecBase(SysBase
)->ResetHandlers
);
299 NEWLIST(&PrivExecBase(SysBase
)->AllocMemList
);
300 NEWLIST(&PrivExecBase(SysBase
)->AllocatorCtxList
);
302 #if defined(__AROSEXEC_BROKENMEMLOCK__)
303 InitSemaphore(&PrivExecBase(SysBase
)->MemListSem
);
305 InitSemaphore(&PrivExecBase(SysBase
)->LowMemSem
);
307 SysBase
->SoftVer
= VERSION_NUMBER
;
308 #if !defined(__AROSEXEC_SMP__)
309 SCHEDQUANTUM_SET(SCHEDQUANTUM_VALUE
);
311 SysBase
->TaskTrapCode
= Exec_TrapHandler
;
312 SysBase
->TaskExceptCode
= NULL
;
313 SysBase
->TaskExitCode
= Exec_TaskFinaliser
;
314 SysBase
->TaskSigAlloc
= 0xFFFF;
315 SysBase
->TaskTrapAlloc
= 0;
317 /* Parse some arguments from command line */
318 args
= (char *)LibGetTagData(KRN_CmdLine
, 0, msg
);
324 * Enable mungwall before the first AllocMem().
325 * Yes, we have actually already called stdAlloc() once
326 * in order to allocate memory for SysBase itself, however
327 * this is not a real problem because it is never going
330 * We store mungwall setting in private flags because it must not be
331 * switched at runtime (or hard crash will happen).
333 opts
= strcasestr(args
, "mungwall");
335 PrivExecBase(SysBase
)->IntFlags
= EXECF_MungWall
;
337 opts
= strcasestr(args
, "stacksnoop");
339 PrivExecBase(SysBase
)->IntFlags
= EXECF_StackSnoop
;
342 * Parse system runtime debug flags.
343 * These are public. In future they will be editable by prefs program.
344 * However in order to be able to turn them on during early startup,
345 * we apply them also here.
347 opts
= strcasestr(args
, "sysdebug=");
349 SysBase
->ex_DebugFlags
= ParseFlags(&opts
[9], ExecFlagNames
);
352 NEWLIST(&PrivExecBase(SysBase
)->TaskStorageSlots
);
356 /* Add our initial MemHeader */
357 ADDHEAD(&SysBase
->MemList
, &mh
->mh_Node
);
359 /* Bring back saved values (or NULLs) */
360 SysBase
->ColdCapture
= ColdCapture
;
361 SysBase
->CoolCapture
= CoolCapture
;
362 SysBase
->WarmCapture
= WarmCapture
;
363 SysBase
->KickMemPtr
= KickMemPtr
;
364 SysBase
->KickTagPtr
= KickTagPtr
;
365 SysBase
->KickCheckSum
= KickCheckSum
;
367 SysBase
->DebugAROSBase
= PrepareAROSSupportBase(mh
);
368 #if defined(__AROSEXEC_SMP__)
369 PrivExecBase(SysBase
)->ExecLockBase
= NULL
;
370 PrivExecBase(SysBase
)->ExecLockBase
= ExecLock__PrepareBase(mh
);
373 D(bug("[Exec] %s: Preperation complete.\n"));