summaryrefslogblamecommitdiffstats
path: root/private/ntos/nthals/halncr/i386/ncrstart.asm
blob: e36fb91e925f982380173b56d2091582de3686e8 (plain) (tree)
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
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987


























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































                                                                                                                                 
        title "Multiprocessor Startup"
;++
;
;Copyright (c) 1992  NCR Corporation
;
;Module Name:
;
;    ncrstart.asm
;
;Abstract:
;
;    Provides the HAL support for starting processors.
;
;Author:
;
;    Richard Barton (o-richb) 24-Jan-1992
;
;Revision History:
;
;--
.386p
        .xlist
include hal386.inc
include callconv.inc                    ; calling convention macros
include i386\kimacro.inc
include i386\ix8259.inc
include i386\ncr.inc


        extrn   _DbgPrint:PROC
        EXTRNP  _HalpBuildTiledCR3,1
        EXTRNP  _HalpFreeTiledCR3,0
        EXTRNP  _HalEnableSystemInterrupt,3
        EXTRNP  _NCRFindIpiAddress,1
        EXTRNP  _NCRClearQicIpi,1
        EXTRNP  _HalQicStartupIpi,1
		EXTRNP  _NCRTranslateCMOSMask,1
		EXTRNP  _NCRTranslateToCMOSMask,1
		EXTRNP  _NCRAdjustDynamicClaims,0
if DBG
		EXTRNP  _NCRConsoleDebug,2
endif
        extrn   _NCRProcessorsToBringup:DWORD
        extrn   _NCRExistingProcessorMask:DWORD
        extrn   _NCRExistingDyadicProcessorMask:DWORD
        extrn   _NCRExistingQuadProcessorMask:DWORD
        extrn   _NCRExtendedProcessorMask:DWORD
        extrn   _NCRExtendedProcessor0Mask:DWORD
        extrn   _NCRExtendedProcessor1Mask:DWORD
        extrn   _NCRLogicalDyadicProcessorMask:DWORD
        extrn   _NCRLogicalQuadProcessorMask:DWORD
        extrn   _NCRActiveProcessorMask:DWORD
        extrn   _NCRActiveProcessorCount:DWORD
        extrn   _NCRMaxProcessorCount:DWORD
		extrn   _NCRLogicalNumberToPhysicalMask:DWORD
        extrn   _NCRSlotExtended0ToVIC:BYTE
        extrn   _NCRSlotExtended1ToVIC:BYTE
        extrn   _NonbootStartupVirtualPtr:DWORD
        extrn   _NonbootStartupPhysicalPtr:DWORD
        extrn   _PageZeroVirtualPtr:DWORD
        extrn   _HalpDefaultInterruptAffinity:DWORD
        extrn   _HalpActiveProcessors:DWORD
        extrn   _NCRProcessorIDR:DWORD
		extern  _DefaultNeverClaimIRQs:DWORD
		extern  _NCRNeverClaimIRQs:DWORD

        EXTRNP  _HalpInitializePICs,0


PxParamBlock    struc
        SPx_Mask        dd      ?
        SPx_TiledCR3    dd      ?
        SPx_P0EBP       dd      ?
        SPx_PB          db      processorstatelength dup (?)
PxParamBlock    ends

        page ,132
        subttl  "Initialize boot processor"

_TEXT   SEGMENT PARA PUBLIC 'CODE'
        ASSUME  CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING

;++
;
; VOID
; HalInitializeProcessor(
;       ULONG   Number
;       );
;
;Routine Description:
;
;    Initialize hal pcr values for current processor (if any)
;    (called shortly after processor reaches kernel, before
;    HalInitSystem if P0)
;
;    IPI's and KeRaise/LowerIrq's must be available once this function
;    returns.  (IPI's are only used once two or more processors are
;    available)
;
;    This routine makes some VIC accesses assuming that it's running on
;    an NCR box.  The real check won't happen until HalInitMP().
;
;Arguments:
;
;    Number - Logical processor number of calling processor
;
;Return Value:
;
;    None.
;
;--

cPublicProc _HalInitializeProcessor ,1

;
; Initialize IDR in PCR to allow irq 2 only.
;

        mov     dword ptr PCR[PcIDR],0fffffffbh
        mov     dword ptr PCR[PcStallScaleFactor], INITIAL_STALL_COUNT
		mov		dword ptr PCR[PcHal.PcrMyClaimedIRQs], 0
		mov		dword ptr PCR[PcHal.PcrMyClaimedIRQsCount],0


