c41feaf110e5d16c7caf4609dc39270e18c8276a
[reactos.git] / reactos / ntoskrnl / ke / powerpc / kiinit.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/powerpc/kiinit.c
5 * PURPOSE: Kernel Initialization for x86 CPUs
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Art Yerkes (ayerkes@speakeasy.net)
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntoskrnl.h>
13
14 //#define NDEBUG
15 #include <debug.h>
16 #include "ppcmmu/mmu.h"
17
18 /* GLOBALS *******************************************************************/
19
20 /* Ku bit should be set, so that we get the best options for page protection */
21 #define PPC_SEG_Ku 0x40000000
22 #define PPC_SEG_Ks 0x20000000
23
24 extern LOADER_MODULE KeLoaderModules[64];
25 extern ULONG KeLoaderModuleCount;
26 extern ULONG_PTR MmFreeLdrLastKernelAddress;
27 KPRCB PrcbData[MAXIMUM_PROCESSORS];
28 /* BIOS Memory Map. Not NTLDR-compliant yet */
29 extern ULONG KeMemoryMapRangeCount;
30 extern ADDRESS_RANGE KeMemoryMap[64];
31
32 /* FUNCTIONS *****************************************************************/
33 /*
34 * Trap frame:
35 * r0 .. r32
36 * lr, ctr, srr0, srr1, dsisr
37 */
38
39 extern int syscall_start[], syscall_end, KiDecrementerTrapHandler[],
40 KiDecrementerTrapHandlerEnd;
41
42 VOID
43 NTAPI
44 KiSetupSyscallHandler()
45 {
46 paddr_t handler_target;
47 int *source;
48 for(source = syscall_start, handler_target = 0xc00;
49 source < &syscall_end;
50 source++, handler_target += sizeof(int))
51 SetPhys(handler_target, *source);
52 }
53
54 VOID
55 NTAPI
56 KiSetupDecrementerTrap()
57 {
58 paddr_t handler_target;
59 int *source;
60
61 /* Turn off EE bit while redefining dec trap */
62 _disable();
63
64 for(source = KiDecrementerTrapHandler, handler_target = 0x900;
65 source != &KiDecrementerTrapHandlerEnd;
66 source++, handler_target += sizeof(int))
67 SetPhys(handler_target, *source);
68
69 DPRINT("CurrentThread %08x IdleThread %08x\n",
70 KeGetCurrentThread(), KeGetCurrentPrcb()->IdleThread);
71
72 /* Kick decmrenter! */
73 __asm__("mtdec %0" : : "r" (0));
74
75 /* Enable interrupts! */
76 _enable();
77 }
78
79 VOID
80 NTAPI
81 KiInitializePcr(IN ULONG ProcessorNumber,
82 IN PKIPCR Pcr,
83 IN PKTHREAD IdleThread,
84 IN PVOID DpcStack)
85 {
86 Pcr->MajorVersion = PCR_MAJOR_VERSION;
87 Pcr->MinorVersion = PCR_MINOR_VERSION;
88 Pcr->CurrentIrql = PASSIVE_LEVEL;
89 Pcr->PrcbData = &PrcbData[ProcessorNumber];
90 Pcr->PrcbData->MajorVersion = PRCB_MAJOR_VERSION;
91 Pcr->PrcbData->MinorVersion = 0;
92 Pcr->PrcbData->Number = 0; /* UP for now */
93 Pcr->PrcbData->SetMember = 1;
94 #if DBG
95 Pcr->PrcbData->BuildType = PRCB_BUILD_DEBUG;
96 #else
97 Pcr->PrcbData->BuildType = 0;
98 #endif
99 Pcr->PrcbData->DpcStack = DpcStack;
100 KeGetPcr()->Prcb = Pcr->PrcbData;
101 KiProcessorBlock[ProcessorNumber] = Pcr->PrcbData;
102 }
103
104 extern ULONG KiGetFeatureBits();
105 extern VOID KiSetProcessorType();
106 extern VOID KiGetCacheInformation();
107
108 VOID
109 NTAPI
110 KiInitializeKernel(IN PKPROCESS InitProcess,
111 IN PKTHREAD InitThread,
112 IN PVOID IdleStack,
113 IN PKPRCB Prcb,
114 IN CCHAR Number,
115 IN PLOADER_PARAMETER_BLOCK LoaderBlock)
116 {
117 ULONG FeatureBits;
118 LARGE_INTEGER PageDirectory;
119 PVOID DpcStack;
120
121 /* Detect and set the CPU Type */
122 KiSetProcessorType();
123
124 /* Initialize the Power Management Support for this PRCB */
125 PoInitializePrcb(Prcb);
126
127 /* Get the processor features for the CPU */
128 FeatureBits = KiGetFeatureBits();
129
130 /* Save feature bits */
131 Prcb->FeatureBits = FeatureBits;
132
133 /* Get cache line information for this CPU */
134 KiGetCacheInformation();
135
136 /* Initialize spinlocks and DPC data */
137 KiInitSpinLocks(Prcb, Number);
138
139 /* Check if this is the Boot CPU */
140 if (!Number)
141 {
142 /* Set Node Data */
143 KeNodeBlock[0] = &KiNode0;
144 Prcb->ParentNode = KeNodeBlock[0];
145 KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;
146
147 /* Set boot-level flags */
148 KeProcessorArchitecture = 0;
149 KeProcessorLevel = (USHORT)Prcb->CpuType;
150 KeFeatureBits = FeatureBits;
151
152 /* Set the current MP Master KPRCB to the Boot PRCB */
153 Prcb->MultiThreadSetMaster = Prcb;
154
155 /* Lower to APC_LEVEL */
156 KeLowerIrql(APC_LEVEL);
157
158 /* Initialize portable parts of the OS */
159 KiInitSystem();
160
161 /* Initialize the Idle Process and the Process Listhead */
162 InitializeListHead(&KiProcessListHead);
163 PageDirectory.QuadPart = 0;
164 KeInitializeProcess(InitProcess,
165 0,
166 0xFFFFFFFF,
167 &PageDirectory,
168 TRUE);
169 InitProcess->QuantumReset = MAXCHAR;
170 }
171 else
172 {
173 /* FIXME */
174 DPRINT1("SMP Boot support not yet present\n");
175 }
176
177 /* Setup the Idle Thread */
178 KeInitializeThread(InitProcess,
179 InitThread,
180 NULL,
181 NULL,
182 NULL,
183 NULL,
184 NULL,
185 IdleStack);
186 InitThread->NextProcessor = Number;
187 InitThread->Priority = HIGH_PRIORITY;
188 InitThread->State = Running;
189 InitThread->Affinity = 1 << Number;
190 InitThread->WaitIrql = DISPATCH_LEVEL;
191 InitProcess->ActiveProcessors = 1 << Number;
192
193 /* HACK for MmUpdatePageDir */
194 ((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess;
195
196 /* Set up the thread-related fields in the PRCB */
197 Prcb->CurrentThread = InitThread;
198 Prcb->NextThread = NULL;
199 Prcb->IdleThread = InitThread;
200
201 /* Initialize Kernel Memory Address Space */
202 MmInit1(MmFreeLdrFirstKrnlPhysAddr,
203 MmFreeLdrLastKrnlPhysAddr,
204 MmFreeLdrLastKernelAddress,
205 KeMemoryMap,
206 KeMemoryMapRangeCount,
207 4096);
208
209 /* Initialize the Kernel Executive */
210 ExpInitializeExecutive(0, LoaderBlock);
211
212 /* Only do this on the boot CPU */
213 if (!Number)
214 {
215 /* Calculate the time reciprocal */
216 KiTimeIncrementReciprocal =
217 KiComputeReciprocal(KeMaximumIncrement,
218 &KiTimeIncrementShiftCount);
219
220 /* Update DPC Values in case they got updated by the executive */
221 Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
222 Prcb->MinimumDpcRate = KiMinimumDpcRate;
223 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
224
225 /* Allocate the DPC Stack */
226 DpcStack = MmCreateKernelStack(FALSE, 0);
227 if (!DpcStack) KeBugCheckEx(NO_PAGES_AVAILABLE, 1, 0, 0, 0);
228 Prcb->DpcStack = DpcStack;
229 }
230
231 /* Free Initial Memory */
232 // MiFreeInitMemory();
233
234 KfRaiseIrql(DISPATCH_LEVEL);
235
236 KeSetPriorityThread(InitThread, 0);
237 /* Setup decrementer exception */
238 KiSetupDecrementerTrap();
239
240 KfLowerIrql(PASSIVE_LEVEL);
241
242 /* Should not return */
243 while(1)
244 {
245 NtYieldExecution();
246 }
247 }
248
249 extern int KiPageFaultTrap();
250 KTRAP_FRAME KiInitialTrapFrame;
251
252 /* Use this for early boot additions to the page table */
253 VOID
254 NTAPI
255 KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
256 {
257 ULONG Cpu;
258 ppc_map_info_t info[4];
259 PKIPCR Pcr = (PKIPCR)KPCR_BASE;
260 PKPRCB Prcb;
261
262 __asm__("mr 13,%0" : : "r" (KPCR_BASE));
263
264 /* Set the page fault handler to the kernel */
265 MmuSetTrapHandler(3,KiPageFaultTrap);
266 MmuSetTrapHandler(4,KiPageFaultTrap);
267
268 // Make 0xf... special
269 MmuAllocVsid(2, 0x8000);
270 MmuSetVsid(15,16,2);
271
272 /* Get the current CPU */
273 Cpu = KeNumberProcessors;
274 if (!Cpu)
275 {
276 /* We'll allocate a page from the end of the kernel area for KPCR. This code will probably
277 * change when we get SMP support.
278 */
279 info[0].phys = 0;
280 info[0].proc = 2;
281 info[0].addr = (vaddr_t)Pcr;
282 info[0].flags = MMU_KRW_UR;
283 info[1].phys = 0;
284 info[1].proc = 2;
285 info[1].addr = ((vaddr_t)Pcr) + (1 << PAGE_SHIFT);
286 info[1].flags = MMU_KRW_UR;
287 info[2].phys = 0;
288 info[2].proc = 2;
289 info[2].addr = (vaddr_t)KI_USER_SHARED_DATA;
290 info[2].flags = MMU_KRW_UR;
291 info[3].phys = 0;
292 info[3].proc = 2;
293 info[3].addr = (vaddr_t)KIP0PCRADDRESS;
294 info[3].flags = MMU_KRW_UR;
295 MmuMapPage(info, 4);
296 }
297
298 /* Skip initial setup if this isn't the Boot CPU */
299 if (Cpu) goto AppCpuInit;
300
301 /* Initialize the PCR */
302 RtlZeroMemory(Pcr, PAGE_SIZE);
303 KiInitializePcr(Cpu,
304 Pcr,
305 &KiInitialThread.Tcb,
306 KiDoubleFaultStack);
307
308 /* Set us as the current process */
309 KiInitialThread.Tcb.ApcState.Process = &KiInitialProcess.Pcb;
310 KiInitialThread.Tcb.TrapFrame = &KiInitialTrapFrame;
311
312 /* Setup CPU-related fields */
313 AppCpuInit:
314 Pcr->Number = Cpu;
315 Pcr->SetMember = 1 << Cpu;
316 Prcb = KeGetCurrentPrcb();
317 Prcb->SetMember = 1 << Cpu;
318
319 /* Initialize the Processor with HAL */
320 HalInitializeProcessor(Cpu, LoaderBlock);
321
322 /* Set active processors */
323 KeActiveProcessors |= Pcr->SetMember;
324 KeNumberProcessors++;
325
326 /* Initialize the Debugger for the Boot CPU */
327 if (!Cpu) KdInitSystem (0, LoaderBlock);
328
329 /* Check for break-in */
330 if (KdPollBreakIn())
331 {
332 DbgBreakPointWithStatus(1);
333 }
334
335 /* Raise to HIGH_LEVEL */
336 KfRaiseIrql(HIGH_LEVEL);
337
338 /* Call main kernel intialization */
339 KiInitializeKernel(&KiInitialProcess.Pcb,
340 &KiInitialThread.Tcb,
341 P0BootStack,
342 Prcb,
343 Cpu,
344 (PVOID)LoaderBlock);
345 }
346
347 VOID
348 NTAPI
349 KiInitMachineDependent(VOID)
350 {
351 }
352
353 void abort()
354 {
355 KeBugCheck(0);
356 while(1);
357 }