2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Early bootup section
10 i386-pc AROS MemoryMap:
12 First 4KB of RAM (page 0x0000-0x0FFF) are READ ONLY!
14 +------------+-----------+-------------------------------------------------+
15 | address | length | description |
16 +------------+-----------+-------------------------------------------------+
17 | System page. Read only! Addresses undefined here are not allowed!!!! |
18 +------------------------+-------------------------------------------------+
19 | 0x00000000 | 0x0000100 | Extended BIOS data area preserved |
20 | 0x00000004 | 0x0000004 | SysBase pointer |
21 | 0x00000100 | 0x0000800 | Not used |
22 | 0x00000900 | 0x0000004 | INT server! cached_irq_mask |
23 | 0x00000904 | 0x0000004 | INT server! io_apic_irqs |
24 | 0x00000940 | 0x0000001 | INT server! softblock |
25 | 0x00000a00 | 0x0000200 | INT server! irq_desc[] |
26 | 0x00000c00 | 0x0000300 | Temporary stack for warm reboot |
27 +------------+-----------+-------------------------------------------------+
28 | 0x00001000 | ......... | System RAM. Initially bootstrap resides here. |
29 | 0x000a0000 | 0x0060000 | Data reserved for BIOS, VGA and some MMIO cards |
30 1MB| 0x00100000 | ......... | System RAM divided into DMA and rest. |
31 +------------+-----------+-------------------------------------------------+
34 #include <exec/resident.h>
35 #include <exec/types.h>
36 #include <exec/nodes.h>
37 #include <exec/execbase.h>
38 #include <exec/memory.h>
39 #include <hardware/intbits.h>
40 #include <asm/segments.h>
41 #include <asm/linkage.h>
42 #include <asm/ptrace.h>
43 #include <dos/dosextens.h>
45 #include <aros/arossupportbase.h>
46 #include <aros/asmcall.h>
47 #include <aros/config.h>
49 #include <aros/kernel.h>
53 #include <aros/debug.h>
54 #include <aros/multiboot.h>
56 #include <utility/tagitem.h>
58 #include <hardware/custom.h>
59 #include <resources/acpi.h>
61 #include <proto/alib.h>
62 #include <proto/exec.h>
70 #include LC_LIBDEFS_FILE
73 #include "exec_intern.h"
74 #include "exec_debug.h"
75 #include "exec_util.h"
76 #include "intservers.h"
80 /* As long as we don't have CPU detection routine, assume FPU to be present */
85 * Some macro definitions. __text will place given structure in .text section.
86 * __no_ret will force function type to be no-return function. __packed will
87 * force any structure to be non-aligned (we don't need alignment in native
91 #define __text __attribute__((section(".text")))
92 #define __no_ret __attribute__((noreturn))
93 #define __packed __attribute__((packed))
96 ({ long val; asm volatile("mov %%" #reg ",%0":"=r"(val)); val; })
98 #define wrcr(reg, val) \
99 do { asm volatile("mov %0,%%" #reg::"r"(val)); } while(0)
101 #define cpuid(num, eax, ebx, ecx, edx) \
102 do { asm volatile("cpuid":"=a"(eax),"=b"(ebx),"=c"(ecx),"=d"(edx):"a"(num)); } while(0)
107 AROS_UFP3S(struct ExecBase
*, exec_init
,
108 AROS_UFPA(struct MemHeader
*, mh
, D0
),
109 AROS_UFPA(struct TagItem
*, tagList
, A0
),
110 AROS_UFPA(struct ExecBase
*, sysBase
, A6
));
114 extern const UBYTE LIBEND __text
; /* Somewhere in library */
116 extern void AROS_SLIB_ENTRY(SerialRawIOInit
, Exec
, 84)();
117 extern void AROS_SLIB_ENTRY(SerialRawPutChar
, Exec
, 86)(UBYTE chr
);
118 extern void AROS_SLIB_ENTRY(MemoryRawIOInit
, Exec
, 84)();
119 extern void AROS_SLIB_ENTRY(MemoryRawPutChar
, Exec
, 86)(UBYTE chr
);
121 extern void AROS_SLIB_ENTRY(Switch_FPU
, Exec
, 9)();
122 extern void AROS_SLIB_ENTRY(PrepareContext_FPU
, Exec
, 6)();
123 extern void AROS_SLIB_ENTRY(Dispatch_FPU
, Exec
, 10)();
125 extern void AROS_SLIB_ENTRY(Switch_SSE
, Exec
, 9)();
126 extern void AROS_SLIB_ENTRY(PrepareContext_SSE
, Exec
, 6)();
127 extern void AROS_SLIB_ENTRY(Dispatch_SSE
, Exec
, 10)();
128 extern void AROS_SLIB_ENTRY(CopyMem_SSE
, Exec
, 104)();
131 * First, we will define exec.library (global) to make it usable outside this
134 const char exec_name
[] __text
= "exec.library";
135 /* Now ID string as it will be used in a minute in resident structure. */
136 const char exec_idstring
[] __text
= VERSION_STRING
;
139 * The RomTag structure. It has to be placed inside .text block as there will
140 * be no public RomTagList. In future we may change RTC_MATCHWORD to be machine
143 const struct Resident Exec_resident __text
=
145 RTC_MATCHWORD
, /* Magic value used to find resident */
146 &Exec_resident
, /* Points to Resident itself */
147 (APTR
)&LIBEND
, /* Where could we find next Resident? */
148 0, /* There are no flags!! */
149 VERSION_NUMBER
, /* Version */
150 NT_LIBRARY
, /* Type */
151 126, /* Very high startup priority. */
152 (char *)exec_name
, /* Pointer to name string */
153 (char *)exec_idstring
, /* Ditto */
154 exec_init
/* Library initializer */
158 /* These defines used to keep control over interrupt server */
159 asm(".globl cached_irq_mask\n\t"
160 ".globl io_apic_irqs\n\t"
161 ".globl softblock\n\t"
162 ".globl irq_desc\n\t"
163 ".set cached_irq_mask, 0x00000900\n\t"
164 ".set io_apic_irqs, 0x00000904\n\t"
165 ".set softblock, 0x00000940\n\t"
166 ".set irq_desc, 0x00000a00");
168 AROS_UFH3S(struct ExecBase
*, exec_init
,
169 AROS_UFHA(struct MemHeader
*, mh
, D0
),
170 AROS_UFHA(struct TagItem
*, tagList
, A0
),
171 AROS_UFHA(struct ExecBase
*, origSysBase
, A6
)
177 return PrepareExecBase(mh
, tagList
);
184 void exec_boot(struct TagItem
*msg
)
186 char *cmdline
= (char *)LibGetTagData(KRN_CmdLine
, 0, msg
);
189 bug("Initializing library...");
193 if( (1<<i
) & (INTF_PORTS
|INTF_COPER
|INTF_VERTB
|INTF_EXTER
|INTF_SETCLR
))
195 struct Interrupt
*is
;
196 struct SoftIntList
*sil
;
199 sizeof(struct Interrupt
) + sizeof(struct SoftIntList
),
200 MEMF_CLEAR
| MEMF_PUBLIC
204 bug("ERROR: Cannot install Interrupt Servers!\n");
206 sil
= (struct SoftIntList
*)((struct Interrupt
*)is
+ 1);
208 is
->is_Code
= &IntServer
;
210 NEWLIST((struct List
*)sil
);
215 struct Interrupt
*is
;
221 sizeof(struct Interrupt
),
222 MEMF_CLEAR
| MEMF_PUBLIC
226 bug("Error: Cannot install Interrupt Servers!\n");
227 // Alert(AT_DeadEnd | AN_IntrMem);
229 is
->is_Node
.ln_Type
= NT_SOFTINT
; //INTERRUPT;
230 is
->is_Node
.ln_Pri
= 0;
231 is
->is_Node
.ln_Name
= "SW Interrupt Dispatcher";
233 is
->is_Code
= (void *)SoftIntDispatch
;
241 bug("IRQ services initialized\n");
243 /* Enable interrupts and set int disable level to -1 */
245 SysBase
->TDNestCnt
= -1;
246 SysBase
->IDNestCnt
= -1;
248 bug("Creating the very first task...");
250 /* Complete boot task. */
252 struct Task
*t
= SysBase
->ThisTask
;
255 ml
= (struct MemList
*)AllocMem(sizeof(struct MemList
), MEMF_PUBLIC
|MEMF_CLEAR
);
259 bug("ERROR: Cannot create Boot Task!\n");
262 ml
->ml_NumEntries
= 1;
263 ml
->ml_ME
[0].me_Addr
= t
;
264 ml
->ml_ME
[0].me_Length
= sizeof(struct Process
);
266 AddHead(&t
->tc_MemEntry
,&ml
->ml_Node
);
268 t
->tc_Flags
|= TF_ETASK
;
269 t
->tc_UnionETask
.tc_ETask
= AllocVec(sizeof(struct IntETask
), MEMF_CLEAR
);
271 if (!t
->tc_UnionETask
.tc_ETask
)
273 bug("Not enough memory for first task\n");
277 /* Initialise the ETask data. */
278 InitETask(t
, t
->tc_UnionETask
.tc_ETask
);
280 GetIntETask(t
)->iet_Context
= AllocTaskMem(t
, SIZEOF_ALL_REGISTERS
, MEMF_PUBLIC
|MEMF_CLEAR
);
282 if (!GetIntETask(t
)->iet_Context
)
284 bug("Not enough memory for first task\n");
287 t
->tc_UnionETask
.tc_ETask
->et_Parent
= NULL
;
293 Check whether the CPU supports SSE and FXSAVE.
295 Dirty check, without use of any defines and human readable constants. The
296 cpuid instruction with %eax=1 will return some essential cpu informations in %edx back,
298 - bit 24: CPU does support FXSAVE and FXRSTOR for MMX/FPU/SSE context saving and restoring
299 - bit 25: CPU supports SSE
300 - bit 26: CPU supports SSE2
304 cpuid(1, v1
,v2
,v3
,v4
);
306 bug("cpuid 1 = %08x %08x %08x %08x\n", v1
, v2
, v3
, v4
);
310 bug("The CPU supports FXSAVE and FXRSTOR. Good.\n");
311 bug("CPU Supports ");
313 switch ((v4
>> 25) & 3)
320 /* Patch exec with some SSE-aware functions */
321 SetFunction(&SysBase
->LibNode
, -6*LIB_VECTSIZE
, AROS_SLIB_ENTRY(PrepareContext_SSE
, Exec
, 6));
322 SetFunction(&SysBase
->LibNode
, -9*LIB_VECTSIZE
, AROS_SLIB_ENTRY(Switch_SSE
, Exec
, 9));
323 SetFunction(&SysBase
->LibNode
, -10*LIB_VECTSIZE
, AROS_SLIB_ENTRY(Dispatch_SSE
, Exec
, 10));
324 SetFunction(&SysBase
->LibNode
, -104*LIB_VECTSIZE
, AROS_SLIB_ENTRY(CopyMem_SSE
, Exec
, 104));
325 SetFunction(&SysBase
->LibNode
, -105*LIB_VECTSIZE
, AROS_SLIB_ENTRY(CopyMem_SSE
, Exec
, 104));
326 /* tell the CPU that we will support SSE */
327 wrcr(cr4
, rdcr(cr4
) | (3 << 9));
328 /* Clear the EM and MP flags of CR0 */
329 wrcr(cr0
, rdcr(cr0
) & ~6);
330 bug("SSE enabled.\n");
335 Ha! Bloody PentiumII does supports MMX/FPU/SSE saving instructions,
336 but it does not support SSE
338 bug("no SSE. Sorry :)\n");
345 SetFunction(&SysBase
->LibNode
, -6*LIB_VECTSIZE
, AROS_SLIB_ENTRY(PrepareContext_FPU
, Exec
, 6));
346 SetFunction(&SysBase
->LibNode
, -9*LIB_VECTSIZE
, AROS_SLIB_ENTRY(Switch_FPU
, Exec
, 9));
347 SetFunction(&SysBase
->LibNode
, -10*LIB_VECTSIZE
, AROS_SLIB_ENTRY(Dispatch_FPU
, Exec
, 10));
349 bug("FPU enabled.\n");
354 bug("Jumping out from Supervisor mode...");
358 asm("mov %0,%%ds\n\t" /* User DS */
359 "mov %0,%%es\n\t" /* User ES */
360 "movl %%esp,%%ebx\n\t" /* Hold the esp value before pushing! */
361 "pushl %0\n\t" /* User SS */
362 "pushl %%ebx\n\t" /* Stack frame */
363 "pushl $0x3002\n\t" /* IOPL:3 */
364 "pushl %1\n\t" /* User CS */
365 "pushl $1f\n\t" /* Entry address */
366 "iret\n" /* Go down to the user mode */
367 "1:\tsti" /* Enable interrupts */
369 : "eax"(USER_DS
),"ecx"(USER_CS
));
371 # define _stringify(x) #x
372 # define stringify(x) _stringify(x)
374 asm("movl $" stringify(USER_DS
) ",%%eax\n\t"
375 "mov %%eax,%%ds\n\t" /* User DS */
376 "mov %%eax,%%es\n\t" /* User ES */
377 "movl %%esp,%%ebx\n\t" /* Hold the esp value before pushing! */
378 "pushl %%eax\n\t" /* User SS */
379 "pushl %%ebx\n\t" /* Stack frame */
380 "pushl $0x3002\n\t" /* IOPL:3 */
381 "pushl $" stringify(USER_CS
) "\n\t" /* User CS */
382 "pushl $1f\n\t" /* Entry address */
383 "iret\n" /* Go down to the user mode */
384 "1:\tsti":::"eax","ebx"); /* Enable interrupts */
392 SysBase
->TDNestCnt
++;
396 * Enable type of debug output chosen by user.
397 * 'serial' is not handled in libbootconsole.
399 if (strstr(cmdline
, "debug=memory"))
401 SetFunction(&SysBase
->LibNode
, -84 * LIB_VECTSIZE
,
402 AROS_SLIB_ENTRY(MemoryRawIOInit
, Exec
, 84));
403 SetFunction(&SysBase
->LibNode
, -86 * LIB_VECTSIZE
,
404 AROS_SLIB_ENTRY(MemoryRawPutChar
, Exec
, 86));
408 if (SysBase
->CoolCapture
)
410 void (*p
)() = SysBase
->CoolCapture
;
412 bug("Executing CoolCapture at 0x%p\n", p
);
416 InitCode(RTF_COLDSTART
, 0);
419 /* Small delay routine used by exec_cinit initializer */
420 asm("\ndelay:\t.short 0x00eb\n\tret");
422 AROS_LH1(struct ExecBase
*, open
,
423 AROS_LHA(ULONG
, version
, D0
),
424 struct ExecBase
*, SysBase
, 1, Exec
)
428 /* I have one more opener. */
429 SysBase
->LibNode
.lib_OpenCnt
++;
434 AROS_LH0(BPTR
, close
,
435 struct ExecBase
*, SysBase
, 2, Exec
)
439 /* I have one fewer opener. */
440 SysBase
->LibNode
.lib_OpenCnt
--;
446 struct ExecBase
*, SysBase
, 3, Exec
)
454 struct ExecBase
*, SysBase
, 4, Exec
)