3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: hal/halx86/generic/mpconfig.c
10 /* INCLUDES *****************************************************************/
12 #include <ddk/ntddk.h>
13 #include <ntos/types.h>
20 #include <internal/debug.h>
22 /* GLOBALS ******************************************************************/
24 MP_FLOATING_POINTER
* Mpf
= NULL
;
26 /* FUNCTIONS ****************************************************************/
29 MPChecksum(PUCHAR Base
,
32 * Checksum an MP configuration block
44 HaliMPIntSrcInfo(PMP_CONFIGURATION_INTSRC m
)
46 DPRINT("Int: type %d, pol %d, trig %d, bus %d,"
47 " IRQ %02x, APIC ID %x, APIC INT %02x\n",
48 m
->IrqType
, m
->IrqFlag
& 3,
49 (m
->IrqFlag
>> 2) & 3, m
->SrcBusId
,
50 m
->SrcBusIrq
, m
->DstApicId
, m
->DstApicInt
);
51 if (IRQCount
> MAX_IRQ_SOURCE
)
53 DPRINT1("Max # of irq sources exceeded!!\n");
57 IRQMap
[IRQCount
] = *m
;
62 HaliMPFamily(ULONG Family
,
69 "80486SX", "80486DX/2 or 80487",
70 "80486SL", "Intel5X2(tm)",
75 return ("Pentium(tm) Pro");
77 return ("Pentium(tm)");
78 if (Family
== 0x0F && Model
== 0x0F)
79 return("Special controller");
80 if (Family
== 0x0F && Model
== 0x00)
81 return("Pentium 4(tm)");
82 if (Family
== 0x04 && Model
< 9)
84 sprintf(str
, "Unknown CPU with family ID %ld and model ID %ld", Family
, Model
);
90 HaliMPProcessorInfo(PMP_CONFIGURATION_PROCESSOR m
)
94 if (!(m
->CpuFlags
& CPU_FLAG_ENABLED
))
97 DPRINT("Processor #%d %s APIC version %d\n",
99 HaliMPFamily((m
->FeatureFlags
& CPU_FAMILY_MASK
) >> 8,
100 (m
->FeatureFlags
& CPU_MODEL_MASK
) >> 4),
103 if (m
->FeatureFlags
& (1 << 0))
104 DPRINT(" Floating point unit present.\n");
105 if (m
->FeatureFlags
& (1 << 7))
106 DPRINT(" Machine Exception supported.\n");
107 if (m
->FeatureFlags
& (1 << 8))
108 DPRINT(" 64 bit compare & exchange supported.\n");
109 if (m
->FeatureFlags
& (1 << 9))
110 DPRINT(" Internal APIC present.\n");
111 if (m
->FeatureFlags
& (1 << 11))
112 DPRINT(" SEP present.\n");
113 if (m
->FeatureFlags
& (1 << 12))
114 DPRINT(" MTRR present.\n");
115 if (m
->FeatureFlags
& (1 << 13))
116 DPRINT(" PGE present.\n");
117 if (m
->FeatureFlags
& (1 << 14))
118 DPRINT(" MCA present.\n");
119 if (m
->FeatureFlags
& (1 << 15))
120 DPRINT(" CMOV present.\n");
121 if (m
->FeatureFlags
& (1 << 16))
122 DPRINT(" PAT present.\n");
123 if (m
->FeatureFlags
& (1 << 17))
124 DPRINT(" PSE present.\n");
125 if (m
->FeatureFlags
& (1 << 18))
126 DPRINT(" PSN present.\n");
127 if (m
->FeatureFlags
& (1 << 19))
128 DPRINT(" Cache Line Flush Instruction present.\n");
130 if (m
->FeatureFlags
& (1 << 21))
131 DPRINT(" Debug Trace and EMON Store present.\n");
132 if (m
->FeatureFlags
& (1 << 22))
133 DPRINT(" ACPI Thermal Throttle Registers present.\n");
134 if (m
->FeatureFlags
& (1 << 23))
135 DPRINT(" MMX present.\n");
136 if (m
->FeatureFlags
& (1 << 24))
137 DPRINT(" FXSR present.\n");
138 if (m
->FeatureFlags
& (1 << 25))
139 DPRINT(" XMM present.\n");
140 if (m
->FeatureFlags
& (1 << 26))
141 DPRINT(" Willamette New Instructions present.\n");
142 if (m
->FeatureFlags
& (1 << 27))
143 DPRINT(" Self Snoop present.\n");
145 if (m
->FeatureFlags
& (1 << 29))
146 DPRINT(" Thermal Monitor present.\n");
147 /* 30, 31 Reserved */
149 CPUMap
[CPUCount
].APICId
= m
->ApicId
;
151 CPUMap
[CPUCount
].Flags
= CPU_USABLE
;
153 if (m
->CpuFlags
& CPU_FLAG_BSP
)
155 DPRINT(" Bootup CPU\n");
156 CPUMap
[CPUCount
].Flags
|= CPU_BSP
;
160 if (m
->ApicId
> MAX_CPU
)
162 DPRINT("Processor #%d INVALID. (Max ID: %d).\n", m
->ApicId
, MAX_CPU
);
165 ver
= m
->ApicVersion
;
172 DPRINT("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m
->ApicId
);
175 // ApicVersion[m->ApicId] = Ver;
176 // BiosCpuApicId[CPUCount] = m->ApicId;
177 CPUMap
[CPUCount
].APICVersion
= ver
;
183 HaliMPBusInfo(PMP_CONFIGURATION_BUS m
)
185 static ULONG CurrentPCIBusId
= 0;
187 DPRINT("Bus #%d is %.*s\n", m
->BusId
, 6, m
->BusType
);
189 if (strncmp(m
->BusType
, BUSTYPE_ISA
, sizeof(BUSTYPE_ISA
)-1) == 0)
191 BUSMap
[m
->BusId
] = MP_BUS_ISA
;
193 else if (strncmp(m
->BusType
, BUSTYPE_EISA
, sizeof(BUSTYPE_EISA
)-1) == 0)
195 BUSMap
[m
->BusId
] = MP_BUS_EISA
;
197 else if (strncmp(m
->BusType
, BUSTYPE_PCI
, sizeof(BUSTYPE_PCI
)-1) == 0)
199 BUSMap
[m
->BusId
] = MP_BUS_PCI
;
200 PCIBUSMap
[m
->BusId
] = CurrentPCIBusId
;
203 else if (strncmp(m
->BusType
, BUSTYPE_MCA
, sizeof(BUSTYPE_MCA
)-1) == 0)
205 BUSMap
[m
->BusId
] = MP_BUS_MCA
;
209 DPRINT("Unknown bustype %.*s - ignoring\n", 6, m
->BusType
);
214 HaliMPIOApicInfo(PMP_CONFIGURATION_IOAPIC m
)
216 if (!(m
->ApicFlags
& CPU_FLAG_ENABLED
))
219 DPRINT("I/O APIC #%d Version %d at 0x%lX.\n",
220 m
->ApicId
, m
->ApicVersion
, m
->ApicAddress
);
221 if (IOAPICCount
> MAX_IOAPIC
)
223 DPRINT("Max # of I/O APICs (%d) exceeded (found %d).\n",
224 MAX_IOAPIC
, IOAPICCount
);
225 DPRINT1("Recompile with bigger MAX_IOAPIC!.\n");
229 IOAPICMap
[IOAPICCount
].ApicId
= m
->ApicId
;
230 IOAPICMap
[IOAPICCount
].ApicVersion
= m
->ApicVersion
;
231 IOAPICMap
[IOAPICCount
].ApicAddress
= m
->ApicAddress
;
237 HaliMPIntLocalInfo(PMP_CONFIGURATION_INTLOCAL m
)
239 DPRINT("Lint: type %d, pol %d, trig %d, bus %d,"
240 " IRQ %02x, APIC ID %x, APIC LINT %02x\n",
241 m
->IrqType
, m
->SrcBusIrq
& 3,
242 (m
->SrcBusIrq
>> 2) & 3, m
->SrcBusId
,
243 m
->SrcBusIrq
, m
->DstApicId
, m
->DstApicLInt
);
245 * Well it seems all SMP boards in existence
246 * use ExtINT/LVT1 == LINT0 and
247 * NMI/LVT2 == LINT1 - the following check
248 * will show us if this assumptions is false.
249 * Until then we do not have to add baggage.
251 if ((m
->IrqType
== INT_EXTINT
) && (m
->DstApicLInt
!= 0))
253 DPRINT1("Invalid MP table!\n");
256 if ((m
->IrqType
== INT_NMI
) && (m
->DstApicLInt
!= 1))
258 DPRINT1("Invalid MP table!\n");
265 HaliReadMPConfigTable(PMP_CONFIGURATION_TABLE Table
)
268 Table = Pointer to MP configuration table
274 if (Table
->Signature
!= MPC_SIGNATURE
)
276 PUCHAR pc
= (PUCHAR
)&Table
->Signature
;
278 DPRINT1("Bad MP configuration block signature: %c%c%c%c\n",
279 pc
[0], pc
[1], pc
[2], pc
[3]);
280 KEBUGCHECKEX(0, pc
[0], pc
[1], pc
[2], pc
[3]);
284 if (MPChecksum((PUCHAR
)Table
, Table
->Length
))
286 DPRINT1("Bad MP configuration block checksum\n");
291 if (Table
->Specification
!= 0x01 && Table
->Specification
!= 0x04)
293 DPRINT1("Bad MP configuration table version (%d)\n",
294 Table
->Specification
);
299 if (Table
->LocalAPICAddress
!= APIC_DEFAULT_BASE
)
301 DPRINT1("APIC base address is at 0x%X. I cannot handle non-standard adresses\n",
302 Table
->LocalAPICAddress
);
307 DPRINT("Oem: %.*s, ProductId: %.*s\n", 8, Table
->Oem
, 12, Table
->ProductId
);
308 DPRINT("APIC at: %08x\n", Table
->LocalAPICAddress
);
311 Entry
= (PUCHAR
)((PVOID
)Table
+ sizeof(MP_CONFIGURATION_TABLE
));
313 while (Count
< (Table
->Length
- sizeof(MP_CONFIGURATION_TABLE
)))
318 case MPCTE_PROCESSOR
:
320 HaliMPProcessorInfo((PMP_CONFIGURATION_PROCESSOR
)Entry
);
321 Entry
+= sizeof(MP_CONFIGURATION_PROCESSOR
);
322 Count
+= sizeof(MP_CONFIGURATION_PROCESSOR
);
327 HaliMPBusInfo((PMP_CONFIGURATION_BUS
)Entry
);
328 Entry
+= sizeof(MP_CONFIGURATION_BUS
);
329 Count
+= sizeof(MP_CONFIGURATION_BUS
);
334 HaliMPIOApicInfo((PMP_CONFIGURATION_IOAPIC
)Entry
);
335 Entry
+= sizeof(MP_CONFIGURATION_IOAPIC
);
336 Count
+= sizeof(MP_CONFIGURATION_IOAPIC
);
341 HaliMPIntSrcInfo((PMP_CONFIGURATION_INTSRC
)Entry
);
342 Entry
+= sizeof(MP_CONFIGURATION_INTSRC
);
343 Count
+= sizeof(MP_CONFIGURATION_INTSRC
);
348 HaliMPIntLocalInfo((PMP_CONFIGURATION_INTLOCAL
)Entry
);
349 Entry
+= sizeof(MP_CONFIGURATION_INTLOCAL
);
350 Count
+= sizeof(MP_CONFIGURATION_INTLOCAL
);
354 DPRINT1("Unknown entry in MPC table\n");
363 HaliConstructDefaultIOIrqMPTable(ULONG Type
)
365 MP_CONFIGURATION_INTSRC intsrc
;
368 intsrc
.Type
= MPCTE_INTSRC
;
369 intsrc
.IrqFlag
= 0; /* conforming */
371 intsrc
.DstApicId
= IOAPICMap
[0].ApicId
;
373 intsrc
.IrqType
= INT_VECTORED
;
374 for (i
= 0; i
< 16; i
++) {
377 if (i
== 0 || i
== 13)
378 continue; /* IRQ0 & IRQ13 not connected */
382 continue; /* IRQ2 is never connected */
385 intsrc
.SrcBusIrq
= i
;
386 intsrc
.DstApicInt
= i
? i
: 2; /* IRQ0 to INTIN2 */
387 HaliMPIntSrcInfo(&intsrc
);
390 intsrc
.IrqType
= INT_EXTINT
;
391 intsrc
.SrcBusIrq
= 0;
392 intsrc
.DstApicInt
= 0; /* 8259A to INTIN0 */
393 HaliMPIntSrcInfo(&intsrc
);
397 HaliConstructDefaultISAMPTable(ULONG Type
)
399 MP_CONFIGURATION_PROCESSOR processor
;
400 MP_CONFIGURATION_BUS bus
;
401 MP_CONFIGURATION_IOAPIC ioapic
;
402 MP_CONFIGURATION_INTLOCAL lintsrc
;
403 ULONG linttypes
[2] = { INT_EXTINT
, INT_NMI
};
407 * 2 CPUs, numbered 0 & 1.
409 processor
.Type
= MPCTE_PROCESSOR
;
410 /* Either an integrated APIC or a discrete 82489DX. */
411 processor
.ApicVersion
= Type
> 4 ? 0x10 : 0x01;
412 processor
.CpuFlags
= CPU_FLAG_ENABLED
| CPU_FLAG_BSP
;
413 /* FIXME: Get this from the bootstrap processor */
414 processor
.CpuSignature
= 0;
415 processor
.FeatureFlags
= 0;
416 processor
.Reserved
[0] = 0;
417 processor
.Reserved
[1] = 0;
418 for (i
= 0; i
< 2; i
++)
420 processor
.ApicId
= i
;
421 HaliMPProcessorInfo(&processor
);
422 processor
.CpuFlags
&= ~CPU_FLAG_BSP
;
425 bus
.Type
= MPCTE_BUS
;
430 DPRINT("Unknown standard configuration %d\n", Type
);
434 memcpy(bus
.BusType
, "ISA ", 6);
439 memcpy(bus
.BusType
, "EISA ", 6);
443 memcpy(bus
.BusType
, "MCA ", 6);
448 bus
.Type
= MPCTE_BUS
;
450 memcpy(bus
.BusType
, "PCI ", 6);
454 ioapic
.Type
= MPCTE_IOAPIC
;
456 ioapic
.ApicVersion
= Type
> 4 ? 0x10 : 0x01;
457 ioapic
.ApicFlags
= MP_IOAPIC_USABLE
;
458 ioapic
.ApicAddress
= IOAPIC_DEFAULT_BASE
;
459 HaliMPIOApicInfo(&ioapic
);
462 * We set up most of the low 16 IO-APIC pins according to MPS rules.
464 HaliConstructDefaultIOIrqMPTable(Type
);
466 lintsrc
.Type
= MPCTE_LINTSRC
;
468 lintsrc
.IrqFlag
= 0; /* conforming */
469 lintsrc
.SrcBusId
= 0;
470 lintsrc
.SrcBusIrq
= 0;
471 lintsrc
.DstApicId
= MP_APIC_ALL
;
472 for (i
= 0; i
< 2; i
++)
474 lintsrc
.IrqType
= linttypes
[i
];
475 lintsrc
.DstApicLInt
= i
;
476 HaliMPIntLocalInfo(&lintsrc
);
482 HaliScanForMPConfigTable(ULONG Base
,
487 Base = Base address of region
488 Size = Length of region to check
490 TRUE if a valid MP configuration table was found
493 PULONG bp
= (PULONG
)Base
;
494 MP_FLOATING_POINTER
* mpf
;
499 mpf
= (MP_FLOATING_POINTER
*)bp
;
500 if (mpf
->Signature
== MPF_SIGNATURE
)
502 Checksum
= MPChecksum((PUCHAR
)bp
, 16);
503 DPRINT("Found MPF signature at %x, checksum %x\n", bp
, Checksum
);
507 DPRINT("Intel MultiProcessor Specification v1.%d compliant system.\n",
510 if (mpf
->Feature2
& FEATURE2_IMCRP
)
512 DPRINT("Running in IMCR and PIC compatibility mode.\n");
516 DPRINT("Running in Virtual Wire compatibility mode.\n");
520 switch (mpf
->Feature1
)
523 /* Non standard configuration */
529 DPRINT("EISA with no IRQ8 chaining\n");
538 DPRINT("ISA and PCI\n");
541 DPRINT("EISA and PCI\n");
544 DPRINT("MCA and PCI\n");
547 DPRINT("Unknown standard configuration %d\n", mpf
->Feature1
);
561 HaliGetSmpConfig(VOID
)
568 if (Mpf
->Feature2
& FEATURE2_IMCRP
)
570 DPRINT("Running in IMCR and PIC compatibility mode.\n");
575 DPRINT("Running in Virtual Wire compatibility mode.\n");
579 if (Mpf
->Feature1
== 0 && Mpf
->Address
)
581 if(!HaliReadMPConfigTable((PMP_CONFIGURATION_TABLE
)Mpf
->Address
))
583 DPRINT("BIOS bug, MP table errors detected!...\n");
584 DPRINT("... disabling SMP support. (tell your hw vendor)\n");
589 MP_CONFIGURATION_BUS bus
;
591 DPRINT("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
594 memcpy(bus
.BusType
, "ISA ", 6);
596 HaliConstructDefaultIOIrqMPTable(bus
.BusId
);
600 else if(Mpf
->Feature1
!= 0)
602 HaliConstructDefaultISAMPTable(Mpf
->Feature1
);
612 HaliFindSmpConfig(VOID
)
615 Scan the system memory for an MP configuration table
616 1) Scan the first KB of system base memory
617 2) Scan the last KB of system base memory
618 3) Scan the BIOS ROM address space between 0F0000h and 0FFFFFh
619 4) Scan the first KB from the Extended BIOS Data Area
622 if (!HaliScanForMPConfigTable(0x0, 0x400))
624 if (!HaliScanForMPConfigTable(0x9FC00, 0x400))
626 if (!HaliScanForMPConfigTable(0xF0000, 0x10000))
628 if (!HaliScanForMPConfigTable(*((PUSHORT
)0x040E) << 4, 0x400))
630 DPRINT("No multiprocessor compliant system found.\n");
637 if (HaliGetSmpConfig())
643 DPRINT("No MP config table found\n");