Set 386 as default cpu type.
[reactos.git] / reactos / ntoskrnl / ke / i386 / kernel.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /*
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/ke/i386/kernel.c
22 * PURPOSE: Initializes the kernel
23 * PROGRAMMER: David Welch (welch@mcmail.com)
24 * UPDATE HISTORY:
25 * Created 22/05/98
26 */
27
28 /* INCLUDES *****************************************************************/
29
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>
35
36 #define NDEBUG
37 #include <internal/debug.h>
38
39 /* GLOBALS *******************************************************************/
40
41 ULONG KiPcrInitDone = 0;
42 static ULONG PcrsAllocated = 0;
43 static PHYSICAL_ADDRESS PcrPages[MAXIMUM_PROCESSORS];
44 ULONG Ke386CpuidFlags, Ke386CpuidFlags2, Ke386CpuidExFlags;
45 ULONG Ke386Cpuid = 300;
46
47 #define X86_EFLAGS_ID (1 << 21)
48
49 /* FUNCTIONS *****************************************************************/
50
51 VOID INIT_FUNCTION STATIC
52 Ki386GetCpuId(VOID)
53 {
54 ULONG OrigFlags, Flags, FinalFlags;
55 ULONG MaxCpuidLevel;
56
57 Ke386CpuidFlags = Ke386CpuidFlags2 = Ke386CpuidExFlags = 0;
58
59 /* Try to toggle the id bit in eflags. */
60 __asm__ ("pushfl\n\t"
61 "popl %0\n\t"
62 : "=r" (OrigFlags));
63 Flags = OrigFlags ^ X86_EFLAGS_ID;
64 __asm__ ("pushl %1\n\t"
65 "popfl\n\t"
66 "pushfl\n\t"
67 "popl %0\n\t"
68 : "=r" (FinalFlags)
69 : "r" (Flags));
70 if ((OrigFlags & X86_EFLAGS_ID) == (FinalFlags & X86_EFLAGS_ID))
71 {
72 /* No cpuid supported. */
73 return;
74 }
75
76 /* Get maximum cpuid level supported. */
77 __asm__("cpuid\n\t"
78 : "=a" (MaxCpuidLevel)
79 : "a" (0x00000000)
80 : "ebx", "ecx", "edx");
81 if (MaxCpuidLevel > 0)
82 {
83 /* Get the feature flags. */
84 __asm__("cpuid\n\t"
85 : "=a" (Ke386Cpuid),"=d" (Ke386CpuidFlags), "=c" (Ke386CpuidFlags2)
86 : "a" (0x00000001)
87 : "ebx");
88 }
89
90 /* Get the maximum extended cpuid level supported. */
91 __asm__("cpuid\n\t"
92 : "=a" (MaxCpuidLevel)
93 : "a" (0x80000000)
94 : "ebx", "ecx", "edx");
95 if (MaxCpuidLevel > 0)
96 {
97 /* Get the extended feature flags. */
98 __asm__("cpuid\n\t"
99 : "=d" (Ke386CpuidExFlags)
100 : "a" (0x80000001)
101 : "ebx", "ecx");
102 }
103 }
104
105 VOID INIT_FUNCTION
106 KePrepareForApplicationProcessorInit(ULONG Id)
107 {
108 MmRequestPageMemoryConsumer(MC_NPPOOL, FALSE, &PcrPages[Id]);
109 KiGdtPrepareForApplicationProcessorInit(Id);
110 }
111
112 VOID
113 KeApplicationProcessorInit(VOID)
114 {
115 PKPCR KPCR;
116 ULONG Offset;
117
118 /*
119 * Create a PCR for this processor
120 */
121 Offset = InterlockedIncrement((LONG *)&PcrsAllocated) - 1;
122 KPCR = (PKPCR)(KPCR_BASE + (Offset * PAGE_SIZE));
123 MmCreateVirtualMappingForKernel((PVOID)KPCR,
124 PAGE_READWRITE,
125 PcrPages[Offset]);
126 memset(KPCR, 0, PAGE_SIZE);
127 KPCR->ProcessorNumber = (UCHAR)Offset;
128 KPCR->Self = KPCR;
129 KPCR->Irql = HIGH_LEVEL;
130
131 /* Mark the end of the exception handler list */
132 KPCR->Tib.ExceptionList = (PVOID)-1;
133
134 /*
135 * Initialize the GDT
136 */
137 KiInitializeGdt(KPCR);
138
139 /*
140 * It is now safe to process interrupts
141 */
142 KeLowerIrql(DISPATCH_LEVEL);
143
144 /*
145 * Initialize the TSS
146 */
147 Ki386ApplicationProcessorInitializeTSS();
148
149 /*
150 * Initialize a default LDT
151 */
152 Ki386InitializeLdt();
153
154 /* Now we can enable interrupts. */
155 Ke386EnableInterrupts();
156 }
157
158 VOID INIT_FUNCTION
159 KeInit1(VOID)
160 {
161 PKPCR KPCR;
162 extern USHORT KiBootGdt[];
163 extern KTSS KiBootTss;
164
165 KiCheckFPU();
166
167 KiInitializeGdt (NULL);
168 Ki386BootInitializeTSS();
169 KeInitExceptions ();
170 KeInitInterrupts ();
171
172 /*
173 * Initialize the initial PCR region. We can't allocate a page
174 * with MmAllocPage() here because MmInit1() has not yet been
175 * called, so we use a predefined page in low memory
176 */
177 KPCR = (PKPCR)KPCR_BASE;
178 memset(KPCR, 0, PAGE_SIZE);
179 KPCR->Self = (PKPCR)KPCR_BASE;
180 KPCR->Irql = HIGH_LEVEL;
181 KPCR->GDT = (PUSHORT)&KiBootGdt;
182 KPCR->IDT = (PUSHORT)&KiIdt;
183 KPCR->TSS = &KiBootTss;
184 KPCR->ProcessorNumber = 0;
185 KiPcrInitDone = 1;
186 PcrsAllocated++;
187
188 /* Mark the end of the exception handler list */
189 KPCR->Tib.ExceptionList = (PVOID)-1;
190
191 Ki386InitializeLdt();
192
193 /* Get processor information. */
194 Ki386GetCpuId();
195 }
196
197 VOID INIT_FUNCTION
198 KeInit2(VOID)
199 {
200 KeInitDpc();
201 KeInitializeBugCheck();
202 KeInitializeDispatcher();
203 KeInitializeTimerImpl();
204 }