1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
|
title "MP primitives for the Corollary Cbus machines"
;++
;
;Copyright (c) 1991 Microsoft Corporation
;
;Module Name:
;
; cbusboot.asm
;
;Abstract:
;
; Corollary Start Next Processor assembly code
;
; This module along implements the code to start
; off the additional processors in the Corollary machines.
;
;
;Author:
;
; Ken Reneris (kenr) 12-Jan-1992
;
;Environment:
; Kernel mode.
;
;
;Revision History:
;
; Landy Wang (landy@corollary.com) 20-Oct-1992
;
; - slight modification to boot Corollary-architecture processors
; to allow booting multiple hardware platforms
;
; - preserve interrupt state in eflags whilst booting other processors
;
;--
.386p
.xlist
include hal386.inc
include callconv.inc ; calling convention macros
include i386\kimacro.inc
include cbus.inc
.list
WarmResetVector equ 467h ; warm reset vector in ROM data segment
;
; Internal defines and structures
;
PxParamBlock struc
SPx_flag dd ?
SPx_TiledCR3 dd ?
SPx_P0EBP dd ?
SPx_PB db ProcessorStateLength dup (?)
PxParamBlock ends
_TEXT SEGMENT PARA PUBLIC 'CODE' ; Start 32 bit code
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
;++
;
; BOOLEAN
; HalStartNextProcessor (
; IN PLOADER_BLOCK pLoaderBlock,
; IN PKPROCESSOR_STATE pProcessorState
; )
;
; Routine Description:
;
; This routine is called by the kernel durning kernel initialization
; to obtain more processors. It is called until no more processors
; are available.
;
; If another processor exists this function is to initialize it to
; the passed in processorstate structure, and return TRUE.
;
; If another processor does not exists, then a FALSE is returned.
;
; Also note that the loader block has been setup for the next processor.
; The new processor logical thread number can be obtained from it, if
; required.
;
; Arguments:
; pLoaderBlock, - Loader block which has been intialized for the
; next processor.
;
; pProcessorState - The processor state which is to be loaded into
; the next processor.
;
;
; Return Value:
;
; TRUE - ProcessorNumber was dispatched.
; FALSE - A processor was not dispatched. no other processors exists.
;
;--
pLoaderBlock equ dword ptr [ebp+8] ; zero based
pProcessorState equ dword ptr [ebp+12]
;
; Local variables
;
PxFrame equ [ebp - size PxParamBlock]
cPublicProc _HalStartNextProcessor ,2
push ebp ; save ebp
mov ebp, esp ;
sub esp, size PxParamBlock ; Make room for local vars
push esi
push edi
push ebx
xor eax, eax
mov PxFrame.SPx_flag, eax
cmp _MpCount, eax
jbe snp_exit ; exit FALSE
mov esi, OFFSET FLAT:StartPx_RMStub
mov ecx, StartPx_RMStub_Len
mov edi, _MpLowStub ; Copy RMStub to low memory
add edi, size PxParamBlock
rep movsb
lea edi, PxFrame.SPx_PB
mov esi, pProcessorState
mov ecx, ProcessorStateLength ; Copy processorstate
rep movsb ; to PxFrame
stdCall _HalpBuildTiledCR3, <pProcessorState>
mov PxFrame.SPx_TiledCR3, eax
mov PxFrame.SPx_P0EBP, ebp
mov eax, pLoaderBlock ; lookup processor # we are
mov eax, [eax].LpbPrcb ; starting
movzx eax, byte ptr [eax].PbNumber
mov ecx, size PxParamBlock ; copy param block
lea esi, PxFrame ; to low memory stub
mov edi, _MpLowStub
mov eax, edi
rep movsb
add eax, size PxParamBlock
mov ebx, OFFSET FLAT:StartPx_RMStub
sub eax, ebx ; (eax) = adjusted pointer
mov bx, word ptr [PxFrame.SPx_PB.PsContextFrame.CsSegCs]
mov [eax.SPrxFlatCS], bx ; patch realmode stub with
mov [eax.SPrxPMStub], offset _StartPx_PMStub ; valid long jump
mov ebx, _MppIDT
add ebx, WarmResetVector
pushfd ; must preserve flags
cli
push dword ptr [ebx] ; Save current vector
mov edx, _MpLowStubPhysicalAddress
shl edx, 12 ; seg:0
add edx, size PxParamBlock
mov dword ptr [ebx], edx ; start Px here
mov ecx, pLoaderBlock ; lookup processor # we are
mov ecx, [ecx].LpbPrcb ; starting
movzx ecx, byte ptr [ecx].PbNumber
push edx ; start address (seg:off)
push ecx ; processor number
mov eax, _CbusBackend ; use hardware handler
call HalBootCPU[ eax ] ; to boot specified processor
; callee pops the args
align 4
Hsnp002:
@@:
cmp PxFrame.SPx_flag, 0 ; wait for Px to get its
jz @b ; info
pop dword ptr [ebx] ; restore WarmResetVector
popfd ; must restore flags
stdCall _HalpFreeTiledCR3 ; free memory used for tiled
; CR3
dec _MpCount ; one less
mov eax, 1 ; return TRUE
snp_exit:
pop ebx
pop edi
pop esi
mov esp, ebp
pop ebp
stdRET _HalStartNextProcessor
stdENDP _HalStartNextProcessor
_TEXT ends ; end 32 bit code
_TEXT16 SEGMENT DWORD PUBLIC USE16 'CODE' ; start 16 bit code
;++
;
; VOID
; StartPx_RMStub
;
; Routine Description:
;
; When a new processor is started, it starts in real-mode and is
; sent to a copy of this function which has been copied into low memory.
; (below 1MB and accessible from real-mode).
;
; Once CR0 has been set, this function jmp's to a StartPx_PMStub
;
; Arguments:
; none
;
; Return Value:
; does not return, jumps to StartPx_PMStub
;
;--
cPublicProc StartPx_RMStub ,0
cli
db 066h ; load the GDT
lgdt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrGdtr]
db 066h ; load the IDT
lidt fword ptr cs:[SPx_PB.PsSpecialRegisters.SrIdtr]
mov eax, cs:[SPx_TiledCR3]
mov cr3, eax
mov ebp, dword ptr cs:[SPx_P0EBP]
mov ecx, dword ptr cs:[SPx_PB.PsContextFrame.CsSegDs]
mov ebx, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr3]
mov eax, dword ptr cs:[SPx_PB.PsSpecialRegisters.SrCr0]
mov cr0, eax ; into prot mode
db 066h
db 0eah ; reload cs:eip
SPrxPMStub dd 0
SPrxFlatCS dw 0
StartPx_RMStub_Len equ $ - StartPx_RMStub
stdENDP StartPx_RMStub
_TEXT16 ends ; End 16 bit code
_TEXT SEGMENT ; Start 32 bit code
;++
;
; VOID
; StartPx_PMStub
;
; Routine Description:
;
; This function completes the processor's state loading, and signals
; the requesting processor that the state has been loaded.
;
; Arguments:
; ebx - requested CR3 for this processors_state
; cx - requested ds for this processors_state
; ebp - EBP of P0
;
; Return Value:
; does not return - completes the loading of the processors_state
;
;--
align 16 ; to make sure we don't cross a page boundry
; before reloading CR3
cPublicProc _StartPx_PMStub ,0
; process is now in the load image copy of this function.
; (ie, it's not the low memory copy)
mov cr3, ebx ; get real CR3
mov ds, cx ; set real ds
lea esi, PxFrame.SPx_PB.PsSpecialRegisters
lldt word ptr ds:[esi].SrLdtr ; load ldtr
ltr word ptr ds:[esi].SrTr ; load tss
lea edi, PxFrame.SPx_PB.PsContextFrame
mov es, word ptr ds:[edi].CsSegEs ; Set other selectors
mov fs, word ptr ds:[edi].CsSegFs
mov gs, word ptr ds:[edi].CsSegGs
mov ss, word ptr ds:[edi].CsSegSs
add esi, SrKernelDr0
.errnz (SrKernelDr1 - SrKernelDr0 - 1 * 4)
.errnz (SrKernelDr2 - SrKernelDr0 - 2 * 4)
.errnz (SrKernelDr3 - SrKernelDr0 - 3 * 4)
.errnz (SrKernelDr6 - SrKernelDr0 - 4 * 4)
.errnz (SrKernelDr7 - SrKernelDr0 - 5 * 4)
lodsd
mov dr0, eax ; load dr0-dr7
lodsd
mov dr1, eax
lodsd
mov dr2, eax
lodsd
mov dr3, eax
lodsd
mov dr6, eax
lodsd
mov dr7, eax
mov esp, dword ptr ds:[edi].CsEsp
mov esi, dword ptr ds:[edi].CsEsi
mov ecx, dword ptr ds:[edi].CsEcx
push dword ptr ds:[edi].CsEflags
popfd ; load eflags
push dword ptr ds:[edi].CsEip ; make a copy of remaining
push dword ptr ds:[edi].CsEax ; registers which need
push dword ptr ds:[edi].CsEbx ; loaded
push dword ptr ds:[edi].CsEdx
push dword ptr ds:[edi].CsEdi
push dword ptr ds:[edi].CsEbp
inc [PxFrame.SPx_flag] ; Signal p0 that we are
; done with it's data
; Set remaining registers
pop ebp
pop edi
pop edx
pop ebx
pop eax
stdRET _StartPx_PMStub ; Set eip
stdENDP _StartPx_PMStub
_TEXT ends ; end 32 bit code
end
|