1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: i386 Application Processor (AP) spinup setup 5 * COPYRIGHT: Copyright 2021 Victor Perevertkin <victor.perevertkin@reactos.org> 6 * Copyright 2021-2023 Justin Miller <justin.miller@reactos.org> 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <hal.h> 12 #include <smp.h> 13 14 #define NDEBUG 15 #include <debug.h> 16 17 /* GLOBALS *******************************************************************/ 18 19 extern PPROCESSOR_IDENTITY HalpProcessorIdentity; 20 extern PHYSICAL_ADDRESS HalpLowStubPhysicalAddress; 21 extern PVOID HalpLowStub; 22 23 // The data necessary for a boot (stored inside HalpLowStub) 24 extern PVOID HalpAPEntry16; 25 extern PVOID HalpAPEntryData; 26 extern PVOID HalpAPEntry32; 27 extern PVOID HalpAPEntry16End; 28 extern HALP_APIC_INFO_TABLE HalpApicInfoTable; 29 30 ULONG HalpStartedProcessorCount = 1; 31 32 #ifndef Add2Ptr 33 #define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I))) 34 #endif 35 #ifndef PtrOffset 36 #define PtrOffset(B,O) ((ULONG)((ULONG_PTR)(O) - (ULONG_PTR)(B))) 37 #endif 38 39 typedef struct _AP_ENTRY_DATA 40 { 41 UINT32 Jump32Offset; 42 ULONG Jump32Segment; 43 PVOID SelfPtr; 44 ULONG PageTableRoot; 45 PKPROCESSOR_STATE ProcessorState; 46 KDESCRIPTOR Gdtr; 47 KDESCRIPTOR Idtr; 48 } AP_ENTRY_DATA, *PAP_ENTRY_DATA; 49 50 /* FUNCTIONS *****************************************************************/ 51 52 static 53 ULONG 54 HalpSetupTemporaryMappings( 55 _In_ PKPROCESSOR_STATE ProcessorState) 56 { 57 PMMPDE RootPageTable = Add2Ptr(HalpLowStub, PAGE_SIZE); 58 PMMPDE LowMapPde = Add2Ptr(HalpLowStub, 2 * PAGE_SIZE); 59 PMMPTE LowStubPte = MiAddressToPte(HalpLowStub); 60 PHYSICAL_ADDRESS PhysicalAddress; 61 ULONG StartPti; 62 63 /* Copy current mappings */ 64 RtlCopyMemory(RootPageTable, MiAddressToPde(NULL), PAGE_SIZE); 65 66 /* Set up low PDE */ 67 PhysicalAddress = MmGetPhysicalAddress(LowMapPde); 68 RootPageTable[0].u.Hard.PageFrameNumber = PhysicalAddress.QuadPart >> PAGE_SHIFT; 69 RootPageTable[0].u.Hard.Valid = 1; 70 RootPageTable[0].u.Hard.Write = 1; 71 72 /* Copy low stub PTEs */ 73 StartPti = MiAddressToPteOffset(HalpLowStubPhysicalAddress.QuadPart); 74 ASSERT(StartPti + HALP_LOW_STUB_SIZE_IN_PAGES < 1024); 75 for (ULONG i = 0; i < HALP_LOW_STUB_SIZE_IN_PAGES; i++) 76 { 77 LowMapPde[StartPti + i] = LowStubPte[i]; 78 } 79 80 PhysicalAddress = MmGetPhysicalAddress(RootPageTable); 81 ASSERT(PhysicalAddress.QuadPart < 0x100000000); 82 return (ULONG)PhysicalAddress.QuadPart; 83 } 84 85 BOOLEAN 86 NTAPI 87 HalStartNextProcessor( 88 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock, 89 _In_ PKPROCESSOR_STATE ProcessorState) 90 { 91 if (HalpStartedProcessorCount == HalpApicInfoTable.ProcessorCount) 92 return FALSE; 93 94 // Initalize the temporary page table 95 // TODO: clean it up after an AP boots successfully 96 ULONG initialCr3 = HalpSetupTemporaryMappings(ProcessorState); 97 if (!initialCr3) 98 return FALSE; 99 100 // Put the bootstrap code into low memory 101 RtlCopyMemory(HalpLowStub, &HalpAPEntry16, (ULONG_PTR)&HalpAPEntry16End - (ULONG_PTR)&HalpAPEntry16); 102 103 // Get a pointer to apEntryData 104 PAP_ENTRY_DATA apEntryData = (PVOID)((ULONG_PTR)HalpLowStub + ((ULONG_PTR)&HalpAPEntryData - (ULONG_PTR)&HalpAPEntry16)); 105 106 *apEntryData = (AP_ENTRY_DATA){ 107 .Jump32Offset = (ULONG)&HalpAPEntry32, 108 .Jump32Segment = (ULONG)ProcessorState->ContextFrame.SegCs, 109 .SelfPtr = (PVOID)apEntryData, 110 .PageTableRoot = initialCr3, 111 .ProcessorState = ProcessorState, 112 .Gdtr = ProcessorState->SpecialRegisters.Gdtr, 113 .Idtr = ProcessorState->SpecialRegisters.Idtr, 114 }; 115 116 ApicStartApplicationProcessor(HalpStartedProcessorCount, HalpLowStubPhysicalAddress); 117 118 HalpStartedProcessorCount++; 119 120 return TRUE; 121 } 122