From ca4f3acc0edb5446a0f438a2cc5125d45b400911 Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Thu, 14 May 2026 18:59:00 +0200 Subject: [PATCH] Properly identify CPU vendor --- xtoskrnl/ar/amd64/procsup.cc | 181 +++++++++++++++----------- xtoskrnl/ar/i686/procsup.cc | 176 ++++++++++++++----------- xtoskrnl/includes/ar/amd64/procsup.hh | 1 + xtoskrnl/includes/ar/i686/procsup.hh | 2 +- 4 files changed, 211 insertions(+), 149 deletions(-) diff --git a/xtoskrnl/ar/amd64/procsup.cc b/xtoskrnl/ar/amd64/procsup.cc index 1ee51de..16aab6b 100644 --- a/xtoskrnl/ar/amd64/procsup.cc +++ b/xtoskrnl/ar/amd64/procsup.cc @@ -20,6 +20,7 @@ XTAPI PVOID AR::ProcSup::GetBootStack(VOID) { + /* Return base address of kernel boot stack */ return (PVOID)((ULONG_PTR)BootStack + KERNEL_STACK_SIZE); } @@ -29,19 +30,23 @@ AR::ProcSup::GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType, OUT PVOID *TrampolineCode, OUT PULONG_PTR TrampolineSize) { + /* Get trampoline information */ switch(TrampolineType) { case TrampolineApStartup: + /* Get AP startup trampoline information */ *TrampolineCode = (PVOID)ArStartApplicationProcessor; *TrampolineSize = (ULONG_PTR)ArStartApplicationProcessorEnd - (ULONG_PTR)ArStartApplicationProcessor; break; case TrampolineEnableXpa: + /* Get Enable XPA trampoline information */ *TrampolineCode = (PVOID)ArEnableExtendedPhysicalAddressing; *TrampolineSize = (ULONG_PTR)ArEnableExtendedPhysicalAddressingEnd - (ULONG_PTR)ArEnableExtendedPhysicalAddressing; break; default: + /* Unknown trampoline type */ *TrampolineCode = NULLPTR; *TrampolineSize = 0; break; @@ -64,9 +69,6 @@ AR::ProcSup::IdentifyProcessor(VOID) CPUID_REGISTERS CpuRegisters; CPUID_SIGNATURE CpuSignature; - /* Not fully implemented yet */ - UNIMPLEMENTED; - /* Get current processor control block */ Prcb = KE::Processor::GetCurrentProcessorControlBlock(); @@ -75,13 +77,29 @@ AR::ProcSup::IdentifyProcessor(VOID) CpuRegisters.Leaf = CPUID_GET_VENDOR_STRING; AR::CpuFunc::CpuId(&CpuRegisters); - /* Store CPU vendor in processor control block */ - Prcb->CpuId.Vendor = (CPU_VENDOR)CpuRegisters.Ebx; + /* Store CPU vendor name in processor control block */ *(PULONG)&Prcb->CpuId.VendorName[0] = CpuRegisters.Ebx; *(PULONG)&Prcb->CpuId.VendorName[4] = CpuRegisters.Edx; *(PULONG)&Prcb->CpuId.VendorName[8] = CpuRegisters.Ecx; Prcb->CpuId.VendorName[12] = '\0'; + /* Resolve CPU vendor */ + if(RTL::Memory::CompareMemory(Prcb->CpuId.VendorName, "AuthenticAMD", 12) == 12) + { + /* AMD CPU */ + Prcb->CpuId.Vendor = CPU_VENDOR_AMD; + } + else if(RTL::Memory::CompareMemory(Prcb->CpuId.VendorName, "GenuineIntel", 12) == 12) + { + /* Intel CPU */ + Prcb->CpuId.Vendor = CPU_VENDOR_INTEL; + } + else + { + /* Unknown CPU vendor */ + Prcb->CpuId.Vendor = CPU_VENDOR_UNKNOWN; + } + /* Get CPU standard features */ RtlZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES; @@ -116,17 +134,13 @@ AR::ProcSup::IdentifyProcessor(VOID) Prcb->CpuId.Model += (CpuSignature.ExtendedModel << 4); } } - else - { - /* Unknown CPU vendor */ - Prcb->CpuId.Vendor = CPU_VENDOR_UNKNOWN; - } - /* TODO: Store a list of CPU features in processor control block */ + /* Identify processor features */ + IdentifyProcessorFeatures(); } /** - * Initializes AMD64 processor specific structures. + * Identifies processor features and stores them in Processor Control Block (PRCB). * * @return This routine does not return any value. * @@ -134,71 +148,12 @@ AR::ProcSup::IdentifyProcessor(VOID) */ XTAPI VOID -AR::ProcSup::InitializeProcessor(IN PVOID ProcessorStructures) +AR::ProcSup::IdentifyProcessorFeatures(VOID) { - PVOID KernelBootStack, KernelFaultStack, KernelNmiStack; - KDESCRIPTOR GdtDescriptor, IdtDescriptor; - PKPROCESSOR_BLOCK ProcessorBlock; - PKGDTENTRY Gdt; - PKIDTENTRY Idt; - PKTSS Tss; + PKPROCESSOR_CONTROL_BLOCK Prcb; - /* Check if processor structures buffer provided */ - if(ProcessorStructures) - { - /* Assign CPU structures from provided buffer */ - InitializeProcessorStructures(ProcessorStructures, &Gdt, &Tss, &ProcessorBlock, - &KernelBootStack, &KernelFaultStack, &KernelNmiStack); - - /* Use global IDT */ - Idt = InitialIdt; - } - else - { - /* Use initial structures */ - Gdt = InitialGdt; - Idt = InitialIdt; - Tss = &InitialTss; - KernelBootStack = (PVOID)((ULONG_PTR)&BootStack + KERNEL_STACK_SIZE); - KernelFaultStack = (PVOID)((ULONG_PTR)&FaultStack + KERNEL_STACK_SIZE); - KernelNmiStack = (PVOID)((ULONG_PTR)&NmiStack + KERNEL_STACK_SIZE); - ProcessorBlock = &InitialProcessorBlock; - } - - /* Initialize processor block */ - InitializeProcessorBlock(ProcessorBlock, Gdt, Idt, Tss, KernelFaultStack); - - /* Initialize GDT, IDT and TSS */ - InitializeGdt(ProcessorBlock); - InitializeIdt(ProcessorBlock); - InitializeTss(ProcessorBlock, KernelBootStack, KernelFaultStack, KernelNmiStack); - - /* Set GDT and IDT descriptors */ - GdtDescriptor.Base = Gdt; - GdtDescriptor.Limit = (GDT_ENTRIES * sizeof(KGDTENTRY)) - 1; - IdtDescriptor.Base = Idt; - IdtDescriptor.Limit = (IDT_ENTRIES * sizeof(KIDTENTRY)) - 1; - - /* Load GDT, IDT and TSS */ - AR::CpuFunc::LoadGlobalDescriptorTable(&GdtDescriptor.Limit); - AR::CpuFunc::LoadInterruptDescriptorTable(&IdtDescriptor.Limit); - AR::CpuFunc::LoadTaskRegister((UINT)KGDT_SYS_TSS); - - /* Enter passive IRQ level */ - HL::RunLevel::SetRunLevel(PASSIVE_LEVEL); - - /* Initialize segment registers */ - InitializeSegments(); - - /* Set GS base */ - AR::CpuFunc::WriteModelSpecificRegister(X86_MSR_GSBASE, (ULONGLONG)ProcessorBlock); - AR::CpuFunc::WriteModelSpecificRegister(X86_MSR_KERNEL_GSBASE, (ULONGLONG)ProcessorBlock); - - /* Initialize processor registers */ - InitializeProcessorRegisters(); - - /* Identify processor */ - IdentifyProcessor(); + /* Get current processor control block */ + Prcb = KE::Processor::GetCurrentProcessorControlBlock(); } /** @@ -281,6 +236,82 @@ AR::ProcSup::InitializeIdt(IN PKPROCESSOR_BLOCK ProcessorBlock) SetIdtGate(ProcessorBlock->IdtBase, 0xE1, (PVOID)ArInterruptEntry[0xE1], KGDT_R0_CODE, KIDT_IST_RESERVED, KIDT_ACCESS_RING0, AMD64_INTERRUPT_GATE); } +/** + * Initializes AMD64 processor specific structures. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +AR::ProcSup::InitializeProcessor(IN PVOID ProcessorStructures) +{ + PVOID KernelBootStack, KernelFaultStack, KernelNmiStack; + KDESCRIPTOR GdtDescriptor, IdtDescriptor; + PKPROCESSOR_BLOCK ProcessorBlock; + PKGDTENTRY Gdt; + PKIDTENTRY Idt; + PKTSS Tss; + + /* Check if processor structures buffer provided */ + if(ProcessorStructures) + { + /* Assign CPU structures from provided buffer */ + InitializeProcessorStructures(ProcessorStructures, &Gdt, &Tss, &ProcessorBlock, + &KernelBootStack, &KernelFaultStack, &KernelNmiStack); + + /* Use global IDT */ + Idt = InitialIdt; + } + else + { + /* Use initial structures */ + Gdt = InitialGdt; + Idt = InitialIdt; + Tss = &InitialTss; + KernelBootStack = (PVOID)((ULONG_PTR)&BootStack + KERNEL_STACK_SIZE); + KernelFaultStack = (PVOID)((ULONG_PTR)&FaultStack + KERNEL_STACK_SIZE); + KernelNmiStack = (PVOID)((ULONG_PTR)&NmiStack + KERNEL_STACK_SIZE); + ProcessorBlock = &InitialProcessorBlock; + } + + /* Initialize processor block */ + InitializeProcessorBlock(ProcessorBlock, Gdt, Idt, Tss, KernelFaultStack); + + /* Initialize GDT, IDT and TSS */ + InitializeGdt(ProcessorBlock); + InitializeIdt(ProcessorBlock); + InitializeTss(ProcessorBlock, KernelBootStack, KernelFaultStack, KernelNmiStack); + + /* Set GDT and IDT descriptors */ + GdtDescriptor.Base = Gdt; + GdtDescriptor.Limit = (GDT_ENTRIES * sizeof(KGDTENTRY)) - 1; + IdtDescriptor.Base = Idt; + IdtDescriptor.Limit = (IDT_ENTRIES * sizeof(KIDTENTRY)) - 1; + + /* Load GDT, IDT and TSS */ + AR::CpuFunc::LoadGlobalDescriptorTable(&GdtDescriptor.Limit); + AR::CpuFunc::LoadInterruptDescriptorTable(&IdtDescriptor.Limit); + AR::CpuFunc::LoadTaskRegister((UINT)KGDT_SYS_TSS); + + /* Enter passive IRQ level */ + HL::RunLevel::SetRunLevel(PASSIVE_LEVEL); + + /* Initialize segment registers */ + InitializeSegments(); + + /* Set GS base */ + AR::CpuFunc::WriteModelSpecificRegister(X86_MSR_GSBASE, (ULONGLONG)ProcessorBlock); + AR::CpuFunc::WriteModelSpecificRegister(X86_MSR_KERNEL_GSBASE, (ULONGLONG)ProcessorBlock); + + /* Initialize processor registers */ + InitializeProcessorRegisters(); + + /* Identify processor */ + IdentifyProcessor(); +} + /** * Initializes processor block. * diff --git a/xtoskrnl/ar/i686/procsup.cc b/xtoskrnl/ar/i686/procsup.cc index 937d818..4957b83 100644 --- a/xtoskrnl/ar/i686/procsup.cc +++ b/xtoskrnl/ar/i686/procsup.cc @@ -20,6 +20,7 @@ XTAPI PVOID AR::ProcSup::GetBootStack(VOID) { + /* Return base address of kernel boot stack */ return (PVOID)((ULONG_PTR)BootStack + KERNEL_STACK_SIZE); } @@ -29,14 +30,17 @@ AR::ProcSup::GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType, OUT PVOID *TrampolineCode, OUT PULONG_PTR TrampolineSize) { + /* Get trampoline information */ switch(TrampolineType) { case TrampolineApStartup: + /* Get AP startup trampoline information */ *TrampolineCode = (PVOID)ArStartApplicationProcessor; *TrampolineSize = (ULONG_PTR)ArStartApplicationProcessorEnd - (ULONG_PTR)ArStartApplicationProcessor; break; default: + /* Unknown trampoline type */ *TrampolineCode = NULLPTR; *TrampolineSize = 0; break; @@ -44,8 +48,7 @@ AR::ProcSup::GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType, } /** - * Identifies processor type (vendor, model, stepping) as well as looks for available CPU features and stores them - * in Processor Control Block (PRCB). + * Identifies processor type (vendor, model, stepping) and stores them in Processor Control Block (PRCB). * * @return This routine does not return any value. * @@ -59,9 +62,6 @@ AR::ProcSup::IdentifyProcessor(VOID) CPUID_REGISTERS CpuRegisters; CPUID_SIGNATURE CpuSignature; - /* Not fully implemented yet */ - UNIMPLEMENTED; - /* Get current processor control block */ Prcb = KE::Processor::GetCurrentProcessorControlBlock(); @@ -70,13 +70,29 @@ AR::ProcSup::IdentifyProcessor(VOID) CpuRegisters.Leaf = CPUID_GET_VENDOR_STRING; AR::CpuFunc::CpuId(&CpuRegisters); - /* Store CPU vendor in processor control block */ - Prcb->CpuId.Vendor = (CPU_VENDOR)CpuRegisters.Ebx; + /* Store CPU vendor name in processor control block */ *(PULONG)&Prcb->CpuId.VendorName[0] = CpuRegisters.Ebx; *(PULONG)&Prcb->CpuId.VendorName[4] = CpuRegisters.Edx; *(PULONG)&Prcb->CpuId.VendorName[8] = CpuRegisters.Ecx; Prcb->CpuId.VendorName[12] = '\0'; + /* Resolve CPU vendor */ + if(RTL::Memory::CompareMemory(Prcb->CpuId.VendorName, "AuthenticAMD", 12) == 12) + { + /* AMD CPU */ + Prcb->CpuId.Vendor = CPU_VENDOR_AMD; + } + else if(RTL::Memory::CompareMemory(Prcb->CpuId.VendorName, "GenuineIntel", 12) == 12) + { + /* Intel CPU */ + Prcb->CpuId.Vendor = CPU_VENDOR_INTEL; + } + else + { + /* Unknown CPU vendor */ + Prcb->CpuId.Vendor = CPU_VENDOR_UNKNOWN; + } + /* Get CPU standard features */ RtlZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS)); CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES; @@ -111,17 +127,13 @@ AR::ProcSup::IdentifyProcessor(VOID) Prcb->CpuId.Model += (CpuSignature.ExtendedModel << 4); } } - else - { - /* Unknown CPU vendor */ - Prcb->CpuId.Vendor = CPU_VENDOR_UNKNOWN; - } - /* TODO: Store a list of CPU features in processor control block */ + /* Identify processor features */ + IdentifyProcessorFeatures(); } /** - * Initializes i686 processor specific structures. + * Identifies processor features and stores them in Processor Control Block (PRCB). * * @return This routine does not return any value. * @@ -129,67 +141,12 @@ AR::ProcSup::IdentifyProcessor(VOID) */ XTAPI VOID -AR::ProcSup::InitializeProcessor(IN PVOID ProcessorStructures) +AR::ProcSup::IdentifyProcessorFeatures(VOID) { - KDESCRIPTOR GdtDescriptor, IdtDescriptor; - PVOID KernelBootStack, KernelFaultStack, KernelNmiStack; - PKPROCESSOR_BLOCK ProcessorBlock; - PKGDTENTRY Gdt; - PKIDTENTRY Idt; - PKTSS Tss; + PKPROCESSOR_CONTROL_BLOCK Prcb; - /* Check if processor structures buffer provided */ - if(ProcessorStructures) - { - /* Assign CPU structures from provided buffer */ - InitializeProcessorStructures(ProcessorStructures, &Gdt, &Tss, &ProcessorBlock, - &KernelBootStack, &KernelFaultStack, &KernelNmiStack); - - /* Use global IDT */ - Idt = InitialIdt; - } - else - { - /* Use initial structures */ - Gdt = InitialGdt; - Idt = InitialIdt; - Tss = &InitialTss; - KernelBootStack = (PVOID)((ULONG_PTR)&BootStack + KERNEL_STACK_SIZE); - KernelFaultStack = (PVOID)((ULONG_PTR)&FaultStack + KERNEL_STACK_SIZE); - KernelNmiStack = (PVOID)((ULONG_PTR)&NmiStack + KERNEL_STACK_SIZE); - ProcessorBlock = &InitialProcessorBlock; - } - - /* Initialize processor block */ - InitializeProcessorBlock(ProcessorBlock, Gdt, Idt, Tss, KernelFaultStack); - - /* Initialize GDT, IDT and TSS */ - InitializeGdt(ProcessorBlock); - InitializeIdt(ProcessorBlock); - InitializeTss(ProcessorBlock, KernelBootStack, KernelFaultStack, KernelNmiStack); - - /* Set GDT and IDT descriptors */ - GdtDescriptor.Base = Gdt; - GdtDescriptor.Limit = (GDT_ENTRIES * sizeof(KGDTENTRY)) - 1; - IdtDescriptor.Base = Idt; - IdtDescriptor.Limit = (IDT_ENTRIES * sizeof(KIDTENTRY)) - 1; - - /* Load GDT, IDT and TSS */ - AR::CpuFunc::LoadGlobalDescriptorTable(&GdtDescriptor.Limit); - AR::CpuFunc::LoadInterruptDescriptorTable(&IdtDescriptor.Limit); - AR::CpuFunc::LoadTaskRegister((UINT)KGDT_SYS_TSS); - - /* Enter passive IRQ level */ - HL::RunLevel::SetRunLevel(PASSIVE_LEVEL); - - /* Initialize segment registers */ - InitializeSegments(); - - /* Initialize processor registers */ - InitializeProcessorRegisters(); - - /* Identify processor */ - IdentifyProcessor(); + /* Get current processor control block */ + Prcb = KE::Processor::GetCurrentProcessorControlBlock(); } /** @@ -274,6 +231,79 @@ AR::ProcSup::InitializeIdt(IN PKPROCESSOR_BLOCK ProcessorBlock) SetIdtGate(ProcessorBlock->IdtBase, 0x2E, (PVOID)ArTrapEntry[0x2E], KGDT_R0_CODE, 0, KIDT_ACCESS_RING3, I686_INTERRUPT_GATE); } + +/** + * Initializes i686 processor specific structures. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +AR::ProcSup::InitializeProcessor(IN PVOID ProcessorStructures) +{ + KDESCRIPTOR GdtDescriptor, IdtDescriptor; + PVOID KernelBootStack, KernelFaultStack, KernelNmiStack; + PKPROCESSOR_BLOCK ProcessorBlock; + PKGDTENTRY Gdt; + PKIDTENTRY Idt; + PKTSS Tss; + + /* Check if processor structures buffer provided */ + if(ProcessorStructures) + { + /* Assign CPU structures from provided buffer */ + InitializeProcessorStructures(ProcessorStructures, &Gdt, &Tss, &ProcessorBlock, + &KernelBootStack, &KernelFaultStack, &KernelNmiStack); + + /* Use global IDT */ + Idt = InitialIdt; + } + else + { + /* Use initial structures */ + Gdt = InitialGdt; + Idt = InitialIdt; + Tss = &InitialTss; + KernelBootStack = (PVOID)((ULONG_PTR)&BootStack + KERNEL_STACK_SIZE); + KernelFaultStack = (PVOID)((ULONG_PTR)&FaultStack + KERNEL_STACK_SIZE); + KernelNmiStack = (PVOID)((ULONG_PTR)&NmiStack + KERNEL_STACK_SIZE); + ProcessorBlock = &InitialProcessorBlock; + } + + /* Initialize processor block */ + InitializeProcessorBlock(ProcessorBlock, Gdt, Idt, Tss, KernelFaultStack); + + /* Initialize GDT, IDT and TSS */ + InitializeGdt(ProcessorBlock); + InitializeIdt(ProcessorBlock); + InitializeTss(ProcessorBlock, KernelBootStack, KernelFaultStack, KernelNmiStack); + + /* Set GDT and IDT descriptors */ + GdtDescriptor.Base = Gdt; + GdtDescriptor.Limit = (GDT_ENTRIES * sizeof(KGDTENTRY)) - 1; + IdtDescriptor.Base = Idt; + IdtDescriptor.Limit = (IDT_ENTRIES * sizeof(KIDTENTRY)) - 1; + + /* Load GDT, IDT and TSS */ + AR::CpuFunc::LoadGlobalDescriptorTable(&GdtDescriptor.Limit); + AR::CpuFunc::LoadInterruptDescriptorTable(&IdtDescriptor.Limit); + AR::CpuFunc::LoadTaskRegister((UINT)KGDT_SYS_TSS); + + /* Enter passive IRQ level */ + HL::RunLevel::SetRunLevel(PASSIVE_LEVEL); + + /* Initialize segment registers */ + InitializeSegments(); + + /* Initialize processor registers */ + InitializeProcessorRegisters(); + + /* Identify processor */ + IdentifyProcessor(); +} + /** * Initializes processor block. * diff --git a/xtoskrnl/includes/ar/amd64/procsup.hh b/xtoskrnl/includes/ar/amd64/procsup.hh index 9591cc4..878a846 100644 --- a/xtoskrnl/includes/ar/amd64/procsup.hh +++ b/xtoskrnl/includes/ar/amd64/procsup.hh @@ -49,6 +49,7 @@ namespace AR private: STATIC XTAPI VOID IdentifyProcessor(VOID); + STATIC XTAPI VOID IdentifyProcessorFeatures(VOID); STATIC XTAPI VOID InitializeGdt(IN PKPROCESSOR_BLOCK ProcessorBlock); STATIC XTAPI VOID InitializeIdt(IN PKPROCESSOR_BLOCK ProcessorBlock); STATIC XTAPI VOID InitializeProcessorBlock(OUT PKPROCESSOR_BLOCK ProcessorBlock, diff --git a/xtoskrnl/includes/ar/i686/procsup.hh b/xtoskrnl/includes/ar/i686/procsup.hh index 2f1b93c..eb482ed 100644 --- a/xtoskrnl/includes/ar/i686/procsup.hh +++ b/xtoskrnl/includes/ar/i686/procsup.hh @@ -52,6 +52,7 @@ namespace AR private: STATIC XTAPI VOID IdentifyProcessor(VOID); + STATIC XTAPI VOID IdentifyProcessorFeatures(VOID); STATIC XTAPI VOID InitializeGdt(IN PKPROCESSOR_BLOCK ProcessorBlock); STATIC XTAPI VOID InitializeIdt(IN PKPROCESSOR_BLOCK ProcessorBlock); STATIC XTAPI VOID InitializeProcessorBlock(OUT PKPROCESSOR_BLOCK ProcessorBlock, @@ -79,7 +80,6 @@ namespace AR IN ULONG_PTR Base); STATIC XTAPI VOID SetNonMaskableInterruptTssEntry(IN PKPROCESSOR_BLOCK ProcessorBlock, IN PVOID KernelNmiStack); - }; }