3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/ke/i386/kernel.c
22 * PURPOSE: Initializes the kernel
23 * PROGRAMMER: David Welch (welch@mcmail.com)
28 /* INCLUDES *****************************************************************/
30 #include <ddk/ntddk.h>
31 #include <internal/ke.h>
32 #include <internal/mm.h>
33 #include <internal/ps.h>
34 #include <internal/i386/fpu.h>
37 #include <internal/debug.h>
39 /* GLOBALS *******************************************************************/
41 ULONG KiPcrInitDone
= 0;
42 static ULONG PcrsAllocated
= 0;
43 static PFN_TYPE PcrPages
[MAXIMUM_PROCESSORS
];
44 ULONG Ke386CpuidFlags
, Ke386CpuidFlags2
, Ke386CpuidExFlags
;
45 ULONG Ke386Cpuid
= 300;
47 #define X86_EFLAGS_ID (1 << 21)
49 /* FUNCTIONS *****************************************************************/
51 VOID INIT_FUNCTION STATIC
54 ULONG OrigFlags
, Flags
, FinalFlags
;
57 Ke386CpuidFlags
= Ke386CpuidFlags2
= Ke386CpuidExFlags
= 0;
59 /* Try to toggle the id bit in eflags. */
63 Flags
= OrigFlags
^ X86_EFLAGS_ID
;
64 __asm__ ("pushl %1\n\t"
70 if ((OrigFlags
& X86_EFLAGS_ID
) == (FinalFlags
& X86_EFLAGS_ID
))
72 /* No cpuid supported. */
76 /* Get maximum cpuid level supported. */
78 : "=a" (MaxCpuidLevel
)
80 : "ebx", "ecx", "edx");
81 if (MaxCpuidLevel
> 0)
83 /* Get the feature flags. */
85 : "=a" (Ke386Cpuid
),"=d" (Ke386CpuidFlags
), "=c" (Ke386CpuidFlags2
)
90 /* Get the maximum extended cpuid level supported. */
92 : "=a" (MaxCpuidLevel
)
94 : "ebx", "ecx", "edx");
95 if (MaxCpuidLevel
> 0)
97 /* Get the extended feature flags. */
99 : "=d" (Ke386CpuidExFlags
)
106 KePrepareForApplicationProcessorInit(ULONG Id
)
108 MmRequestPageMemoryConsumer(MC_NPPOOL
, TRUE
, &PcrPages
[Id
]);
109 KiGdtPrepareForApplicationProcessorInit(Id
);
113 KeApplicationProcessorInit(VOID
)
119 * Create a PCR for this processor
121 Offset
= InterlockedIncrement((LONG
*)&PcrsAllocated
) - 1;
122 KPCR
= (PKPCR
)(KPCR_BASE
+ (Offset
* PAGE_SIZE
));
123 MmCreateVirtualMappingForKernel((PVOID
)KPCR
,
127 memset(KPCR
, 0, PAGE_SIZE
);
128 KPCR
->ProcessorNumber
= (UCHAR
)Offset
;
130 KPCR
->Irql
= HIGH_LEVEL
;
132 /* Mark the end of the exception handler list */
133 KPCR
->Tib
.ExceptionList
= (PVOID
)-1;
138 KiInitializeGdt(KPCR
);
141 * It is now safe to process interrupts
143 KeLowerIrql(DISPATCH_LEVEL
);
148 Ki386ApplicationProcessorInitializeTSS();
151 * Initialize a default LDT
153 Ki386InitializeLdt();
155 /* Now we can enable interrupts. */
156 Ke386EnableInterrupts();
163 extern USHORT KiBootGdt
[];
164 extern KTSS KiBootTss
;
168 KiInitializeGdt (NULL
);
169 Ki386BootInitializeTSS();
174 * Initialize the initial PCR region. We can't allocate a page
175 * with MmAllocPage() here because MmInit1() has not yet been
176 * called, so we use a predefined page in low memory
178 KPCR
= (PKPCR
)KPCR_BASE
;
179 memset(KPCR
, 0, PAGE_SIZE
);
180 KPCR
->Self
= (PKPCR
)KPCR_BASE
;
181 KPCR
->Irql
= HIGH_LEVEL
;
182 KPCR
->GDT
= KiBootGdt
;
183 KPCR
->IDT
= (PUSHORT
)KiIdt
;
184 KPCR
->TSS
= &KiBootTss
;
185 KPCR
->ProcessorNumber
= 0;
189 /* Mark the end of the exception handler list */
190 KPCR
->Tib
.ExceptionList
= (PVOID
)-1;
192 Ki386InitializeLdt();
194 /* Get processor information. */
202 KeInitializeBugCheck();
203 KeInitializeDispatcher();
204 KeInitializeTimerImpl();