feat: Add CPU vendor and features identification
Add functionality to identify the CPU vendor and features using the CPUID instruction. The CPU vendor information is stored in the Processor Control Block (PRCB), including the vendor name and a corresponding enumeration. CPU features are also retrieved and stored in the PRCB. Previously, the CPU vendor was not properly stored in the PRCB, caused by a missing type cast. Using Rtl functions to copy the CPU vendor name to the PRCB. Details: - Introduced functions `ArpSetCpuVendor` and `ArpSetCpuFeatures` to set CPU vendor and features, respectively. - Modified `ArpIdentifyProcessor` to call the new functions for vendor and features identification. - Added `CPU_FEATURES` structure to `KPROCESSOR_CONTROL_BLOCK` structure to store CPU features. Tests: - Tested x86_64 on QEMU. Verified that the CPU vendor and features are correctly identified and stored in the PRCB.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user