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