;
;  all processors execute this first section
;
;  remember this processors logical number
;

        mov     ecx, 4[esp]
        mov     PCR[PcHal.PcrMyLogicalNumber], ecx

;
; Set IDR table to same value as PcIDR
;
		mov		_NCRProcessorIDR[ecx*4],0fffffffbh


;RMU
;if DBG
;		push	ebx
;		push	ecx
;		push	edx
;		mov		eax,1
;        stdCall   _NCRConsoleDebug, <eax,ecx>
;		pop		edx
;		pop		ecx
;		pop		ebx
;endif
;RMU


        mov     eax, 1
        shl     eax, cl
        lock or _HalpActiveProcessors, eax

if 0
    ; begin - spinlock test code - kenr
        push    eax
        push    edx

        mov     eax, 1
        shl     eax, cl         ; (eax) = pmask
        shl     eax, 16         ; mask into high word of dword

        mov     fs:PcHal.PcrCheckForBit, eax    ; (pmask<<16)

        or      eax, 1          ; set  low byte to 1
        mov     fs:PcHal.PcrSpinAcquireBits, eax    ; (pmask<<16) | 1

        not     eax
        and     eax, 0ffff0000h
        mov     fs:PcHal.PcrSpinReleaseMask, eax    ; ~(pmask<<16)


        mov     eax, ecx
        inc     eax             ; handoff id
        shl     eax, 8
        or      eax, 1          ; (handoff << 8) | 1
        mov     fs:PcHal.PcrSpinId, eax


        pop     edx
        pop     eax
    ; end - spinlock test code
endif


;
;  remember this processors physical mask
;
        WHO_AM_I
		jb	IAmQuad

;
; Processor init code for Dyadic
;

        lock or _NCRActiveProcessorMask, eax
        lock inc _NCRActiveProcessorCount

        mov     edx, CPU_DYADIC
        mov     PCR[PcHal.PcrMyProcessorFlags],edx
;
;  setup translation databases:
;					   
        mov     edx, 1
        shl     edx, cl         ; edx contains logical mask
        mov     PCR[PcHal.PcrMyLogicalMask], edx
		lock or _NCRLogicalDyadicProcessorMask, edx
        lock or _HalpDefaultInterruptAffinity, edx
;
;   Get the real hardware VIC mask so we can send CPIs
;
        mov     dx, VIC_BASE_ADDRESS+vic_ProcessorWhoAmIReg
        xor     eax,eax
        in      al,dx
		mov     _NCRLogicalNumberToPhysicalMask[ecx*4], eax

;
; make sure all processors can take interrupts (have this processor claim none)
;
        VIC_WRITE ClaimRegLsb, 0
        VIC_WRITE ClaimRegMsb, 0

        or      ecx, ecx
        jz      InitBoot
;
;  nonboot processor only stuff
;
        stdCall   _HalpInitializePICs

;
;  no need to send EOI for startup CPI since just initialized PICs above
;

;
;  make sure each processor can get IPI
;
        stdCall   _HalEnableSystemInterrupt, <NCR_CPI_VECTOR_BASE+NCR_IPI_LEVEL_CPI,IPI_LEVEL,0>

        stdRET    _HalInitializeProcessor
;
;  boot processor only stuff
;
        align   dword
InitBoot:
;
;  setup the cross-processor vector base
;
        mov     eax, NCR_CPI_VECTOR_BASE
        VIC_WRITE CpiVectorBaseReg
;
;  temporary fix for VIC errata - true spurious primary MC interrupts (where
;  HW removes the request during INTA cycle) can result in a secondary MC based
;  vector being supplied by the VIC (with the ISR bit actually set, but no
;  real interrupt).  Since currently no interrupts are routed through the
;  secondary MC vector space, will simply set the secondary MC vector space
;  equal to the primary vector space.
;
        mov     eax, NCR_SECONDARY_VECTOR_BASE
        VIC_WRITE ExtMasterVectorBaseReg
        mov     eax, NCR_SECONDARY_VECTOR_BASE+8
        VIC_WRITE ExtSlaveVectorBaseReg

        stdRET    _HalInitializeProcessor
;
; Processor init code for Quad processor
;

IAmQuad:

;
; save logical processor number to hardware mask
;

        mov     _NCRLogicalNumberToPhysicalMask[ecx*4], eax

