diff --git a/sdk/xtdk/amd64/artypes.h b/sdk/xtdk/amd64/artypes.h index e2ad86b..e3607b0 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,84 @@ typedef enum _CPUID_FEATURES CPUID_FEATURES_EDX_PBE = 1 << 31 } CPUID_FEATURES, *PCPUID_FEATURES; +/* CPU features, as reported by CPUID instruction */ +typedef struct _CPU_FEATURES { + union { + struct { + BOOLEAN SSE3 : 1; + BOOLEAN PCLMUL : 1; + BOOLEAN DTES64 : 1; + BOOLEAN MONITOR : 1; + BOOLEAN DS_CPL : 1; + BOOLEAN VMX : 1; + BOOLEAN SMX : 1; + BOOLEAN EST : 1; + BOOLEAN TM2 : 1; + BOOLEAN SSSE3 : 1; + BOOLEAN CID : 1; + BOOLEAN SDBG : 1; + BOOLEAN FMA : 1; + BOOLEAN CX16 : 1; + BOOLEAN XTPR : 1; + BOOLEAN PDCM : 1; + BOOLEAN Reserved1 : 1; // Bit 16 is reserved + BOOLEAN PCID : 1; + BOOLEAN DCA : 1; + BOOLEAN SSE4_1 : 1; + BOOLEAN SSE4_2 : 1; + BOOLEAN X2APIC : 1; + BOOLEAN MOVBE : 1; + BOOLEAN POPCNT : 1; + BOOLEAN TSC_DEADLINE : 1; + BOOLEAN AES : 1; + BOOLEAN XSAVE : 1; + BOOLEAN OSXSAVE : 1; + BOOLEAN AVX : 1; + BOOLEAN F16C : 1; + BOOLEAN RDRAND : 1; + BOOLEAN HYPERVISOR : 1; + }; + UINT32 ExtendedFeatures; + }; + union { + struct { + BOOLEAN FPU : 1; + BOOLEAN VME : 1; + BOOLEAN DE : 1; + BOOLEAN PSE : 1; + BOOLEAN TSC : 1; + BOOLEAN MSR : 1; + BOOLEAN PAE : 1; + BOOLEAN MCE : 1; + BOOLEAN CX8 : 1; + BOOLEAN APIC : 1; + BOOLEAN Reserved2 : 1; // Bit 10 is reserved + BOOLEAN SEP : 1; + BOOLEAN MTRR : 1; + BOOLEAN PGE : 1; + BOOLEAN MCA : 1; + BOOLEAN CMOV : 1; + BOOLEAN PAT : 1; + BOOLEAN PSE36 : 1; + BOOLEAN PSN : 1; + BOOLEAN CLFLUSH : 1; + BOOLEAN Reserved3 : 1; // Bit 20 is reserved + BOOLEAN DS : 1; + BOOLEAN ACPI : 1; + BOOLEAN MMX : 1; + BOOLEAN FXSR : 1; + BOOLEAN SSE : 1; + BOOLEAN SSE2 : 1; + BOOLEAN SS : 1; + BOOLEAN HTT : 1; + BOOLEAN TM : 1; + BOOLEAN Reserved4 : 1; // Bit 30 is reserved + BOOLEAN PBE : 1; + }; + UINT64 Features; + }; +} 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 ee5bcc3..8c3e8b2 100644 --- a/sdk/xtdk/amd64/ketypes.h +++ b/sdk/xtdk/amd64/ketypes.h @@ -514,6 +514,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..1c8cd77 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,79 @@ typedef enum _CPUID_FEATURES CPUID_FEATURES_EDX_PBE = 1 << 31 } CPUID_FEATURES, *PCPUID_FEATURES; +/* CPU features, as reported by CPUID instruction */ +typedef struct _CPU_FEATURES { + union { + struct { + BOOLEAN SSE3 : 1; + BOOLEAN PCLMUL : 1; + BOOLEAN DTES64 : 1; + BOOLEAN MONITOR : 1; + BOOLEAN DS_CPL : 1; + BOOLEAN VMX : 1; + BOOLEAN SMX : 1; + BOOLEAN EST : 1; + BOOLEAN TM2 : 1; + BOOLEAN SSSE3 : 1; + BOOLEAN CID : 1; + BOOLEAN SDBG : 1; + BOOLEAN FMA : 1; + BOOLEAN CX16 : 1; + BOOLEAN XTPR : 1; + BOOLEAN PDCM : 1; + BOOLEAN Reserved1 : 1; // Bit 16 is reserved + BOOLEAN PCID : 1; + BOOLEAN DCA : 1; + BOOLEAN SSE4_1 : 1; + BOOLEAN SSE4_2 : 1; + BOOLEAN X2APIC : 1; + BOOLEAN MOVBE : 1; + BOOLEAN POPCNT : 1; + BOOLEAN TSC_DEADLINE : 1; + BOOLEAN AES : 1; + BOOLEAN XSAVE : 1; + BOOLEAN OSXSAVE : 1; + BOOLEAN AVX : 1; + BOOLEAN F16C : 1; + BOOLEAN RDRAND : 1; + BOOLEAN HYPERVISOR : 1; + BOOLEAN FPU : 1; + BOOLEAN VME : 1; + BOOLEAN DE : 1; + BOOLEAN PSE : 1; + BOOLEAN TSC : 1; + BOOLEAN MSR : 1; + BOOLEAN PAE : 1; + BOOLEAN MCE : 1; + BOOLEAN CX8 : 1; + BOOLEAN APIC : 1; + BOOLEAN Reserved2 : 1; // Bit 10 is reserved + BOOLEAN SEP : 1; + BOOLEAN MTRR : 1; + BOOLEAN PGE : 1; + BOOLEAN MCA : 1; + BOOLEAN CMOV : 1; + BOOLEAN PAT : 1; + BOOLEAN PSE36 : 1; + BOOLEAN PSN : 1; + BOOLEAN CLFLUSH : 1; + BOOLEAN Reserved3 : 1; // Bit 20 is reserved + BOOLEAN DS : 1; + BOOLEAN ACPI : 1; + BOOLEAN MMX : 1; + BOOLEAN FXSR : 1; + BOOLEAN SSE : 1; + BOOLEAN SSE2 : 1; + BOOLEAN SS : 1; + BOOLEAN HTT : 1; + BOOLEAN TM : 1; + BOOLEAN Reserved4 : 1; // Bit 30 is reserved + BOOLEAN PBE : 1; + }; + UINT64 AsUINT64; + }; +} 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 7069eb5..30826a5 100644 --- a/sdk/xtdk/i686/ketypes.h +++ b/sdk/xtdk/i686/ketypes.h @@ -454,6 +454,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 5c165ec..f4d880e 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 77d258e..5ed9cd1 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 */