diff --git a/sdk/xtdk/amd64/artypes.h b/sdk/xtdk/amd64/artypes.h index e2ad86b..5888d83 100644 --- a/sdk/xtdk/amd64/artypes.h +++ b/sdk/xtdk/amd64/artypes.h @@ -110,11 +110,16 @@ #define X86_EFLAGS_VIP_MASK 0x00100000 #define X86_EFLAGS_ID_MASK 0x00200000 +/* CPUID vendor names */ +#define CPUID_VENDOR_NAME_AMD "AuthenticAMD" +#define CPUID_VENDOR_NAME_INTEL "GenuineIntel" + /* CPU vendor enumeration list */ typedef enum _CPU_VENDOR { - CPU_VENDOR_AMD = 0x68747541, - CPU_VENDOR_INTEL = 0x756e6547, + CPU_VENDOR_INVALID, + CPU_VENDOR_AMD, + CPU_VENDOR_INTEL, CPU_VENDOR_UNKNOWN = 0xFFFFFFFF } CPU_VENDOR, *PCPU_VENDOR; @@ -144,7 +149,7 @@ typedef enum _CPUID_FEATURES CPUID_FEATURES_ECX_X2APIC = 1 << 21, CPUID_FEATURES_ECX_MOVBE = 1 << 22, CPUID_FEATURES_ECX_POPCNT = 1 << 23, - CPUID_FEATURES_ECX_TSC = 1 << 24, + CPUID_FEATURES_ECX_TSC_DEADLINE = 1 << 24, CPUID_FEATURES_ECX_AES = 1 << 25, CPUID_FEATURES_ECX_XSAVE = 1 << 26, CPUID_FEATURES_ECX_OSXSAVE = 1 << 27, @@ -184,6 +189,92 @@ typedef enum _CPUID_FEATURES CPUID_FEATURES_EDX_PBE = 1 << 31 } CPUID_FEATURES, *PCPUID_FEATURES; +/* CPU features, as reported by CPUID instruction */ +typedef union _CPU_FEATURES +{ + UINT64 Value; + union + { + UINT32 Ecx; + UINT32 ExtendedFeatures; + struct + { + BYTE SSE3 : 1; + BYTE PCLMUL : 1; + BYTE DTES64 : 1; + BYTE MONITOR : 1; + BYTE DS_CPL : 1; + BYTE VMX : 1; + BYTE SMX : 1; + BYTE EST : 1; + BYTE TM2 : 1; + BYTE SSSE3 : 1; + BYTE CID : 1; + BYTE SDBG : 1; + BYTE FMA : 1; + BYTE CX16 : 1; + BYTE XTPR : 1; + BYTE PDCM : 1; + BYTE Reserved4 : 1; // Bit 16 is reserved + BYTE PCID : 1; + BYTE DCA : 1; + BYTE SSE4_1 : 1; + BYTE SSE4_2 : 1; + BYTE X2APIC : 1; + BYTE MOVBE : 1; + BYTE POPCNT : 1; + BYTE TSC_DEADLINE : 1; + BYTE AES : 1; + BYTE XSAVE : 1; + BYTE OSXSAVE : 1; + BYTE AVX : 1; + BYTE F16C : 1; + BYTE RDRAND : 1; + BYTE HYPERVISOR : 1; + }; + }; + union + { + UINT32 Edx; + UINT32 Features; + struct + { + BYTE FPU : 1; + BYTE VME : 1; + BYTE DE : 1; + BYTE PSE : 1; + BYTE TSC : 1; + BYTE MSR : 1; + BYTE PAE : 1; + BYTE MCE : 1; + BYTE CX8 : 1; + BYTE APIC : 1; + BYTE Reserved1 : 1; // Bit 10 is reserved + BYTE SEP : 1; + BYTE MTRR : 1; + BYTE PGE : 1; + BYTE MCA : 1; + BYTE CMOV : 1; + BYTE PAT : 1; + BYTE PSE36 : 1; + BYTE PSN : 1; + BYTE CLFLUSH : 1; + BYTE Reserved2 : 1; // Bit 20 is reserved + BYTE DS : 1; + BYTE ACPI : 1; + BYTE MMX : 1; + BYTE FXSR : 1; + BYTE SSE : 1; + BYTE SSE2 : 1; + BYTE SS : 1; + BYTE HTT : 1; + BYTE TM : 1; + BYTE Reserved3 : 1; // Bit 30 is reserved + BYTE PBE : 1; + }; + }; +} CPU_FEATURES, *PCPU_FEATURES; + /* CPUID requests */ typedef enum _CPUID_REQUESTS { diff --git a/sdk/xtdk/amd64/ketypes.h b/sdk/xtdk/amd64/ketypes.h index 7441427..09692b2 100644 --- a/sdk/xtdk/amd64/ketypes.h +++ b/sdk/xtdk/amd64/ketypes.h @@ -522,6 +522,7 @@ typedef struct _KPROCESSOR_CONTROL_BLOCK ULONG64 RspBase; ULONG_PTR SetMember; CPU_IDENTIFICATION CpuId; + CPU_FEATURES CpuFeatures; KPROCESSOR_STATE ProcessorState; KDPC_DATA DpcData[2]; PVOID DpcStack; diff --git a/sdk/xtdk/i686/artypes.h b/sdk/xtdk/i686/artypes.h index 5dab6e1..c9f2142 100644 --- a/sdk/xtdk/i686/artypes.h +++ b/sdk/xtdk/i686/artypes.h @@ -61,11 +61,16 @@ #define SEGMENT_FS 0x64 #define SEGMENT_GS 0x65 +/* CPUID vendor names */ +#define CPUID_VENDOR_NAME_AMD "AuthenticAMD" +#define CPUID_VENDOR_NAME_INTEL "GenuineIntel" + /* CPU vendor enumeration list */ typedef enum _CPU_VENDOR { - CPU_VENDOR_AMD = 0x68747541, - CPU_VENDOR_INTEL = 0x756e6547, + CPU_VENDOR_INVALID, + CPU_VENDOR_AMD, + CPU_VENDOR_INTEL, CPU_VENDOR_UNKNOWN = 0xFFFFFFFF } CPU_VENDOR, *PCPU_VENDOR; @@ -95,7 +100,7 @@ typedef enum _CPUID_FEATURES CPUID_FEATURES_ECX_X2APIC = 1 << 21, CPUID_FEATURES_ECX_MOVBE = 1 << 22, CPUID_FEATURES_ECX_POPCNT = 1 << 23, - CPUID_FEATURES_ECX_TSC = 1 << 24, + CPUID_FEATURES_ECX_TSC_DEADLINE = 1 << 24, CPUID_FEATURES_ECX_AES = 1 << 25, CPUID_FEATURES_ECX_XSAVE = 1 << 26, CPUID_FEATURES_ECX_OSXSAVE = 1 << 27, @@ -135,6 +140,92 @@ typedef enum _CPUID_FEATURES CPUID_FEATURES_EDX_PBE = 1 << 31 } CPUID_FEATURES, *PCPUID_FEATURES; +/* CPU features, as reported by CPUID instruction */ +typedef union _CPU_FEATURES +{ + UINT64 Value; + union + { + UINT32 Ecx; + UINT32 ExtendedFeatures; + struct + { + BYTE SSE3 : 1; + BYTE PCLMUL : 1; + BYTE DTES64 : 1; + BYTE MONITOR : 1; + BYTE DS_CPL : 1; + BYTE VMX : 1; + BYTE SMX : 1; + BYTE EST : 1; + BYTE TM2 : 1; + BYTE SSSE3 : 1; + BYTE CID : 1; + BYTE SDBG : 1; + BYTE FMA : 1; + BYTE CX16 : 1; + BYTE XTPR : 1; + BYTE PDCM : 1; + BYTE Reserved1 : 1; // Bit 16 is reserved + BYTE PCID : 1; + BYTE DCA : 1; + BYTE SSE4_1 : 1; + BYTE SSE4_2 : 1; + BYTE X2APIC : 1; + BYTE MOVBE : 1; + BYTE POPCNT : 1; + BYTE TSC_DEADLINE : 1; + BYTE AES : 1; + BYTE XSAVE : 1; + BYTE OSXSAVE : 1; + BYTE AVX : 1; + BYTE F16C : 1; + BYTE RDRAND : 1; + BYTE HYPERVISOR : 1; + }; + }; + union + { + UINT32 Edx; + UINT32 Features; + struct + { + BYTE FPU : 1; + BYTE VME : 1; + BYTE DE : 1; + BYTE PSE : 1; + BYTE TSC : 1; + BYTE MSR : 1; + BYTE PAE : 1; + BYTE MCE : 1; + BYTE CX8 : 1; + BYTE APIC : 1; + BYTE Reserved2 : 1; // Bit 10 is reserved + BYTE SEP : 1; + BYTE MTRR : 1; + BYTE PGE : 1; + BYTE MCA : 1; + BYTE CMOV : 1; + BYTE PAT : 1; + BYTE PSE36 : 1; + BYTE PSN : 1; + BYTE CLFLUSH : 1; + BYTE Reserved3 : 1; // Bit 20 is reserved + BYTE DS : 1; + BYTE ACPI : 1; + BYTE MMX : 1; + BYTE FXSR : 1; + BYTE SSE : 1; + BYTE SSE2 : 1; + BYTE SS : 1; + BYTE HTT : 1; + BYTE TM : 1; + BYTE Reserved4 : 1; // Bit 30 is reserved + BYTE PBE : 1; + }; + }; +} CPU_FEATURES, *PCPU_FEATURES; + /* CPUID requests */ typedef enum _CPUID_REQUESTS { diff --git a/sdk/xtdk/i686/ketypes.h b/sdk/xtdk/i686/ketypes.h index 4c01e93..3f4051a 100644 --- a/sdk/xtdk/i686/ketypes.h +++ b/sdk/xtdk/i686/ketypes.h @@ -461,6 +461,7 @@ typedef struct _KPROCESSOR_CONTROL_BLOCK UCHAR Number; ULONG_PTR SetMember; CPU_IDENTIFICATION CpuId; + CPU_FEATURES CpuFeatures; KPROCESSOR_STATE ProcessorState; ULONG_PTR MultiThreadProcessorSet; KDPC_DATA DpcData[2]; diff --git a/xtoskrnl/ar/amd64/procsup.c b/xtoskrnl/ar/amd64/procsup.c index 417368e..bd7bd68 100644 --- a/xtoskrnl/ar/amd64/procsup.c +++ b/xtoskrnl/ar/amd64/procsup.c @@ -108,8 +108,7 @@ ArSetGdtEntryBase(IN PKGDTENTRY Gdt, } /** - * Identifies processor type (vendor, model, stepping) as well as looks for available CPU features and stores them - * in Processor Control Block (PRCB). + * Sets the CPU vendor information in the processor control block (PRCB). * * @return This routine does not return any value. * @@ -117,29 +116,62 @@ ArSetGdtEntryBase(IN PKGDTENTRY Gdt, */ XTAPI VOID -ArpIdentifyProcessor(VOID) +ArpSetCpuVendor() { PKPROCESSOR_CONTROL_BLOCK Prcb; CPUID_REGISTERS CpuRegisters; - CPUID_SIGNATURE CpuSignature; - - /* Not fully implemented yet */ - UNIMPLEMENTED; + UINT32 VendorNameBytes[3]; /* Get current processor control block */ Prcb = KeGetCurrentProcessorControlBlock(); - /* Get CPU vendor by issueing CPUID instruction */ + /* Get CPU vendor by issuing CPUID instruction */ RtlZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_VENDOR_STRING; ArCpuId(&CpuRegisters); - /* Store CPU vendor in processor control block */ - Prcb->CpuId.Vendor = CpuRegisters.Ebx; - Prcb->CpuId.VendorName[0] = CpuRegisters.Ebx; - Prcb->CpuId.VendorName[4] = CpuRegisters.Edx; - Prcb->CpuId.VendorName[8] = CpuRegisters.Ecx; - Prcb->CpuId.VendorName[12] = '\0'; + /* Order CPU vendor name bytes */ + VendorNameBytes[0] = CpuRegisters.Ebx; + VendorNameBytes[1] = CpuRegisters.Edx; + VendorNameBytes[2] = CpuRegisters.Ecx; + + /* Copy CPU vendor name to processor control block */ + RtlZeroMemory(&Prcb->CpuId.VendorName[0], 13); + RtlCopyMemory(&Prcb->CpuId.VendorName[0], &VendorNameBytes[0], 12); + + /* Set CPU vendor on processor control block by comparing known vendor names */ + if (RtlCompareMemory(&Prcb->CpuId.VendorName[0], CPUID_VENDOR_NAME_AMD, 12) == 12) + { + Prcb->CpuId.Vendor = CPU_VENDOR_AMD; + } + else if (RtlCompareMemory(&Prcb->CpuId.VendorName[0], CPUID_VENDOR_NAME_INTEL, 12) == 12) + { + Prcb->CpuId.Vendor = CPU_VENDOR_INTEL; + } + else + { + Prcb->CpuId.Vendor = CPU_VENDOR_UNKNOWN; + } +} + +/** + * Sets the CPU features information in the processor control block (PRCB). + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +ArpSetCpuFeatures(VOID) +{ + PKPROCESSOR_CONTROL_BLOCK Prcb; + CPUID_REGISTERS CpuRegisters; + CPUID_SIGNATURE CpuSignature; + UINT32 FeatureArray[2]; + + /* Get current processor control block */ + Prcb = KeGetCurrentProcessorControlBlock(); /* Get CPU features */ RtlZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); @@ -153,24 +185,25 @@ ArpIdentifyProcessor(VOID) Prcb->CpuId.Stepping = CpuSignature.Stepping; /* CPU vendor specific quirks */ - if(Prcb->CpuId.Vendor == CPU_VENDOR_AMD) + if (Prcb->CpuId.Vendor == CPU_VENDOR_AMD) { /* AMD CPU */ Prcb->CpuId.Family = Prcb->CpuId.Family + CpuSignature.ExtendedFamily; - if(Prcb->CpuId.Model == 0xF) + + if (Prcb->CpuId.Model == 0xF) { Prcb->CpuId.Model = Prcb->CpuId.Model + (CpuSignature.ExtendedModel << 4); } } - else if(Prcb->CpuId.Vendor == CPU_VENDOR_INTEL) + else if (Prcb->CpuId.Vendor == CPU_VENDOR_INTEL) { /* Intel CPU */ - if(Prcb->CpuId.Family == 0xF) + if (Prcb->CpuId.Family == 0xF) { Prcb->CpuId.Family = Prcb->CpuId.Family + CpuSignature.ExtendedFamily; } - if((Prcb->CpuId.Family == 0xF) || (Prcb->CpuId.Family == 0x6)) + if ((Prcb->CpuId.Family == 0xF) || (Prcb->CpuId.Family == 0x6)) { Prcb->CpuId.Model = Prcb->CpuId.Model + (CpuSignature.ExtendedModel << 4); } @@ -181,7 +214,29 @@ ArpIdentifyProcessor(VOID) Prcb->CpuId.Vendor = CPU_VENDOR_UNKNOWN; } - /* TODO: Store a list of CPU features in processor control block */ + /* Store CPU features in processor control block */ + FeatureArray[0] = CpuRegisters.Edx; + FeatureArray[1] = CpuRegisters.Ecx; + RtlCopyMemory(&Prcb->CpuFeatures, &FeatureArray[0], sizeof(UINT64)); +} + +/** + * Identifies processor type (vendor, model, stepping) as well as looks for available CPU features and stores them + * in Processor Control Block (PRCB). + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +ArpIdentifyProcessor(VOID) +{ + /* Set CPU vendor */ + ArpSetCpuVendor(); + + /* Set CPU features */ + ArpSetCpuFeatures(); } /** diff --git a/xtoskrnl/ar/i686/procsup.c b/xtoskrnl/ar/i686/procsup.c index 99856cd..b6b0fdf 100644 --- a/xtoskrnl/ar/i686/procsup.c +++ b/xtoskrnl/ar/i686/procsup.c @@ -105,8 +105,7 @@ ArSetGdtEntryBase(IN PKGDTENTRY Gdt, } /** - * Identifies processor type (vendor, model, stepping) as well as looks for available CPU features and stores them - * in Processor Control Block (PRCB). + * Sets the CPU vendor information in the processor control block (PRCB). * * @return This routine does not return any value. * @@ -114,14 +113,11 @@ ArSetGdtEntryBase(IN PKGDTENTRY Gdt, */ XTAPI VOID -ArpIdentifyProcessor(VOID) +ArpSetCpuVendor() { PKPROCESSOR_CONTROL_BLOCK Prcb; CPUID_REGISTERS CpuRegisters; - CPUID_SIGNATURE CpuSignature; - - /* Not fully implemented yet */ - UNIMPLEMENTED; + UINT32 VendorNameBytes[3]; /* Get current processor control block */ Prcb = KeGetCurrentProcessorControlBlock(); @@ -131,12 +127,48 @@ ArpIdentifyProcessor(VOID) CpuRegisters.Leaf = CPUID_GET_VENDOR_STRING; ArCpuId(&CpuRegisters); - /* Store CPU vendor in processor control block */ - Prcb->CpuId.Vendor = CpuRegisters.Ebx; - Prcb->CpuId.VendorName[0] = CpuRegisters.Ebx; - Prcb->CpuId.VendorName[4] = CpuRegisters.Edx; - Prcb->CpuId.VendorName[8] = CpuRegisters.Ecx; - Prcb->CpuId.VendorName[12] = '\0'; + /* Fix CPU vendor name bytes order */ + VendorNameBytes[0] = CpuRegisters.Ebx; + VendorNameBytes[1] = CpuRegisters.Edx; + VendorNameBytes[2] = CpuRegisters.Ecx; + + /* Copy CPU vendor name to processor control block */ + RtlZeroMemory(&Prcb->CpuId.VendorName[0], 13); + RtlCopyMemory(&Prcb->CpuId.VendorName[0], &VendorNameBytes[0], 12); + + /* Set CPU vendor on processor control block by comparing known vendor names */ + if (RtlCompareMemory(&Prcb->CpuId.VendorName[0], CPUID_VENDOR_NAME_AMD, 12) == 12) + { + Prcb->CpuId.Vendor = CPU_VENDOR_AMD; + } + else if (RtlCompareMemory(&Prcb->CpuId.VendorName[0], CPUID_VENDOR_NAME_INTEL, 12) == 12) + { + Prcb->CpuId.Vendor = CPU_VENDOR_INTEL; + } + else + { + Prcb->CpuId.Vendor = CPU_VENDOR_UNKNOWN; + } +} + +/** + * Sets the CPU features information in the processor control block (PRCB). + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +ArpSetCpuFeatures(VOID) +{ + PKPROCESSOR_CONTROL_BLOCK Prcb; + CPUID_REGISTERS CpuRegisters; + CPUID_SIGNATURE CpuSignature; + UINT32 FeatureArray[2]; + + /* Get current processor control block */ + Prcb = KeGetCurrentProcessorControlBlock(); /* Get CPU features */ RtlZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); @@ -149,25 +181,29 @@ ArpIdentifyProcessor(VOID) Prcb->CpuId.Model = CpuSignature.Model; Prcb->CpuId.Stepping = CpuSignature.Stepping; + /* Prcb->CpuId.Vendor print*/ + DebugPrint(L"CPU Signature: %s\n", Prcb->CpuId.Vendor); + /* CPU vendor specific quirks */ - if(Prcb->CpuId.Vendor == CPU_VENDOR_AMD) + if (Prcb->CpuId.Vendor == CPU_VENDOR_AMD) { /* AMD CPU */ Prcb->CpuId.Family = Prcb->CpuId.Family + CpuSignature.ExtendedFamily; - if(Prcb->CpuId.Model == 0xF) + + if (Prcb->CpuId.Model == 0xF) { Prcb->CpuId.Model = Prcb->CpuId.Model + (CpuSignature.ExtendedModel << 4); } } - else if(Prcb->CpuId.Vendor == CPU_VENDOR_INTEL) + else if (Prcb->CpuId.Vendor == CPU_VENDOR_INTEL) { /* Intel CPU */ - if(Prcb->CpuId.Family == 0xF) + if (Prcb->CpuId.Family == 0xF) { Prcb->CpuId.Family = Prcb->CpuId.Family + CpuSignature.ExtendedFamily; } - if((Prcb->CpuId.Family == 0xF) || (Prcb->CpuId.Family == 0x6)) + if ((Prcb->CpuId.Family == 0xF) || (Prcb->CpuId.Family == 0x6)) { Prcb->CpuId.Model = Prcb->CpuId.Model + (CpuSignature.ExtendedModel << 4); } @@ -178,7 +214,29 @@ ArpIdentifyProcessor(VOID) Prcb->CpuId.Vendor = CPU_VENDOR_UNKNOWN; } - /* TODO: Store a list of CPU features in processor control block */ + /* Store CPU features in processor control block */ + FeatureArray[0] = CpuRegisters.Edx; + FeatureArray[1] = CpuRegisters.Ecx; + RtlCopyMemory(&Prcb->CpuFeatures, &FeatureArray[0], sizeof(UINT64)); +} + +/** + * Identifies processor type (vendor, model, stepping) as well as looks for available CPU features and stores them + * in Processor Control Block (PRCB). + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +ArpIdentifyProcessor(VOID) +{ + /* Set CPU vendor */ + ArpSetCpuVendor(); + + /* Set CPU features */ + ArpSetCpuFeatures(); } /** diff --git a/xtoskrnl/includes/amd64/ar.h b/xtoskrnl/includes/amd64/ar.h index 96d7fa2..5cef37b 100644 --- a/xtoskrnl/includes/amd64/ar.h +++ b/xtoskrnl/includes/amd64/ar.h @@ -288,4 +288,12 @@ ArpSetIdtGate(IN PKIDTENTRY Idt, IN USHORT Ist, IN USHORT Access); +XTAPI +VOID +ArpSetCpuVendor(VOID); + +XTAPI +VOID +ArpSetCpuFeatures(VOID); + #endif /* __XTOSKRNL_AMD64_AR_H */ diff --git a/xtoskrnl/includes/i686/ar.h b/xtoskrnl/includes/i686/ar.h index c127954..f77c0ef 100644 --- a/xtoskrnl/includes/i686/ar.h +++ b/xtoskrnl/includes/i686/ar.h @@ -284,4 +284,12 @@ XTAPI VOID ArpSetNonMaskableInterruptTssEntry(IN PKPROCESSOR_BLOCK ProcessorBlock); +XTAPI +VOID +ArpSetCpuVendor(VOID); + +XTAPI +VOID +ArpSetCpuFeatures(VOID); + #endif /* __XTOSKRNL_I686_AR_H */