;
; now lets see if we are extended or not
;

        mov     edx,eax         ; save process mask
        PROCESSOR_SLOT          ; get the process slot for this CPU
        shl     eax,2h          ; calculate shift to isolate mask to one board
        push    ecx             ; save ecx (contains logical processor number)
        mov     ecx,eax
        mov     eax,edx         ; now get processor mask
        shr     eax,cl          ; now isolate processor on this board
        mov     ecx,eax         ; save processor by board mask

        push    edx             ; save edx with processor mask
        QIC_READ ExtendedProcessorSelect    ; get the extended processor mask 
        pop     edx

        test    eax,ecx         ; test for extended processor 0
        jnz short ExtendedProcessor0

        shr    eax,4h           ; isolate extended processor 1 mask

        test    eax,ecx         ; test for extended processor 1
        jnz short ExtendedProcessor
        pop     ecx
        mov     eax,edx
        mov     edx, CPU_QUAD

        jmp short NotExtended;

ExtendedProcessor0:

;
; For Extended Processor 0 lets setup all other processors on the Quad Board
;
        xor     ecx,ecx
        push    edx                 ; save who am I mask
		align 	dword
ExtendedLoop:

        mov     al,cl
        or      al,8
        QIC_WRITE ProcessorId

        mov     al,0ffh
        QIC_WRITE QicMask0

        mov     al,QIC_IRQ_ENABLE_MASK
        QIC_WRITE QicMask1

        xor     al,al
        QIC_WRITE ProcessorId

        inc     ecx
        cmp     ecx,4
        jne short ExtendedLoop

;
; Qic setup
;

;
; Disable propagation of SBE and SINT to non-extened processors
;
        QIC_READ  Configuration
        or  al,7
        QIC_WRITE Configuration

        mov al, NCR_CPI_VECTOR_BASE
        QIC_WRITE VicCpiVectorBaseReg

        mov al, NCR_QIC_CPI_VECTOR_BASE
        QIC_WRITE QuadCpiVectorBaseReg

        mov     al,0ffh
        QIC_WRITE Clear1Reg

		mov		al,NCR_QIC_SPURIOUS_VECTOR
		QIC_WRITE SpuriousVectorReg

        pop     edx                 ; restore the who am I mask

ExtendedProcessor:
        pop     ecx
        mov     eax,edx
        mov     edx, CPU_QUAD
        or      edx, CPU_EXTENDED
        push    eax
        mov     eax, 1
        shl     eax, cl
        lock or _HalpDefaultInterruptAffinity, eax
        pop     eax
NotExtended:
        mov     PCR[PcHal.PcrMyProcessorFlags],edx
;
;
        lock or _NCRActiveProcessorMask, eax
        lock inc        _NCRActiveProcessorCount

        mov     edx, 1
        shl     edx, cl         ; edx contains logical mask
		lock or _NCRLogicalQuadProcessorMask, edx
        mov     PCR[PcHal.PcrMyLogicalMask], edx


;
; make sure all processors can take interrupts (have this processor claim none)
;
        VIC_WRITE ClaimRegLsb, 0
        VIC_WRITE ClaimRegMsb, 0

        or      ecx, ecx
        jz      QuadInitBoot

        stdCall _NCRFindIpiAddress, <ecx>       ; lookup IPI address so we can send and clear IPI's
        stdCall _NCRClearQicIpi, <2>            ; clear the startup IPI

;
;  nonboot processor only stuff
;
        mov     eax, PCR[PcHal.PcrMyProcessorFlags]
        test    eax,CPU_EXTENDED
        jz      short NoPic

        stdCall   _HalpInitializePICs

NoPic:
        stdRET    _HalInitializeProcessor
;
;  boot processor only stuff
;
        align   dword
QuadInitBoot:
;
;  setup the cross-processor vector base
;
        mov     eax, NCR_CPI_VECTOR_BASE
        VIC_WRITE CpiVectorBaseReg

;
;  temporary fix for VIC errata - true spurious primary MC interrupts (where
;  HW removes the request during INTA cycle) can result in a secondary MC based
;  vector being supplied by the VIC (with the ISR bit actually set, but no
;  real interrupt).  Since currently no interrupts are routed through the
;  secondary MC vector space, will simply set the secondary MC vector space
;  equal to the primary vector space.
;

        mov     eax, NCR_SECONDARY_VECTOR_BASE
        VIC_WRITE ExtMasterVectorBaseReg
        mov     eax, NCR_SECONDARY_VECTOR_BASE+8
        VIC_WRITE ExtSlaveVectorBaseReg

;
; Qic setup
;

        mov al, NCR_CPI_VECTOR_BASE
        QIC_WRITE VicCpiVectorBaseReg

        mov al, NCR_QIC_CPI_VECTOR_BASE
        QIC_WRITE QuadCpiVectorBaseReg

        mov     al,0ffh
        QIC_WRITE Clear1Reg

        stdRET    _HalInitializeProcessor
