From ae18468badc9e899c23a7a3bef92ab18336d9a2d Mon Sep 17 00:00:00 2001 From: Aiken Harris Date: Wed, 13 May 2026 21:48:42 +0200 Subject: [PATCH] Add AP startup assembly trampoline for AMD64 --- sdk/xtadk/amd64/ke.cc | 9 +++ sdk/xtdk/amd64/ketypes.h | 18 +++++- xtoskrnl/ar/amd64/archsup.S | 119 +++++++++++++++++++++++++++++++++++- 3 files changed, 142 insertions(+), 4 deletions(-) diff --git a/sdk/xtadk/amd64/ke.cc b/sdk/xtadk/amd64/ke.cc index 56902fb..e28ab7b 100644 --- a/sdk/xtadk/amd64/ke.cc +++ b/sdk/xtadk/amd64/ke.cc @@ -80,4 +80,13 @@ GenerateAssemblyDefinitions(VOID) /* Generate KTRAP_FRAME size and REGISTERS_SIZE */ ADK_SIZE(KTRAP_FRAME); ADK_SIZE_FROM(REGISTERS_SIZE, KTRAP_FRAME, Rax); + + /* Generate PROCESSOR_START_BLOCK offsets */ + ADK_OFFSET(PROCESSOR_START_BLOCK, Cr3); + ADK_OFFSET(PROCESSOR_START_BLOCK, Cr4); + ADK_OFFSET(PROCESSOR_START_BLOCK, EntryPoint); + ADK_OFFSET(PROCESSOR_START_BLOCK, ProcessorBlock); + ADK_OFFSET(PROCESSOR_START_BLOCK, ProcessorNumber); + ADK_OFFSET(PROCESSOR_START_BLOCK, Stack); + ADK_OFFSET(PROCESSOR_START_BLOCK, Started); } diff --git a/sdk/xtdk/amd64/ketypes.h b/sdk/xtdk/amd64/ketypes.h index 5790d02..5c972a1 100644 --- a/sdk/xtdk/amd64/ketypes.h +++ b/sdk/xtdk/amd64/ketypes.h @@ -118,8 +118,8 @@ #define KERNEL_STACK_GUARD_PAGES 1 /* Processor structures size */ -#define KPROCESSOR_STRUCTURES_SIZE ((2 * KERNEL_STACK_SIZE) + (GDT_ENTRIES * sizeof(KGDTENTRY)) + sizeof(KTSS) + \ - sizeof(KPROCESSOR_BLOCK) + MM_PAGE_SIZE) +#define KPROCESSOR_STRUCTURES_SIZE ((KERNEL_STACKS * KERNEL_STACK_SIZE) + (GDT_ENTRIES * sizeof(KGDTENTRY)) + \ + sizeof(KTSS) + sizeof(KPROCESSOR_BLOCK) + MM_PAGE_SIZE) /* Kernel frames */ #define KEXCEPTION_FRAME_SIZE sizeof(KEXCEPTION_FRAME) @@ -470,11 +470,23 @@ typedef struct _KSPECIAL_REGISTERS ULONG64 MsrSyscallMask; } KSPECIAL_REGISTERS, *PKSPECIAL_REGISTERS; +/* Processor start block structure definition */ +typedef struct _PROCESSOR_START_BLOCK +{ + ULONG_PTR Cr3; + ULONG_PTR Cr4; + PVOID EntryPoint; + PVOID ProcessorBlock; + ULONG ProcessorNumber; + PVOID Stack; + BOOLEAN Started; +} PROCESSOR_START_BLOCK, *PPROCESSOR_START_BLOCK; + /* Processor state frame structure definition */ typedef struct _KPROCESSOR_STATE { - KSPECIAL_REGISTERS SpecialRegisters; CONTEXT ContextFrame; + KSPECIAL_REGISTERS SpecialRegisters; } KPROCESSOR_STATE, *PKPROCESSOR_STATE; /* Processor Control Block (PRCB) structure definition */ diff --git a/xtoskrnl/ar/amd64/archsup.S b/xtoskrnl/ar/amd64/archsup.S index 29c1d05..9bfd3f1 100644 --- a/xtoskrnl/ar/amd64/archsup.S +++ b/xtoskrnl/ar/amd64/archsup.S @@ -359,7 +359,7 @@ ArHandleSpuriousInterrupt: iretq /** - * Starts an application processor (AP). This is just a stub. + * Starts an application processor (AP). * * @return This routine does not return any value. * @@ -367,6 +367,123 @@ ArHandleSpuriousInterrupt: */ .global ArStartApplicationProcessor ArStartApplicationProcessor: + /* Enter 16-bit real mode */ + .code16 + + /* Disable interrupts and clear direction flag */ + cli + cld + + /* Establish a flat addressing baseline */ + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + + /* Calculate absolute physical base address */ + xorl %ebx, %ebx + movw %cs, %bx + shll $4, %ebx + + /* Set up a temporary stack for the AP initialization */ + movl %ebx, %esp + addl $0x1000, %esp + + /* Load the temporary Global Descriptor Table */ + leal (ApTemporaryGdtDesc - ArStartApplicationProcessor)(%ebx), %eax + movl %eax, (ApTemporaryGdtBase - ArStartApplicationProcessor) + lgdtl (ApTemporaryGdtSize - ArStartApplicationProcessor) + + /* Enable Protected Mode */ + movl %cr0, %eax + orl $0x01, %eax + movl %eax, %cr0 + + /* Far return to enter 32-bit protected mode */ + leal (ApEnterProtectedMode - ArStartApplicationProcessor)(%ebx), %eax + pushl $0x08 + pushl %eax + lretl + +ApEnterProtectedMode: + /* Enter 32-bit protected mode */ + .code32 + + /* Setup all data segment registers */ + movw $0x18, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + xorw %ax, %ax + movw %ax, %fs + movw %ax, %gs + + /* Locate PROCESSOR_START_BLOCK structure */ + leal (ArStartApplicationProcessorEnd - ArStartApplicationProcessor)(%ebx), %edi + + /* Load CR4 from BSP, but mask PCIDE and PGE */ + movl PROCESSOR_START_BLOCK_Cr4(%edi), %eax + andl $~(CR4_PGE | CR4_PCIDE), %eax + movl %eax, %cr4 + + /* Load the Kernel Page Directory Base from BSP */ + movl PROCESSOR_START_BLOCK_Cr3(%edi), %eax + movl %eax, %cr3 + + /* Enable Long Mode and No-Execute */ + movl $0xC0000080, %ecx + rdmsr + orl $0x00000900, %eax + wrmsr + + /* Enable Paging */ + movl %cr0, %eax + orl $0x80000000, %eax + movl %eax, %cr0 + + /* Far return to enter 64-bit long mode */ + leal (ApEnterLongMode - ArStartApplicationProcessor)(%ebx), %eax + pushl $0x10 + pushl %eax + lretl + +ApEnterLongMode: + /* Enter 64-bit long mode */ + .code64 + + /* Clear all segment registers */ + xorw %ax, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw %ax, %fs + movw %ax, %gs + + /* Zero-extend EDI into RDI to ensure safe 64-bit pointer usage */ + movl %edi, %edi + + /* Load dedicated Stack for AP */ + movq PROCESSOR_START_BLOCK_Stack(%rdi), %rsp + + /* Save the pointer to PROCESSOR_START_BLOCK */ + movq %rdi, %rcx + pushq %rdi + + /* Call the EntryPoint routine */ + movq PROCESSOR_START_BLOCK_EntryPoint(%rdi), %rax + call *%rax + + /* Fire the breakpoint and halt if the entry point returns */ +.ApNoReturnPoint: + int $0x03 + hlt + jmp .ApNoReturnPoint + +/* Data section for temporary GDT */ +.align 8 +ApTemporaryGdtSize: .short ArStartApplicationProcessorEnd - ApTemporaryGdtDesc - 1 +ApTemporaryGdtBase: .quad 0x0000000000000000 +ApTemporaryGdtDesc: .quad 0x0000000000000000, 0x00CF9A000000FFFF, 0x00AF9A000000FFFF, 0x00CF92000000FFFF .global ArStartApplicationProcessorEnd ArStartApplicationProcessorEnd: