Author: tkreuzer Date: Fri Aug 22 21:11:09 2008 New Revision: 35549
URL: http://svn.reactos.org/svn/reactos?rev=35549&view=rev Log: Implement KiSetProcessorType, KiGetCpuVendor, KiGetFeatureBits, KiGetCacheInformation, KiSetCr0Bits and KiInitializeTss based on x86 implementation. Fix and enable Code in KiInitalizeKernel, enable call to HalInitializeProcessor.
Modified: branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/amd64/ke.h branches/ros-amd64-bringup/reactos/ntoskrnl/ke/amd64/cpu.c branches/ros-amd64-bringup/reactos/ntoskrnl/ke/amd64/kiinit.c
Modified: branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/amd64/ke.h URL: http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/ntoskr... ============================================================================== --- branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/amd64/ke.h [iso-8859-1] (original) +++ branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/amd64/ke.h [iso-8859-1] Fri Aug 22 21:11:09 2008 @@ -75,7 +75,8 @@ Ki386InitializeTss( IN PKTSS Tss, IN PKIDTENTRY Idt, - IN PKGDTENTRY Gdt + IN PKGDTENTRY Gdt, + IN UINT64 Stack );
VOID KiDivideErrorFault();
Modified: branches/ros-amd64-bringup/reactos/ntoskrnl/ke/amd64/cpu.c URL: http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/ntoskr... ============================================================================== --- branches/ros-amd64-bringup/reactos/ntoskrnl/ke/amd64/cpu.c [iso-8859-1] (original) +++ branches/ros-amd64-bringup/reactos/ntoskrnl/ke/amd64/cpu.c [iso-8859-1] Fri Aug 22 21:11:09 2008 @@ -12,32 +12,475 @@ #define NDEBUG #include <debug.h>
+/* FIXME: Local EFLAGS defines not used anywhere else */ +#define EFLAGS_IOPL 0x3000 +#define EFLAGS_NF 0x4000 +#define EFLAGS_RF 0x10000 +#define EFLAGS_ID 0x200000 + /* GLOBALS *******************************************************************/
/* The Boot TSS */ KTSS64 KiBootTss;
-/* The TSS to use for Double Fault Traps (INT 0x9) */ -UCHAR KiDoubleFaultTSS[KTSS_IO_MAPS]; - -/* The TSS to use for NMI Fault Traps (INT 0x2) */ -UCHAR KiNMITSS[KTSS_IO_MAPS]; - /* CPU Features and Flags */ +ULONG KeI386CpuType; +ULONG KeI386CpuStep; ULONG KeI386MachineType; - +ULONG KeI386NpxPresent = 1; +ULONG KeI386XMMIPresent = 0; +ULONG KeI386FxsrPresent = 0; CHAR KeNumberProcessors = 0; +BOOLEAN KiI386PentiumLockErrataPresent; +BOOLEAN KiSMTProcessorsPresent; + +/* CPU Signatures */ +static const CHAR CmpIntelID[] = "GenuineIntel"; +static const CHAR CmpAmdID[] = "AuthenticAMD"; +static const CHAR CmpCyrixID[] = "CyrixInstead"; +static const CHAR CmpTransmetaID[] = "GenuineTMx86"; +static const CHAR CmpCentaurID[] = "CentaurHauls"; +static const CHAR CmpRiseID[] = "RiseRiseRise";
/* FUNCTIONS *****************************************************************/ + +VOID +NTAPI +KiSetProcessorType(VOID) +{ + ULONG64 EFlags; + int Reg[4]; + ULONG Stepping, Type; + + /* Start by assuming no CPUID data */ + KeGetCurrentPrcb()->CpuID = 0; + + /* Save EFlags */ + Ke386SaveFlags(EFlags); + + /* Do CPUID 1 now */ + __cpuid(Reg, 1); + + /* + * Get the Stepping and Type. The stepping contains both the + * Model and the Step, while the Type contains the returned Type. + * We ignore the family. + * + * For the stepping, we convert this: zzzzzzxy into this: x0y + */ + Stepping = Reg[0] & 0xF0; + Stepping <<= 4; + Stepping += (Reg[0] & 0xFF); + Stepping &= 0xF0F; + Type = Reg[0] & 0xF00; + Type >>= 8; + + /* Save them in the PRCB */ + KeGetCurrentPrcb()->CpuID = TRUE; + KeGetCurrentPrcb()->CpuType = (UCHAR)Type; + KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping; + + /* Restore EFLAGS */ + Ke386RestoreFlags(EFlags); +} + +ULONG +NTAPI +KiGetCpuVendor(VOID) +{ + PKPRCB Prcb = KeGetCurrentPrcb(); + ULONG Vendor[5]; + ULONG Temp; + + /* Assume no Vendor ID and fail if no CPUID Support. */ + Prcb->VendorString[0] = 0; + if (!Prcb->CpuID) return 0; + + /* Get the Vendor ID and null-terminate it */ + __cpuid(Vendor, 0); + Vendor[4] = 0; + + /* Re-arrange vendor string */ + Temp = Vendor[2]; + Vendor[2] = Vendor[3]; + Vendor[3] = Temp; + + /* Copy it to the PRCB and null-terminate it again */ + RtlCopyMemory(Prcb->VendorString, + &Vendor[1], + sizeof(Prcb->VendorString) - sizeof(CHAR)); + Prcb->VendorString[sizeof(Prcb->VendorString) - sizeof(CHAR)] = ANSI_NULL; + + /* Now check the CPU Type */ + if (!strcmp(Prcb->VendorString, CmpIntelID)) + { + return CPU_INTEL; + } + else if (!strcmp(Prcb->VendorString, CmpAmdID)) + { + return CPU_AMD; + } + else if (!strcmp(Prcb->VendorString, CmpCyrixID)) + { + DPRINT1("Cyrix CPUs not fully supported\n"); + return 0; + } + else if (!strcmp(Prcb->VendorString, CmpTransmetaID)) + { + DPRINT1("Transmeta CPUs not fully supported\n"); + return 0; + } + else if (!strcmp(Prcb->VendorString, CmpCentaurID)) + { + DPRINT1("VIA CPUs not fully supported\n"); + return 0; + } + else if (!strcmp(Prcb->VendorString, CmpRiseID)) + { + DPRINT1("Rise CPUs not fully supported\n"); + return 0; + } + + /* Invalid CPU */ + return 0; +} + +ULONG +NTAPI +KiGetFeatureBits(VOID) +{ + PKPRCB Prcb = KeGetCurrentPrcb(); + ULONG Vendor; + ULONG FeatureBits = KF_WORKING_PTE; + ULONG Reg[4]; + BOOLEAN ExtendedCPUID = TRUE; + ULONG CpuFeatures = 0; + + /* Get the Vendor ID */ + Vendor = KiGetCpuVendor(); + + /* Make sure we got a valid vendor ID at least. */ + if (!Vendor) return FeatureBits; + + /* Get the CPUID Info. Features are in Reg[3]. */ + __cpuid(Reg, 1); + + /* Set the initial APIC ID */ + Prcb->InitialApicId = (UCHAR)(Reg[1] >> 24); + + /* Check for AMD CPU */ + if (Vendor == CPU_AMD) + { + /* Check if this is a K5 or higher. */ + if ((Reg[0] & 0x0F00) >= 0x0500) + { + /* Check if this is a K5 specifically. */ + if ((Reg[0] & 0x0F00) == 0x0500) + { + /* Get the Model Number */ + switch (Reg[0] & 0x00F0) + { + /* Check if this is the Model 1 */ + case 0x0010: + + /* Check if this is Step 0 or 1. They don't support PGE */ + if ((Reg[0] & 0x000F) > 0x03) break; + + case 0x0000: + + /* Model 0 doesn't support PGE at all. */ + Reg[3] &= ~0x2000; + break; + + case 0x0080: + + /* K6-2, Step 8 and over have support for MTRR. */ + if ((Reg[0] & 0x000F) >= 0x8) FeatureBits |= KF_AMDK6MTRR; + break; + + case 0x0090: + + /* As does the K6-3 */ + FeatureBits |= KF_AMDK6MTRR; + break; + + default: + break; + } + } + } + else + { + /* Families below 5 don't support PGE, PSE or CMOV at all */ + Reg[3] &= ~(0x08 | 0x2000 | 0x8000); + + /* They also don't support advanced CPUID functions. */ + ExtendedCPUID = FALSE; + } + + /* Set the current features */ + CpuFeatures = Reg[3]; + } + + /* Now check if this is Intel */ + if (Vendor == CPU_INTEL) + { + /* Check if it's a P6 */ + if (Prcb->CpuType == 6) + { + /* Perform the special sequence to get the MicroCode Signature */ + __writemsr(0x8B, 0); + __writemsr(Reg, 1); + Prcb->UpdateSignature.QuadPart = __readmsr(0x8B); + } + else if (Prcb->CpuType == 5) + { + /* On P5, enable workaround for the LOCK errata. */ + KiI386PentiumLockErrataPresent = TRUE; + } + + /* Check for broken P6 with bad SMP PTE implementation */ + if (((Reg[0] & 0x0FF0) == 0x0610 && (Reg[0] & 0x000F) <= 0x9) || + ((Reg[0] & 0x0FF0) == 0x0630 && (Reg[0] & 0x000F) <= 0x4)) + { + /* Remove support for correct PTE support. */ + FeatureBits &= ~KF_WORKING_PTE; + } + + /* Check if the CPU is too old to support SYSENTER */ + if ((Prcb->CpuType < 6) || + ((Prcb->CpuType == 6) && (Prcb->CpuStep < 0x0303))) + { + /* Disable it */ + Reg[3] &= ~0x800; + } + + /* Set the current features */ + CpuFeatures = Reg[3]; + } + + /* Convert all CPUID Feature bits into our format */ + if (CpuFeatures & 0x00000002) FeatureBits |= KF_V86_VIS | KF_CR4; + if (CpuFeatures & 0x00000008) FeatureBits |= KF_LARGE_PAGE | KF_CR4; + if (CpuFeatures & 0x00000010) FeatureBits |= KF_RDTSC; + if (CpuFeatures & 0x00000100) FeatureBits |= KF_CMPXCHG8B; + if (CpuFeatures & 0x00000800) FeatureBits |= KF_FAST_SYSCALL; + if (CpuFeatures & 0x00001000) FeatureBits |= KF_MTRR; + if (CpuFeatures & 0x00002000) FeatureBits |= KF_GLOBAL_PAGE | KF_CR4; + if (CpuFeatures & 0x00008000) FeatureBits |= KF_CMOV; + if (CpuFeatures & 0x00010000) FeatureBits |= KF_PAT; + if (CpuFeatures & 0x00200000) FeatureBits |= KF_DTS; + if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX; + if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR; + if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI; + if (CpuFeatures & 0x04000000) FeatureBits |= KF_XMMI64; + + /* Check if the CPU has hyper-threading */ + if (CpuFeatures & 0x10000000) + { + /* Set the number of logical CPUs */ + Prcb->LogicalProcessorsPerPhysicalProcessor = (UCHAR)(Reg[1] >> 16); + if (Prcb->LogicalProcessorsPerPhysicalProcessor > 1) + { + /* We're on dual-core */ + KiSMTProcessorsPresent = TRUE; + } + } + else + { + /* We only have a single CPU */ + Prcb->LogicalProcessorsPerPhysicalProcessor = 1; + } + + /* Check if CPUID 0x80000000 is supported */ + if (ExtendedCPUID) + { + /* Do the call */ + __cpuid(Reg, 0x80000000); + if ((Reg[0] & 0xffffff00) == 0x80000000) + { + /* Check if CPUID 0x80000001 is supported */ + if (Reg[0] >= 0x80000001) + { + /* Check which extended features are available. */ + __cpuid(Reg, 0x80000001); + + /* Check if NX-bit is supported */ + if (Reg[3] & 0x00100000) FeatureBits |= KF_NX_BIT; + + /* Now handle each features for each CPU Vendor */ + switch (Vendor) + { + case CPU_AMD: + if (Reg[3] & 0x80000000) FeatureBits |= KF_3DNOW; + break; + } + } + } + } + + /* Return the Feature Bits */ + return FeatureBits; +} + +VOID +NTAPI +KiGetCacheInformation(VOID) +{ + PKIPCR Pcr = (PKIPCR)KeGetPcr(); + ULONG Vendor; + ULONG Data[4]; + ULONG CacheRequests = 0, i; + ULONG CurrentRegister; + UCHAR RegisterByte; + BOOLEAN FirstPass = TRUE; + + /* Set default L2 size */ + Pcr->SecondLevelCacheSize = 0; + + /* Get the Vendor ID and make sure we support CPUID */ + Vendor = KiGetCpuVendor(); + if (!Vendor) return; + + /* Check the Vendor ID */ + switch (Vendor) + { + /* Handle Intel case */ + case CPU_INTEL: + + /*Check if we support CPUID 2 */ + __cpuid(Data, 0); + if (Data[0] >= 2) + { + /* We need to loop for the number of times CPUID will tell us to */ + do + { + /* Do the CPUID call */ + __cpuid(Data, 2); + + /* Check if it was the first call */ + if (FirstPass) + { + /* + * The number of times to loop is the first byte. Read + * it and then destroy it so we don't get confused. + */ + CacheRequests = Data[0] & 0xFF; + Data[0] &= 0xFFFFFF00; + + /* Don't go over this again */ + FirstPass = FALSE; + } + + /* Loop all 4 registers */ + for (i = 0; i < 4; i++) + { + /* Get the current register */ + CurrentRegister = Data[i]; + + /* + * If the upper bit is set, then this register should + * be skipped. + */ + if (CurrentRegister & 0x80000000) continue; + + /* Keep looping for every byte inside this register */ + while (CurrentRegister) + { + /* Read a byte, skip a byte. */ + RegisterByte = (UCHAR)(CurrentRegister & 0xFF); + CurrentRegister >>= 8; + if (!RegisterByte) continue; + + /* + * Valid values are from 0x40 (0 bytes) to 0x49 + * (32MB), or from 0x80 to 0x89 (same size but + * 8-way associative. + */ + if (((RegisterByte > 0x40) && + (RegisterByte <= 0x49)) || + ((RegisterByte > 0x80) && + (RegisterByte <= 0x89))) + { + /* Mask out only the first nibble */ + RegisterByte &= 0x0F; + + /* Set the L2 Cache Size */ + Pcr->SecondLevelCacheSize = 0x10000 << + RegisterByte; + } + } + } + } while (--CacheRequests); + } + break; + + case CPU_AMD: + + /* Check if we support CPUID 0x80000006 */ + __cpuid(Data, 0x80000000); + if (Data[0] >= 6) + { + /* Get 2nd level cache and tlb size */ + __cpuid(Data, 0x80000006); + + /* Set the L2 Cache Size */ + Pcr->SecondLevelCacheSize = (Data[2] & 0xFFFF0000) >> 6; + } + break; + } +} + + +VOID +NTAPI +KiSetCR0Bits(VOID) +{ + ULONG64 Cr0; + + /* Save current CR0 */ + Cr0 = __readcr0(); + + /* If this is a 486, enable Write-Protection */ + if (KeGetCurrentPrcb()->CpuType > 3) Cr0 |= CR0_WP; + + /* Set new Cr0 */ + __writecr0(Cr0); +}
VOID FASTCALL -Ki386InitializeTss(IN PKTSS Tss, +Ki386InitializeTss(IN PKTSS64 Tss, IN PKIDTENTRY Idt, - IN PKGDTENTRY Gdt) -{ - // UNIMPLEMENTED; + IN PKGDTENTRY Gdt, + IN UINT64 Stack) +{ + PKGDTENTRY TssEntry; + + /* Initialize the boot TSS entry */ + TssEntry = &Gdt[KGDT_TSS / sizeof(KGDTENTRY)]; + TssEntry->Bits.Type = I386_TSS; + TssEntry->Bits.Present = 1; + TssEntry->Bits.Dpl = 0; + + /* FIXME: I/O Map */ + + /* Load the task register */ + Ke386SetTr(KGDT_TSS); + + /* Setup stack pointer */ + Tss->Rsp0 = Stack; + + /* Setup a stack for Double Fault Traps */ + Tss->Ist[1] = PtrToUlong(KiDoubleFaultStack); + + /* Setup a stack for CheckAbort Traps */ + Tss->Ist[2] = PtrToUlong(KiDoubleFaultStack); + + /* Setup a stack for NMI Traps */ + Tss->Ist[3] = PtrToUlong(KiDoubleFaultStack); + }
VOID
Modified: branches/ros-amd64-bringup/reactos/ntoskrnl/ke/amd64/kiinit.c URL: http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/ntoskr... ============================================================================== --- branches/ros-amd64-bringup/reactos/ntoskrnl/ke/amd64/kiinit.c [iso-8859-1] (original) +++ branches/ros-amd64-bringup/reactos/ntoskrnl/ke/amd64/kiinit.c [iso-8859-1] Fri Aug 22 21:11:09 2008 @@ -374,6 +374,8 @@ Pcr->TssBase = Tss; Pcr->Prcb.DpcStack = DpcStack;
+ Pcr->Prcb.RspBase = Tss->Rsp0; + /* Setup the processor set */ Pcr->Prcb.MultiThreadProcessorSet = Pcr->Prcb.SetMember; } @@ -387,13 +389,10 @@ IN CCHAR Number, IN PLOADER_PARAMETER_BLOCK LoaderBlock) { - FrLdrDbgPrint("Enter KiInitializeKernel\n"); -#if 0 BOOLEAN NpxPresent; ULONG FeatureBits; - LARGE_INTEGER PageDirectory; + ULONG PageDirectory[2]; PVOID DpcStack; - ULONG Vendor[3];
/* Detect and set the CPU Type */ KiSetProcessorType(); @@ -401,14 +400,8 @@ /* Set CR0 features based on detected CPU */ KiSetCR0Bits();
- /* Check if an FPU is present */ - NpxPresent = KiIsNpxPresent(); - /* Initialize the Power Management Support for this PRCB */ - PoInitializePrcb(Prcb); - - /* Bugcheck if this is a 386 CPU */ - if (Prcb->CpuType == 3) KeBugCheckEx(0x5D, 0x386, 0, 0, 0); +// PoInitializePrcb(Prcb);
/* Get the processor features for the CPU */ FeatureBits = KiGetFeatureBits(); @@ -456,7 +449,7 @@ KiInitSpinLocks(Prcb, Number);
/* Check if this is the Boot CPU */ - if (!Number) + if (Number == 0) { /* Set Node Data */ KeNodeBlock[0] = &KiNode0; @@ -474,20 +467,6 @@ KeI386FxsrPresent = (KeFeatureBits & KF_FXSR) ? TRUE : FALSE; KeI386XMMIPresent = (KeFeatureBits & KF_XMMI) ? TRUE : FALSE;
- /* Detect 8-byte compare exchange support */ - if (!(KeFeatureBits & KF_CMPXCHG8B)) - { - /* Copy the vendor string */ - RtlCopyMemory(Vendor, Prcb->VendorString, sizeof(Vendor)); - - /* Bugcheck the system. Windows *requires* this */ - KeBugCheckEx(0x5D, - (1 << 24 ) | (Prcb->CpuType << 16) | Prcb->CpuStep, - Vendor[0], - Vendor[1], - Vendor[2]); - } - /* Set the current MP Master KPRCB to the Boot PRCB */ Prcb->MultiThreadSetMaster = Prcb;
@@ -503,11 +482,12 @@
/* Initialize the Idle Process and the Process Listhead */ InitializeListHead(&KiProcessListHead); - PageDirectory.QuadPart = 0; + PageDirectory[0] = 0; + PageDirectory[1] = 0; KeInitializeProcess(InitProcess, 0, 0xFFFFFFFF, - &PageDirectory, + PageDirectory, FALSE); InitProcess->QuantumReset = MAXCHAR; } @@ -516,7 +496,8 @@ /* FIXME */ DPRINT1("SMP Boot support not yet present\n"); } - +FrLdrDbgPrint("before KeInitializeThread\n"); +for(;;); /* Setup the Idle Thread */ KeInitializeThread(InitProcess, InitThread, @@ -577,14 +558,14 @@ Prcb->DpcStack = DpcStack;
/* Allocate the IOPM save area. */ - Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool, - PAGE_SIZE * 2, - TAG('K', 'e', ' ', ' ')); - if (!Ki386IopmSaveArea) - { - /* Bugcheck. We need this for V86/VDM support. */ - KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0); - } +// Ki386IopmSaveArea = ExAllocatePoolWithTag(PagedPool, +// PAGE_SIZE * 2, +// TAG('K', 'e', ' ', ' ')); +// if (!Ki386IopmSaveArea) +// { +// /* Bugcheck. We need this for V86/VDM support. */ +// KeBugCheckEx(NO_PAGES_AVAILABLE, 2, PAGE_SIZE * 2, 0, 0); +// } }
/* Raise to Dispatch */ @@ -601,7 +582,6 @@ /* Raise back to HIGH_LEVEL and clear the PRCB for the loader block */ KfRaiseIrql(HIGH_LEVEL); LoaderBlock->Prcb = 0; -#endif }
VOID @@ -712,7 +692,7 @@ FrLdrDbgPrint("Gdt = %p, Idt = %p, Pcr = %p, Tss = %p\n", Gdt, Idt, Pcr, Tss);
/* Setup the TSS descriptors and entries */ - Ki386InitializeTss(Tss, Idt, Gdt); + Ki386InitializeTss(Tss, Idt, Gdt, InitialStack);
/* Initialize the PCR */ RtlZeroMemory(Pcr, PAGE_SIZE); @@ -769,7 +749,7 @@ Pcr->Prcb.SetMember = 1 << Cpu;
/* Initialize the Processor with HAL */ -// HalInitializeProcessor(Cpu, KeLoaderBlock); + HalInitializeProcessor(Cpu, KeLoaderBlock);
/* Set active processors */ KeActiveProcessors |= 1 << Cpu;