stdENDP _HalInitializeProcessor



        page ,132
        subttl  "Start non-boot processor"


;++
;
; 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.
;
;
;    we need to consult with firmware tables to determine which processors
;    are okay to start.  note that we can not return false until there are
;    no processors left.  so we stay here until we either start another
;    processor, there are no processors left to start, or all our attempts
;    to start another processor fail.
;
; 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
;
; note that we can screen processors two ways:  we can limit the number
; of processors to start or we can choose which physical processors we
; will start.  this is mainly for debugging and benchmarking purposes.
;
; how many processors are we going to allow
;
        mov     ecx, _NCRActiveProcessorCount
        cmp     ecx, _NCRMaxProcessorCount
        jae     Done
;
; which processors are left
;
        mov     eax, _NCRExistingProcessorMask
        xor     eax, _NCRActiveProcessorMask
;
; which processors are we going to allow
;
        and     eax, _NCRProcessorsToBringup
        jz      Done

        push    ebp
        mov     ebp, esp

        sub     esp, size PxParamBlock

        push    esi
        push    edi
        push    ebx

        push    eax                             ; processors to choose from

        mov     esi, OFFSET FLAT:StartPx_RMStubE
        mov     ecx, esi
        mov     esi, OFFSET FLAT:StartPx_RMStub
        sub     ecx, esi
        mov     edi, _NonbootStartupVirtualPtr
        add     edi, size PxParamBlock
        rep     movsb                           ; Copy RMStub to low memory

        lea     edi, PxFrame.SPx_PB
        mov     esi, pProcessorState
        mov     ecx, processorstatelength       ; Copy processorstate
        rep     movsb                           ; to PxFrame

        stdCall   _HalpBuildTiledCR3, <pProcessorState>

        mov     PxFrame.SPx_Mask, 0
        mov     PxFrame.SPx_TiledCR3, eax
        mov     PxFrame.SPx_P0EBP, ebp

        mov     ecx, size PxParamBlock          ; copy param block
        lea     esi, PxFrame                    ; to low memory stub
        mov     edi, _NonbootStartupVirtualPtr
        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

;
; determine which one processor we are going to start.  think i'll try
; alternating buses.
;

	    mov     eax, dword ptr [esp]                     ; retrieve processors awaiting
        bsf     ecx, eax

;
; check to see if we are starting a dyadic or quad processor
;
		mov		eax,1
		shl		eax,cl

		test	eax,_NCRExistingQuadProcessorMask
		jnz		StartQuadProcessor

;
; Startup code for a Dyadic processor
;
		mov	ecx, eax							; now we only care about the startup mask
;
;  fix the startee processors vector to allow it to receive the cpi
;
        mov     ebx, _PageZeroVirtualPtr
        add     ebx, NCR_STARTUP_VECTOR_VIC

        cli
        push    dword ptr [ebx]                 ; Save current vector

        mov     eax, _NonbootStartupPhysicalPtr
        shl     eax, 12                         ; seg:0
        add     eax, size PxParamBlock
        mov     dword ptr [ebx], eax            ; start Px here
;
;  enable the cpi for the startee processor (although unnecessary for 3360 -
;  it's left enabled by BIOS)
;
		push	ebx
        push    ecx
        stdCall _NCRTranslateToCMOSMask, <ecx>
        bsf     ecx, eax
        mov     al, cl
        pop     ecx
		pop		ebx
        or      al, ProcessorIdSelect
        VIC_WRITE ProcessorIdReg                ; assume startee's id
        mov     edx, ecx                          ; save processor number
        mov     eax, 1
        mov     ecx, NCR_STARTUP_CPI
        shl     eax, cl
        not     al
        mov     ecx, edx                          ; restore processor number
        out     PIC1_PORT1, al                  ; clear cpi's irq
        VIC_WRITE ProcessorIdReg, 0             ; restore own id

		mov		eax,ecx							; get the startee mask
;
;  interrupt the startee
;
		push	ebx
		push	ecx
		stdCall _NCRTranslateToCMOSMask, <eax>
        VIC_WRITE CpiLevel2Reg
		pop		ecx
		pop		ebx

		mov		eax,ecx							; get the startee mask

		jmp		StarteeWakeNow
;
; Startup code for a Quad Processor
;
		
StartQuadProcessor:

        test    eax,_NCRExtendedProcessor0Mask
        jnz short StarteeExtended

        mov     ebx, _PageZeroVirtualPtr
        add     ebx, NCR_STARTUP_VECTOR_QIC

        jmp short SkipVicSetup
StarteeExtended:
;
;  fix the startee processors vector to allow it to receive the cpi
;
        mov     ebx, _PageZeroVirtualPtr
        add     ebx, NCR_STARTUP_VECTOR_VIC

SkipVicSetup:

        cli
        push    dword ptr [ebx]                 ; Save current vector

        mov     eax, _NonbootStartupPhysicalPtr
        shl     eax, 12                         ; seg:0
        add     eax, size PxParamBlock
        mov     dword ptr [ebx], eax            ; start Px here

;
;  generate startee processors mask
;
        mov     eax, 1
        shl     eax, cl                         ; mask of processor to start

        test    eax,_NCRExtendedProcessor0Mask
        jz short StarteeNotExtended

;
; We are starting an Extended processor, we do this my using the VIC and not the QIC
;

;
; This is extended processor 0
;

        PROCESSOR_SLOT
        movzx   eax, byte ptr _NCRSlotExtended0ToVIC[eax]

;
;  enable the cpi for the startee processor (although unnecessary for 3360 -
;  it's left enabled by BIOS)
;
        push    eax                             ; save the vic processor number

        or      al, ProcessorIdSelect
        VIC_WRITE ProcessorIdReg                ; assume startee's id
        mov     dl, cl                          ; save processor number
        mov     eax, 1
        mov     ecx, NCR_STARTUP_CPI
        shl     eax, cl
        not     al
        mov     cl, dl                          ; restore processor number
        out     PIC1_PORT1, al                  ; clear cpi's irq
        VIC_WRITE ProcessorIdReg, 0             ; restore own id

        pop     eax
        push    ecx
        mov     ecx, eax
;
;  generate startee processors mask
;
        mov     eax, 1
        shl     eax, cl                         ; mask of VIC processor to start

;  interrupt the startee

        VIC_WRITE CpiLevel2Reg
        pop     ecx

        mov     eax, 1
        shl     eax, cl                         ; mask of processor started

        jmp short StarteeWakeNow

StarteeNotExtended:

        push    ecx
        stdCall _HalQicStartupIpi, <ecx>
        pop     ecx

        mov     eax, 1
        shl     eax, cl                         ; mask of processor started

StarteeWakeNow:

;RMU
;if DBG
;		push	eax
;		push	ebx
;		push	ecx
;		push	edx
;		mov		edx,2
;        stdCall   _NCRConsoleDebug, <edx,eax>
;		pop		edx
;		pop		ecx
;		pop		ebx
;		pop		eax
;endif
;RMU


;
;  wait for startee to say it's active.  we should have a timeout on this
;  loop.  however, what if the startee went off in the weeds and corrupted
;  something.  if we timeout here we can't be sure what the other processor
;  is doing.
;
        align   dword
@@:     cmp     eax, PxFrame.SPx_Mask
        jne     @b


;RMU
;if DBG
;		push	eax
;		push	ebx
;		push	ecx
;		push	edx
;		mov		edx,3
;        stdCall   _NCRConsoleDebug, <edx,eax>
;		pop		edx
;		pop		ecx
;		pop		ebx
;		pop		eax
;endif
;RMU



        pop     dword ptr [ebx]                 ; restore vector
        add     esp, 1*4                        ; pop saved mask

        sti

        stdCall   _HalpFreeTiledCR3               ; free memory used for tiled

        pop     ebx
        pop     edi
        pop     esi
        mov     esp, ebp
        pop     ebp

;
; tell 'em we started another one
;
        mov     eax, 1
        stdRET    _HalStartNextProcessor


;
; All processors are online so now lets start the claiming process
;

        align   dword
Done:
;
; now that all CPU's are online we need to calculate how many interrupts
; each CPU can claim
;

        stdCall	_NCRAdjustDynamicClaims

;
; setting the never claim mask to correct value will start the claim process
;

        mov     eax, _DefaultNeverClaimIRQs;
		mov		_NCRNeverClaimIRQs, eax

		xor 	eax,eax
        stdRET	_HalStartNextProcessor


stdENDP _HalStartNextProcessor


_TEXT   ENDS


;
; heavy-duty plagarism from systempro stuff follows:
;


_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 1m and accessable 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_RMStubE equ     $
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

    ; eax, ebx, edx are still free

        WHO_AM_I
        mov     [PxFrame.SPx_Mask], eax

    ; 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