xref: /reactos/hal/halx86/smp/i386/spinup.c (revision b36d9bd9)
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