Add stubs for shutdown/coldreboot, and definitions for core_APIC calls
[AROS.git] / arch / x86_64-pc / exec / exec_init.c
blobc7c2bc2e45f804c5cd0d2ddfd669f3fc99d64560
1 #include <inttypes.h>
2 #include <utility/tagitem.h>
3 #include <exec/resident.h>
4 #include <exec/nodes.h>
5 #include <exec/execbase.h>
6 #include <exec/memory.h>
7 #include <dos/bptr.h>
8 #include <dos/dosextens.h>
10 #include <aros/arossupportbase.h>
11 #include <aros/libcall.h>
12 #include <aros/asmcall.h>
13 #include <aros/debug.h>
14 #include <aros/kernel.h>
16 #include <asm/cpu.h>
17 #include <asm/segments.h>
19 #include <hardware/intbits.h>
20 #include <hardware/custom.h>
22 #include <proto/exec.h>
23 #include <proto/kernel.h>
25 #include <string.h>
26 #include <stdio.h>
28 #include "../bootstrap/multiboot.h"
30 #include "etask.h"
31 #include "exec_intern.h"
32 #include "exec_util.h"
34 #define __text __attribute__((section(".text")))
35 #define __no_ret __attribute__((noreturn))
36 #define __packed __attribute__((packed))
38 extern struct Library * PrepareAROSSupportBase (void);
39 extern const APTR LIBFUNCTABLE[] __text;
40 extern const APTR Exec_FuncTable[] __text;
41 void exec_DefaultTaskExit();
42 extern ULONG Exec_MakeFunctions(APTR, APTR, APTR, APTR);
43 IPTR **exec_RomTagScanner(struct TagItem *msg);
44 int exec_main(struct TagItem *msg, void *entry);
45 UBYTE core_APICGetTotal();
46 UBYTE core_APICGetNumber();
48 AROS_UFP5(void, SoftIntDispatch,
49 AROS_UFPA(ULONG, intReady, D1),
50 AROS_UFPA(struct Custom *, custom, A0),
51 AROS_UFPA(IPTR, intData, A1),
52 AROS_UFPA(IPTR, intCode, A5),
53 AROS_UFPA(struct ExecBase *, SysBase, A6));
55 AROS_UFP5S(void, IntServer,
56 AROS_UFPA(ULONG, intMask, D0),
57 AROS_UFPA(struct Custom *, custom, A0),
58 AROS_UFPA(struct List *, intList, A1),
59 AROS_UFPA(APTR, intCode, A5),
60 AROS_UFPA(struct ExecBase *, SysBase, A6));
63 struct TagItem *krnNextTagItem(const struct TagItem **tagListPtr);
64 struct TagItem *krnFindTagItem(Tag tagValue, const struct TagItem *tagList);
65 IPTR krnGetTagData(Tag tagValue, intptr_t defaultVal, const struct TagItem *tagList);
66 void krnSetTagData(Tag tagValue, intptr_t newtagValue, const struct TagItem *tagList);
69 * First, we will define exec.library (global) to make it usable outside this
70 * file.
72 const char exec_name[] = "exec.library";
74 /* Now ID string as it will be used in a minute in resident structure. */
75 const char exec_idstring[] = "$VER: exec 41.11 (16.12.2000)\r\n";
77 /* We would need also version and revision fields placed somewhere here. */
78 const short exec_Version = 41;
79 const short exec_Revision = 11;
81 const struct __text Resident Exec_resident =
83 RTC_MATCHWORD, /* Magic value used to find resident */
84 &Exec_resident, /* Points to Resident itself */
85 &Exec_resident+1, /* Where could we find next Resident? */
86 0, /* There are no flags!! */
87 41, /* Version */
88 NT_LIBRARY, /* Type */
89 126, /* Very high startup priority. */
90 (STRPTR)exec_name, /* Pointer to name string */
91 (STRPTR)exec_idstring, /* Ditto */
92 exec_main /* Library initializer (for exec this value is irrelevant since we've jumped there at the begining to bring the system up */
95 extern UBYTE core_APICGetTotal();
96 extern UBYTE core_APICGetNumber();
98 /** Screen/Serial Debug **/
101 extern void Exec_SerialRawIOInit();
102 extern void Exec_SerialRawPutChar(UBYTE chr);
104 void scr_RawPutChars(char *, int);
105 void clr();
106 void vesa_init(int width, int height, int depth, void *base);
108 char tab[512];
109 #ifdef rkprintf
110 #undef rkprintf
111 #endif
112 #define rkprintf(x...) scr_RawPutChars(tab, snprintf(tab, 510, x))
114 static ULONG negsize = LIB_VECTSIZE; /* size of vector table */
115 static UBYTE apicready = 0;
117 void _aros_not_implemented(char *string) {}
119 /****/
121 const char exec_chipname[] = "Chip Memory";
122 const char exec_fastname[] = "Fast Memory";
123 const char exec_sysbasename[] = "SysBase";
124 const char exec_kernalname[] = "Kernel Memory";
127 The MMU pages and directories. They are stored at fixed location and may be either reused in the
128 64-bit kernel, or replaced by it. Four PDE directories (PDE2M structures) are enough to map whole
129 4GB address space.
131 static struct PML4E PML4[512] __attribute__((used,aligned(4096)));
132 static struct PDPE PDP[512] __attribute__((used,aligned(4096)));
133 static struct PDE2M PDE[4][512] __attribute__((used,aligned(4096)));
135 void exec_InsertMemory(struct TagItem *msg, uintptr_t lower, uintptr_t upper)
137 struct ExecBase *SysBase = TLS_GET(SysBase); //*(struct ExecBase **)4UL;
139 uintptr_t kernLow = krnGetTagData(KRN_KernelLowest, 0, msg);
140 uintptr_t kernHigh = krnGetTagData(KRN_KernelHighest, 0, msg);
142 /* Check System Memory bounds */
143 if (lower < 0x2000)
145 if (upper < 0x2000)
146 return;
148 lower = 0x2000;
151 if (lower >= 0x100000000L)
152 return;
154 if (upper >= 0x100000000L)
155 upper = 0xffffffff;
157 if ((upper - lower) < 0x1000)
158 return;
160 /* Scenario 1: Kernel and ExecBase areas outside the affected range. */
161 if ((kernHigh < lower || kernLow > upper) &&
162 ((SysBase + sizeof(struct ExecBase)) < lower || (SysBase - negsize) > upper))
164 rkprintf("[exec] Adding %012p - %012p\n", lower, upper);
166 if (lower < 0x01000000)
168 AddMemList(upper-lower+1,
169 MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL | MEMF_24BITDMA,
170 -10,
171 (APTR)lower,
172 (STRPTR)exec_chipname);
174 else
176 AddMemList(upper-lower+1,
177 MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL,
179 (APTR)lower,
180 (STRPTR)exec_fastname);
182 return;
185 /* Scenario 2: Kernel area completely inside the memory region */
186 if (kernLow >= (lower+sizeof(struct MemHeader)+sizeof(struct MemChunk)) && kernHigh <= upper)
188 rkprintf("[exec] Splitting %012p - %012p\n", lower, upper);
190 exec_InsertMemory(msg, lower, kernLow - 1);
191 exec_InsertMemory(msg, kernHigh + 1, upper);
192 return;
194 /* Scenario 3: Kernel in lower portion of memory region */
195 else if (kernLow <= (lower+sizeof(struct MemHeader)+sizeof(struct MemChunk)) && kernHigh <= upper)
197 lower = (kernHigh + 4096) & ~4095;
199 rkprintf("[exec] Adding Upper region %012p - %012p\n", lower, upper);
201 exec_InsertMemory(msg, lower, upper);
202 return;
204 /* Scenario 4: Kernel in upper portion of memory region */
205 else if (kernLow >= (lower+sizeof(struct MemHeader)+sizeof(struct MemChunk)) && kernHigh >= upper)
207 upper = (kernLow - 1) & ~4095;
209 rkprintf("[exec] Adding Lower region %012p - %012p\n", lower, upper);
211 exec_InsertMemory(msg, lower, upper);
212 return;
214 /* Scenario 5: ExecBase completely inside the memory region */
215 else if ((SysBase - negsize) >= (lower+sizeof(struct MemHeader)+sizeof(struct MemChunk)) && (SysBase + sizeof(struct ExecBase)) <= upper)
217 #warning "TODO: Check if sysbase falls within the region being added"
218 // Add 2 chunks ?
220 /* Scenario 6: ExecBase in lower portion of memory region */
221 else if ((SysBase - negsize) <= (lower+sizeof(struct MemHeader)+sizeof(struct MemChunk)) && (SysBase + sizeof(struct ExecBase)) <= upper)
223 // Adjust ..
225 /* Scenario 7: ExecBase in upper portion of memory region */
226 else if ((SysBase - negsize) >= (lower+sizeof(struct MemHeader)+sizeof(struct MemChunk)) && (SysBase + sizeof(struct ExecBase)) >= upper)
228 // Adjust ..
232 int exec_main(struct TagItem *msg, void *entry)
234 struct ExecBase *SysBase;
235 int i;
236 struct vbe_mode *mode;
237 uintptr_t addr_lower;
239 if (msg != (IPTR)-1)
241 /* Launched on BSP */
242 addr_lower = (uintptr_t)(krnGetTagData(KRN_MEMLower, 0, msg) * 1024);
244 if ((mode = (struct vbe_mode *)krnGetTagData(KRN_VBEModeInfo, 0, msg)))
246 vesa_init(mode->x_resolution, mode->y_resolution,
247 mode->bits_per_pixel, (void*)mode->phys_base);
250 clr();
251 rkprintf("[exec] AROS64 - The AROS Research OS, 64-bit version\n[exec] Compiled %s\n", __DATE__);
253 /* Prepare the exec base */
255 void **fp = Exec_FuncTable; //LIBFUNCTABLE; /* pointer to a function in the table */
257 rkprintf("[exec] Preparing the ExecBase...\n");
259 /* Calculate the size of the vector table */
260 while (*fp++ != (APTR) -1) negsize += LIB_VECTSIZE;
262 if (addr_lower != 0)
264 addr_lower = ((addr_lower - (negsize + sizeof(struct ExecBase))) & ~PAGE_MASK);
265 SysBase = (struct ExecBase *)(addr_lower + negsize);
266 krnSetTagData(KRN_MEMLower, ((addr_lower - 1)/1024), msg);
267 addr_lower = (krnGetTagData(KRN_MEMLower, 0, msg) * 1024);
269 else
271 /* Warn that theres no lowmem pages to load execbase into? */
272 SysBase = (struct ExecBase *)(0x1000 + negsize);
275 rkprintf("[exec] Clearing ExecBase [SysBase = %012p]\n", SysBase);
277 /* How about clearing most of ExecBase structure? */
278 bzero(&SysBase->IntVects[0], sizeof(struct ExecBase) - offsetof(struct ExecBase, IntVects[0]));
280 SysBase->KickMemPtr = NULL;
281 SysBase->KickTagPtr = NULL;
282 SysBase->KickCheckSum = NULL;
284 /* How about clearing most of ExecBase structure? */
285 bzero(&SysBase->IntVects[0], sizeof(struct ExecBase) - offsetof(struct ExecBase, IntVects[0]));
288 * Now everything is prepared to store ExecBase at the location 4UL and set
289 * it complement in ExecBase structure
292 rkprintf("[exec] Initializing library...\n");
294 //*(struct ExecBase **)4 = SysBase;
295 SysBase->ChkBase = ~(ULONG)SysBase;
297 /* Store sysbase in TLS */
298 TLS_SET(SysBase, SysBase);
300 /* Set up system stack */
301 // tss->ssp = (extmem) ? extmem : locmem; /* Either in FAST or in CHIP */
302 // SysBase->SysStkUpper = (APTR)stack_end;
303 // SysBase->SysStkLower = (APTR)&stack[0]; /* 64KB of system stack */
305 /* Store memory configuration */
306 SysBase->MaxLocMem = (IPTR)0; //locmem;
307 SysBase->MaxExtMem = (APTR)0; //extmem;
310 * Initialize exec lists. This is done through information table which consist
311 * of offset from begining of ExecBase and type of the list.
313 NEWLIST(&SysBase->MemList);
314 SysBase->MemList.lh_Type = NT_MEMORY;
315 NEWLIST(&SysBase->ResourceList);
316 SysBase->ResourceList.lh_Type = NT_RESOURCE;
317 NEWLIST(&SysBase->DeviceList);
318 SysBase->DeviceList.lh_Type = NT_DEVICE;
319 NEWLIST(&SysBase->LibList);
320 SysBase->LibList.lh_Type = NT_LIBRARY;
321 NEWLIST(&SysBase->PortList);
322 SysBase->PortList.lh_Type = NT_MSGPORT;
323 NEWLIST(&SysBase->TaskReady);
324 SysBase->TaskReady.lh_Type = NT_TASK;
325 NEWLIST(&SysBase->TaskWait);
326 SysBase->TaskWait.lh_Type = NT_TASK;
327 NEWLIST(&SysBase->IntrList);
328 SysBase->IntrList.lh_Type = NT_INTERRUPT;
329 NEWLIST(&SysBase->SemaphoreList);
330 SysBase->SemaphoreList.lh_Type = NT_SIGNALSEM;
331 NEWLIST(&SysBase->ex_MemHandlers);
333 for (i=0; i<5; i++)
335 NEWLIST(&SysBase->SoftInts[i].sh_List);
336 SysBase->SoftInts[i].sh_List.lh_Type = NT_SOFTINT;
340 * Exec.library initializer. Prepares exec.library for future use. All
341 * lists have to be initialized, some values from ROM are copied.
344 SysBase->TaskTrapCode = NULL; //exec_DefaultTrap;
345 SysBase->TaskExceptCode = NULL; //exec_DefaultTrap;
346 SysBase->TaskExitCode = exec_DefaultTaskExit;
347 SysBase->TaskSigAlloc = 0x0000ffff;
348 SysBase->TaskTrapAlloc = 0x8000;
350 /* Prepare values for execBase (like name, type, pri and other) */
352 SysBase->LibNode.lib_Node.ln_Type = NT_LIBRARY;
353 SysBase->LibNode.lib_Node.ln_Pri = 0;
354 SysBase->LibNode.lib_Node.ln_Name = (char *)exec_name;
355 SysBase->LibNode.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
356 SysBase->LibNode.lib_PosSize = sizeof(struct ExecBase);
357 SysBase->LibNode.lib_OpenCnt = 1;
358 SysBase->LibNode.lib_IdString = (char *)exec_idstring;
359 SysBase->LibNode.lib_Version = exec_Version;
360 SysBase->LibNode.lib_Revision = exec_Revision;
362 SysBase->Quantum = 4;
363 SysBase->VBlankFrequency = 50;
364 SysBase->PowerSupplyFrequency = 1;
366 /* Build the jumptable */
367 SysBase->LibNode.lib_NegSize =
368 Exec_MakeFunctions(SysBase, Exec_FuncTable, NULL, SysBase);
370 SumLibrary((struct Library *)SysBase);
372 rkprintf("[exec] Adding memory ..\n");
373 struct mb_mmap *mmap;
374 uint32_t len = krnGetTagData(KRN_MMAPLength, 0, msg);
376 if (len)
378 rkprintf("[exec] Registering MMAP regions (MMAP Length = %d)\n", len);
379 mmap = (struct mb_mmap *)(krnGetTagData(KRN_MMAPAddress, 0, msg));
381 while(len >= sizeof(struct mb_mmap))
383 if (mmap->type == MMAP_TYPE_RAM)
385 uintptr_t addr = (mmap->addr_low | ((intptr_t)mmap->addr_high << 32));
386 uintptr_t size = (mmap->len_low | ((intptr_t)mmap->len_high << 32));
387 uintptr_t tmp;
389 #warning TODO: Add proper handling of the memory above 4GB!
390 if ((addr_lower != 0) &&
391 ((addr_lower >= addr) && ((addr_lower <= (addr+size) ))))
393 rkprintf("[exec] Fixup entry for lowpages [size %012p -> ", size);
394 size = addr_lower - addr;
395 rkprintf("%012p]\n", size);
398 rkprintf("[exec] %012p - %012p\n", addr, addr+size-1);
400 if (addr < 0x01000000 && (addr+size) <= 0x01000000)
402 exec_InsertMemory(msg, addr, addr+size-1);
404 else if (addr < 0x01000000 && (addr+size) > 0x01000000)
406 exec_InsertMemory(msg, addr, 0x00ffffff);
407 exec_InsertMemory(msg, 0x01000000, addr + size - 1);
409 else
411 exec_InsertMemory(msg, addr, addr+size-1);
415 len -= mmap->size+4;
416 mmap = (struct mb_mmap *)(mmap->size + (IPTR)mmap+4);
419 else
421 rkprintf("[exec] Registering mem_lower/mem_upper Memory Region\n");
423 uintptr_t chip_start, chip_end, fast_start, fast_end, tmp;
425 uintptr_t addr_upper = krnGetTagData(KRN_MEMUpper, 0, msg);
427 if (addr_lower > 0)
429 chip_start = 0X2000;
430 chip_end = (addr_lower * 1024) - 1;
432 if (chip_start < chip_end)
434 rkprintf("[exec] Registering Lower Mem Range (%012p - %012p)\n", chip_start, chip_end);
435 exec_InsertMemory(msg, chip_start, chip_end);
439 if (addr_upper > 0)
441 fast_start = 0x0000100000;
442 fast_end = (addr_upper * 1024) + (fast_start - 1);
444 if (fast_start < fast_end)
446 if (fast_end > 0x01000000)
448 rkprintf("[exec] Registering Upper Chip Mem Range (%012p - %012p)\n", fast_start, 0x00ffffff);
449 exec_InsertMemory(msg, fast_start, 0x00ffffff);
450 rkprintf("[exec] Registering Upper Fast Mem Range (%012p - %012p)\n", 0x01000000, fast_end);
451 exec_InsertMemory(msg, 0x01000000, fast_end);
454 else
456 rkprintf("[exec] Registering Upper Mem Range (%012p - %012p)\n", fast_start, fast_end);
457 exec_InsertMemory(msg, fast_start, fast_end);
463 rkprintf("[exec] MemLists (hopefully!) prepaired\n");
465 SumLibrary((struct Library *)SysBase);
467 rkprintf("[exec] SumLibrary on SysBase finished\n");
469 Enqueue(&SysBase->LibList,&SysBase->LibNode.lib_Node);
471 rkprintf("[exec] SysBase Enqueued in Exec Liblist\n");
473 if ((SysBase->DebugAROSBase = PrepareAROSSupportBase()) == NULL)
475 rkprintf("[exec] PrepareAROSSupportBase returns NULL!!!\n");
478 rkprintf("[exec] ExecBase=%012p\n", SysBase);
480 for (i=0; i<16; i++)
482 if( (1<<i) & (INTF_PORTS|INTF_COPER|INTF_VERTB|INTF_EXTER|INTF_SETCLR))
484 struct Interrupt *is;
485 struct SoftIntList *sil;
486 is = AllocMem
488 sizeof(struct Interrupt) + sizeof(struct SoftIntList),
489 MEMF_CLEAR | MEMF_PUBLIC
491 if( is == NULL )
493 rkprintf("[exec] ERROR: Cannot install Interrupt Servers!\n");
495 sil = (struct SoftIntList *)((struct Interrupt *)is + 1);
497 is->is_Code = &IntServer;
498 is->is_Data = sil;
499 NEWLIST((struct List *)sil);
500 SetIntVector(i,is);
502 else
504 struct Interrupt *is;
505 switch (i)
507 case INTB_SOFTINT :
508 is = AllocMem
510 sizeof(struct Interrupt),
511 MEMF_CLEAR | MEMF_PUBLIC
513 if (is == NULL)
515 rkprintf("[exec] Error: Cannot install Interrupt Servers!\n");
516 // Alert(AT_DeadEnd | AN_IntrMem);
518 is->is_Node.ln_Type = NT_SOFTINT; //INTERRUPT;
519 is->is_Node.ln_Pri = 0;
520 is->is_Node.ln_Name = "SW Interrupt Dispatcher";
521 is->is_Data = NULL;
522 is->is_Code = (void *)SoftIntDispatch;
523 SetIntVector(i,is);
524 break;
529 /* Enable interrupts and set int disable level to -1 */
530 asm("sti");
531 SysBase->TDNestCnt = -1;
532 SysBase->IDNestCnt = -1;
534 /* Now it's time to calculate exec checksum. It will be used
535 * in future to distinguish whether we'd had proper execBase
536 * before restart */
538 UWORD sum=0, *ptr = &SysBase->SoftVer;
539 int i=((IPTR)&SysBase->IntVects[0] - (IPTR)&SysBase->SoftVer) / 2,
542 /* Calculate sum for every static part from SoftVer to ChkSum */
543 for (j=0;j < i;j++)
545 sum+=*(ptr++);
548 SysBase->ChkSum = ~sum;
551 rkprintf("[exec] Registering Special Regions in MemList\n");
553 struct MemHeader *mh;
555 if ((mh = AllocMem(sizeof(struct MemHeader) + sizeof(struct MemChunk), MEMF_CLEAR)) != NULL)
557 mh->mh_Node.ln_Type=NT_MEMORY;
558 mh->mh_Node.ln_Pri = -10;
559 mh->mh_Node.ln_Name = exec_sysbasename;
560 mh->mh_Attributes = (MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL | MEMF_24BITDMA);
561 mh->mh_First = mh + sizeof(struct MemHeader);
562 mh->mh_First->mc_Next = NULL;
563 mh->mh_First->mc_Bytes = (negsize + sizeof(struct ExecBase));
564 mh->mh_Lower = (struct MemChunk *)(SysBase - negsize);
565 mh->mh_Upper = (APTR)((UBYTE *)mh->mh_Lower + mh->mh_First->mc_Bytes);
566 mh->mh_Free = 0; /* All used! */
568 Forbid();
569 Enqueue(&SysBase->MemList,&mh->mh_Node);
570 Permit();
573 if ((mh = AllocMem(sizeof(struct MemHeader) + sizeof(struct MemChunk), MEMF_CLEAR)) != NULL)
575 uintptr_t kernLow = krnGetTagData(KRN_KernelLowest, 0, msg);
576 uintptr_t kernHigh = krnGetTagData(KRN_KernelHighest, 0, msg);
578 mh->mh_Node.ln_Type=NT_MEMORY;
579 mh->mh_Node.ln_Pri = -10;
580 mh->mh_Node.ln_Name = exec_kernalname;
581 mh->mh_Attributes = (MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL);
582 mh->mh_First = mh + sizeof(struct MemHeader);
583 mh->mh_First->mc_Next = NULL;
584 mh->mh_First->mc_Bytes = kernHigh - kernLow + 1;
585 mh->mh_Lower = kernLow;
586 mh->mh_Upper = kernHigh;
587 mh->mh_Free = 0; /* All used! */
589 Forbid();
590 Enqueue(&SysBase->MemList,&mh->mh_Node);
591 Permit();
594 rkprintf("[exec] Creating the very first task...\n");
596 /* Create boot task. Sigh, we actually create a Process sized Task,
597 since DOS needs to call things which think it has a Process and
598 we don't want to overwrite memory with something strange do we?
600 We do this until at least we can boot dos more cleanly.
603 struct Task *t;
604 struct MemList *ml;
606 ml = (struct MemList *)AllocMem(sizeof(struct MemList), MEMF_PUBLIC|MEMF_CLEAR);
607 t = (struct Task *) AllocMem(sizeof(struct Process), MEMF_PUBLIC|MEMF_CLEAR);
609 if( !ml || !t )
611 rkprintf("[exec] ERROR: Cannot create Boot Task!\n");
613 ml->ml_NumEntries = 1;
614 ml->ml_ME[0].me_Addr = t;
615 ml->ml_ME[0].me_Length = sizeof(struct Process);
617 NEWLIST(&t->tc_MemEntry);
618 NEWLIST(&((struct Process *)t)->pr_MsgPort.mp_MsgList);
620 /* It's the boot process that RunCommand()s the boot shell, so we
621 must have this list initialized */
622 NEWLIST((struct List *)&((struct Process *)t)->pr_LocalVars);
624 AddHead(&t->tc_MemEntry,&ml->ml_Node);
626 t->tc_Node.ln_Name = exec_name;
627 t->tc_Node.ln_Pri = 0;
628 t->tc_Node.ln_Type = NT_TASK;
629 t->tc_State = TS_RUN;
630 t->tc_SigAlloc = 0xFFFF;
631 t->tc_SPLower = 0; /* This is the system's stack */
632 t->tc_SPUpper = (APTR)~0UL;
633 t->tc_Flags |= TF_ETASK;
635 if (t->tc_Flags & TF_ETASK)
637 t->tc_UnionETask.tc_ETask = AllocVec
639 sizeof(struct IntETask),
640 MEMF_ANY|MEMF_CLEAR
643 if (!t->tc_UnionETask.tc_ETask)
645 rkprintf("[exec] Not enough memory for first task\n");
648 /* Initialise the ETask data. */
649 InitETask(t, t->tc_UnionETask.tc_ETask);
651 GetIntETask(t)->iet_Context = AllocTaskMem(t
652 , SIZEOF_ALL_REGISTERS
653 , MEMF_PUBLIC|MEMF_CLEAR
656 if (!GetIntETask(t)->iet_Context)
658 rkprintf("[exec] Not enough memory for first task\n");
662 SysBase->ThisTask = t;
665 rkprintf("[exec] Done. SysBase->ThisTask = 0x%012p\n[exec] Leaving supervisor mode\n", SysBase->ThisTask);
667 asm volatile (
668 "mov %[user_ds],%%ds\n\t" // Load DS and ES
669 "mov %[user_ds],%%es\n\t"
670 "mov %%rsp,%%r12\n\t"
671 "pushq %[ds]\n\t" // SS
672 "pushq %%r12\n\t" // rSP
673 "pushq $0x3002\n\t" // rFLANGS
674 "pushq %[cs]\n\t" // CS
675 "pushq $1f\n\t iretq\n 1:"
676 ::[user_ds]"r"(USER_DS),[ds]"i"(USER_DS),[cs]"i"(USER_CS):"r12");
677 rkprintf("[exec] Done?! Still here?\n");
679 SysBase->TDNestCnt++;
681 Permit();
683 BOOL _debug = FALSE;
684 struct TagItem *tag = krnFindTagItem(KRN_CmdLine, msg);
685 if (tag)
687 STRPTR cmd;
688 ULONG temp;
689 cmd = stpblk(tag->ti_Data);
690 while(cmd[0])
692 /* Split the command line */
693 temp = strcspn(cmd," ");
694 if (strncmp(cmd, "DEBUG", 5)==0)
696 _debug = TRUE;
697 SetFunction(&SysBase->LibNode, -84*LIB_VECTSIZE, AROS_SLIB_ENTRY(SerialRawIOInit, Exec));
698 SetFunction(&SysBase->LibNode, -86*LIB_VECTSIZE, AROS_SLIB_ENTRY(SerialRawPutChar, Exec));
699 break;
701 cmd = stpblk(cmd+temp);
705 /* Scan for valid RomTags */
706 SysBase->ResModules = exec_RomTagScanner(msg);
707 apicready = 1;
709 rkprintf("[exec] InitCode(RTF_SINGLETASK)\n");
710 if (!(_debug))
712 rkprintf("\3");
714 InitCode(RTF_SINGLETASK, 0);
716 UBYTE apictotal;
717 if ((apictotal = core_APICGetTotal()) > 1)
719 rkprintf("[exec] Waiting for %d APICs to initialise ..\n", apictotal-1);
720 while (apicready < apictotal)
722 rkprintf("[exec] %d of %d APICs Ready ..\n", apicready, apictotal);
726 rkprintf("[exec] InitCode(RTF_COLDSTART)\n");
727 InitCode(RTF_COLDSTART, 0);
729 rkprintf("[exec] ERROR: System Boot Failed? Halting ...\n");
730 while(1) asm volatile("hlt");
732 else
734 /* Launched on AP */
735 UBYTE _APICNO = core_APICGetNumber();
736 apicready += 1;
737 rkprintf("[exec] exec_main[%d]: APIC No. %d Going IDLE (Halting)...\n", _APICNO, _APICNO);
738 while(1) asm volatile("hlt");
740 return 0;
744 void exec_DefaultTaskExit()
746 struct ExecBase *SysBase = TLS_GET(SysBase); //*(struct ExecBase **)4UL;
747 RemTask(SysBase->ThisTask);
751 AROS_LH1(struct ExecBase *, open,
752 AROS_LHA(ULONG, version, D0),
753 struct ExecBase *, SysBase, 1, Exec)
755 AROS_LIBFUNC_INIT
757 /* I have one more opener. */
758 SysBase->LibNode.lib_OpenCnt++;
759 return SysBase;
761 AROS_LIBFUNC_EXIT
764 AROS_LH0(BPTR, close,
765 struct ExecBase *, SysBase, 2, Exec)
767 AROS_LIBFUNC_INIT
769 /* I have one fewer opener. */
770 SysBase->LibNode.lib_OpenCnt--;
771 return 0;
772 AROS_LIBFUNC_EXIT
775 AROS_LH0I(int, null,
776 struct ExecBase *, SysBase, 4, Exec)
778 AROS_LIBFUNC_INIT
779 return 0;
780 AROS_LIBFUNC_EXIT
784 * RomTag scanner.
786 * This function scans kernel for existing Resident modules. If two modules
787 * with the same name are found, the one with higher version or priority wins.
789 * After building list of kernel modules, the KickTagPtr and KickMemPtr are
790 * checksummed. If checksum is proper and all memory pointed in KickMemPtr may
791 * be allocated, then all modules from KickTagPtr are added to RT list
793 * Afterwards the proper RomTagList is created (see InitCode() for details) and
794 * memory after list and nodes is freed.
797 struct rt_node
799 struct Node node;
800 struct Resident *module;
803 IPTR **exec_RomTagScanner(struct TagItem *msg)
805 struct ExecBase *SysBase = TLS_GET(SysBase); //*(struct ExecBase **)4UL;
807 struct List rtList; /* List of modules */
808 UWORD *ptr = (UWORD*)krnGetTagData(KRN_KernelLowest, 0, msg); /* Start looking here */
809 UWORD *maxptr = (UWORD*)krnGetTagData(KRN_KernelHighest, 0, msg);
810 struct Resident *res; /* module found */
812 int i;
813 IPTR **RomTag;
815 /* Initialize list */
816 NEWLIST(&rtList);
818 rkprintf("[exec] Resident modules (addr: pri version name):\n");
820 /* Look in whole kernel for resident modules */
823 /* Do we have RTC_MATCHWORD? */
824 if (*ptr == RTC_MATCHWORD)
826 /* Yes, assume we have Resident */
827 res = (struct Resident *)ptr;
829 /* Does rt_MatchTag point to Resident? */
830 if (res == res->rt_MatchTag)
832 /* Yes, it is Resident module */
833 struct rt_node *node;
835 /* Check if there is module with such name already */
836 node = (struct rt_node*)FindName(&rtList, res->rt_Name);
837 if (node)
839 /* Yes, there was such module. It it had lower pri then replace it */
840 if (node->node.ln_Pri <= res->rt_Pri)
842 /* If they have the same Pri but new one has higher Version, replace */
843 if ((node->node.ln_Pri == res->rt_Pri) &&
844 (node->module->rt_Version < res->rt_Version))
846 node->node.ln_Pri = res->rt_Pri;
847 node->module = res;
851 else
853 /* New module. Allocate some memory for it */
854 node = (struct rt_node *)
855 AllocMem(sizeof(struct rt_node),MEMF_PUBLIC|MEMF_CLEAR);
857 if (node)
859 node->node.ln_Name = res->rt_Name;
860 node->node.ln_Pri = res->rt_Pri;
861 node->module = res;
863 Enqueue(&rtList,(struct Node*)node);
866 ptr+=sizeof(struct Resident)/sizeof(UWORD);
867 continue;
871 /* Get next address... */
872 ptr++;
873 } while (ptr < maxptr);
876 * By now we have valid (and sorted) list of kernel resident modules.
878 * Now, we will have to analyze used-defined RomTags (via KickTagPtr and
879 * KickMemPtr)
881 #warning "TODO: Implement external modules!"
883 * Everything is done now. Allocate buffer for normal RomTag and convert
884 * list to RomTag
887 ListLength(&rtList,i); /* Get length of the list */
889 RomTag = AllocMem((i+1)*sizeof(IPTR),MEMF_PUBLIC | MEMF_CLEAR);
891 if (RomTag)
893 int j;
894 struct rt_node *n;
896 for (j=0; j<i; j++)
898 n = (struct rt_node *)RemHead(&rtList);
899 rkprintf("[exec] + 0x%012lx: %4d %3d \"%s\"\n",
900 n->module,
901 n->node.ln_Pri,
902 n->module->rt_Version,
903 n->node.ln_Name);
904 RomTag[j] = (IPTR*)n->module;
905 FreeMem(n, sizeof(struct rt_node));
907 RomTag[i] = 0;
910 return RomTag;
916 We temporarily redefine kprintf() so we use the real version in case
917 we have one of these two fn's called before AROSSupportBase is ready.
920 #undef kprintf
921 #undef rkprintf
922 #undef vkprintf
924 #define kprintf(x...)
925 #define rkprintf(x...)
926 #define vkprintf(x...)
928 struct Library * PrepareAROSSupportBase(void)
930 struct AROSSupportBase *AROSSupportBase;
931 struct ExecBase *SysBase = TLS_GET(SysBase); //*(struct ExecBase **)4UL;
933 if ((AROSSupportBase = AllocMem(sizeof(struct AROSSupportBase), MEMF_CLEAR)) != NULL)
935 AROSSupportBase->kprintf = (void *)kprintf;
936 AROSSupportBase->rkprintf = (void *)rkprintf;
937 AROSSupportBase->vkprintf = (void *)vkprintf;
939 NEWLIST(&AROSSupportBase->AllocMemList);
941 else
943 #warning "FIXME What should we do if we fail to allocate AROSSupportBase!?!?"
946 #warning "FIXME Add code to read in the debug options"
948 return (struct Library *)AROSSupportBase;
951 /* IntServer:
952 This interrupt handler will send an interrupt to a series of queued
953 interrupt servers. Servers should return D0 != 0 (Z clear) if they
954 believe the interrupt was for them, and no further interrupts will
955 be called. This will only check the value in D0 for non-m68k systems,
956 however it SHOULD check the Z-flag on 68k systems.
958 Hmm, in that case I would have to separate it from this file in order
959 to replace it...
961 AROS_UFH5S(void, IntServer,
962 AROS_UFHA(ULONG, intMask, D0),
963 AROS_UFHA(struct Custom *, custom, A0),
964 AROS_UFHA(struct List *, intList, A1),
965 AROS_UFHA(APTR, intCode, A5),
966 AROS_UFHA(struct ExecBase *, SysBase, A6))
968 AROS_USERFUNC_INIT
970 struct Interrupt * irq;
972 ForeachNode(intList, irq)
974 if( AROS_UFC4(int, irq->is_Code,
975 AROS_UFCA(struct Custom *, custom, A0),
976 AROS_UFCA(APTR, irq->is_Data, A1),
977 AROS_UFCA(APTR, irq->is_Code, A5),
978 AROS_UFCA(struct ExecBase *, SysBase, A6)
980 break;
983 AROS_USERFUNC_EXIT