Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1415 lines
40 KiB

  1. // TITLE("System Initialization")
  2. //++
  3. //
  4. // Module Name:
  5. //
  6. // start.s
  7. //
  8. // Abstract:
  9. //
  10. // This module implements the code necessary to initially startup the
  11. // NT system.
  12. //
  13. // Author:
  14. //
  15. // Bernard Lint 8-Dec-1995
  16. //
  17. // Environment:
  18. //
  19. // Kernel mode only.
  20. //
  21. // Revision History:
  22. //
  23. // Based on MIPS version (from David N. Cutler (davec) 5-Apr-1991)
  24. //
  25. //--
  26. #include "ksia64.h"
  27. PublicFunction(SwapFromIdle)
  28. PublicFunction(KeBugCheck)
  29. PublicFunction(KiInitializeKernel)
  30. PublicFunction(KeLowerIrql)
  31. PublicFunction(KiNormalSystemCall)
  32. PublicFunction(KiRetireDpcList)
  33. PublicFunction(KeAcquireQueuedSpinLockAtDpcLevel)
  34. PublicFunction(KiAcquireSpinLock)
  35. PublicFunction(KeReleaseQueuedSpinLockFromDpcLevel)
  36. PublicFunction(KeTryToAcquireQueuedSpinLockRaiseToSynch)
  37. PublicFunction(KiIdleSchedule)
  38. .global __imp_HalProcessorIdle
  39. .global KiIvtBase
  40. .global KiIA64PtaContents
  41. .global KiIdleSummary
  42. #if !defined(NT_UP)
  43. .global HalAllProcessorsStarted
  44. .global KeNumberProcessors
  45. .global KiBarrierWait
  46. .global KiKernelPcrPage
  47. #endif // !defined(NT_UP)
  48. #include "icecap.h"
  49. #ifdef _CAPKERN
  50. PublicFunction(SwapContext)
  51. #endif
  52. #if DBG
  53. PublicFunction(KdPollBreakIn)
  54. PublicFunction(DbgBreakPointWithStatus)
  55. .global KdDebuggerEnabled
  56. #endif // DBG
  57. SBTTL("System Initialization")
  58. //++
  59. // Routine:
  60. //
  61. // VOID
  62. // KiSystemBegin (
  63. // PLOADER_PARAMETER_BLOCK)
  64. //
  65. // Routine Description:
  66. //
  67. // This routine is called when the NT system begins execution.
  68. // Its function is to initialize system hardware state, call the
  69. // kernel initialization routine, and then fall into code that
  70. // represents the idle thread for all processors.
  71. //
  72. // Arguments:
  73. //
  74. // a0 - Supplies a pointer to the loader parameter block.
  75. //
  76. // Return Value:
  77. //
  78. // None.
  79. //
  80. // Note:
  81. //
  82. // On entry the global pointer (gp) is initialized for this module (the
  83. // NTOS kernel) by the loader.
  84. //
  85. //--
  86. NESTED_ENTRY(KiSystemBegin)
  87. ALTERNATE_ENTRY(_start)
  88. NESTED_SETUP(1,2,6,0) // Also see "alloc" below
  89. //
  90. // Register aliases
  91. //
  92. rpT1 = t0
  93. rpT2 = t1
  94. rpT3 = t2
  95. rT1 = t3
  96. rT2 = t4
  97. rT3 = t5
  98. rT4 = t6
  99. rpLpb = t7
  100. rThread = t8
  101. rPcrPfn = t9
  102. rPrcb = t10
  103. rPcr2Pfn = t11
  104. rProcNum = t12
  105. rPKR = t13
  106. rPkrNum = t14
  107. rRR = t15
  108. rKstack = t16
  109. rVa = t17
  110. rPcrTr = t18
  111. rpPcr = t19
  112. FAST_DISABLE_INTERRUPTS // disable interrupts
  113. //
  114. // purge OS Loader 1:1 mapping
  115. //
  116. add rT2 = LpbDtrInfo + (TrInfoLength * DTR_LOADER_INDEX), a0
  117. ;;
  118. add rT3 = TrInfoValid, rT2
  119. ;;
  120. ld1 rT3 = [rT3]
  121. ;;
  122. cmp.eq p6, p0 = rT3, r0
  123. ;;
  124. add rT3 = TrInfoVirtualAddress, rT2
  125. add rT2 = TrInfoPageSize, rT2
  126. (p6) br.cond.spnt KiSystemBegin_ItrLoaderPurge
  127. ;;
  128. ld8 rT3 = [rT3]
  129. ld4 rT2 = [rT2]
  130. ;;
  131. shl rT2 = rT2, PS_SHIFT
  132. ;;
  133. ptr.d rT3, rT2
  134. ;;
  135. srlz.d
  136. ;;
  137. KiSystemBegin_ItrLoaderPurge:
  138. add rT2 = LpbItrInfo + (TrInfoLength * ITR_LOADER_INDEX), a0
  139. ;;
  140. add rT3 = TrInfoValid, rT2
  141. ;;
  142. ld1 rT3 = [rT3]
  143. ;;
  144. cmp.eq p6, p0 = rT3, r0
  145. ;;
  146. add rT3 = TrInfoVirtualAddress, rT2
  147. add rT2 = TrInfoPageSize, rT2
  148. (p6) br.cond.spnt KiSystemBegin_SalIvtPurge
  149. ;;
  150. ld8 rT3 = [rT3]
  151. ld4 rT2 = [rT2]
  152. ;;
  153. shl rT2 = rT2, PS_SHIFT
  154. ;;
  155. ptr.i rT3, rT2
  156. ;;
  157. srlz.i
  158. ;;
  159. //
  160. // purge SAL IVT
  161. //
  162. KiSystemBegin_SalIvtPurge:
  163. mov rT2 = PS_1M << 2
  164. mov rT3 = cr.iva
  165. ;;
  166. dep rT3 = 0, rT3, 0, PS_1M
  167. ;;
  168. ptr.i rT3, rT2
  169. ;;
  170. ALTERNATE_ENTRY(KiInitializeSystem)
  171. mov ar.rsc = r0 // put RSE in lazy mode
  172. movl rT2 = KiIvtBase
  173. ;;
  174. rsm 1 << PSR_IC // PSR.ic = 0
  175. mov cr.iva = rT2
  176. #if !defined(NT_UP)
  177. add rpT1 = @gprel(KiKernelPcrPage), gp
  178. ;;
  179. ld8 rPcrPfn = [rpT1]
  180. #else
  181. mov rPcrPfn = 0
  182. #endif
  183. ;;
  184. srlz.d
  185. add rpT2 = LpbPcrPage, a0 // -> PCR page number
  186. cmp.eq pt0, pt1 = 0, rPcrPfn
  187. ;;
  188. //
  189. // Initialize fixed TLB entries that map the PCR into system and user space.
  190. // N.B. These pages are per *processor* so we need a fixed mapping.
  191. //
  192. (pt0) ld8 rPcrPfn = [rpT2] // set PCR page number
  193. movl rVa = KiPcr // set virtual address of PCR
  194. ;;
  195. mov cr.ifa = rVa // setup IFA for insert
  196. mov rT1 = PAGE_SHIFT << IDTR_PS
  197. shl rPcrPfn = rPcrPfn, PAGE_SHIFT // shift to PPN field
  198. ;;
  199. mov cr.itir = rT1 // setup IDTR
  200. movl rPcrTr = KIPCR_TR_INITIAL // PCR translation except for PPN
  201. mov rT2 = DTR_KIPCR_INDEX
  202. ;;
  203. or rPcrTr = rPcrPfn, rPcrTr // form full TR
  204. ;;
  205. itr.d dtr[rT2] = rPcrTr // insert PCR TR to DTR
  206. ssm 1 << PSR_IC // PSR.ic = 1
  207. ;;
  208. srlz.i // I serialize
  209. add rpT1 = LpbKernelStack, a0 // -> idle thread stack
  210. mov rpLpb = a0 // save a0
  211. ;;
  212. LDPTR (rKstack, rpT1) // rKstack = idle thread stack
  213. // N.B. This is also the base
  214. // of backing store
  215. ;;
  216. mov ar.bspstore = rKstack // setup BSP
  217. .fframe STACK_SCRATCH_AREA
  218. add sp = -STACK_SCRATCH_AREA, rKstack // set sp
  219. ;;
  220. loadrs // invalidate RSE
  221. invala
  222. ;;
  223. mov ar.rsc = RSC_KERNEL // put RSE in eager mode
  224. ;;
  225. alloc rT4 = ar.pfs,1,2,6,0 // keep in sync with entry point alloc
  226. mov savedbrp = zero // setup bogus brp and pfs to
  227. mov savedpfs = zero // stop the debugger
  228. PROLOGUE_END
  229. //
  230. // Get page frame numbers for the PCR and PDR pages that were allocated by
  231. // the OS loader. Page directory is 4 physically contiguous pages.
  232. //
  233. add rpT1 = LpbPrcb, rpLpb // -> PRCB
  234. dep.z rRR = UREGION_INDEX, RR_INDEX, RR_INDEX_LEN
  235. ;;
  236. LDPTR (rPrcb, rpT1) // get processor block address
  237. movl rT2 = (START_PROCESS_RID << RR_RID)| RR_PS_VE
  238. ;;
  239. //
  240. // set RR[0], Region ID (RID) = 1, Page Size (PS) = 8K, VHPT enabled (VE) = 1
  241. //
  242. mov rr[rRR] = rT2 // initialize rr[0]
  243. movl rT1 = (START_SESSION_RID << RR_RID) | RR_PS_VE
  244. ;;
  245. //
  246. // set RR[1]
  247. //
  248. movl rRR = SADDRESS_BASE // initialize
  249. ;;
  250. mov rr[rRR] = rT1 // hydra region rr[1]
  251. ;;
  252. //
  253. // set RR[4], Region ID (RID) = 0, Page Size (PS) = 64K, VHPT enabled (VE) = 0
  254. //
  255. //
  256. // set RR[2] to RR[7], RID = KSEG3_RID, Page Size = 8K, VHPT disabled
  257. //
  258. movl rRR = 2 << RR_INDEX
  259. movl rT2 = (KSEG3_RID << RR_RID) | (PAGE_SHIFT << RR_PS)
  260. ;;
  261. mov rr[rRR] = rT2 // initialize rr[2]
  262. movl rRR = 3 << RR_INDEX
  263. ;;
  264. mov rr[rRR] = rT2 // initialize rr[3]
  265. movl rRR = 4 << RR_INDEX
  266. ;;
  267. mov rr[rRR] = rT2 // initialize rr[4]
  268. movl rRR = 5 << RR_INDEX
  269. ;;
  270. mov rr[rRR] = rT2 // initialize rr[5]
  271. movl rRR = 6 << RR_INDEX
  272. ;;
  273. mov rr[rRR] = rT2 // initialize rr[6]
  274. //
  275. // Protection Key Registers
  276. //
  277. mov rPKR = zero // pkr index = 0
  278. mov rT1 = PKR_VALID // rr[0].v=1, pkr[0].key=0
  279. mov rT2 = START_GLOBAL_RID
  280. ;;
  281. mov pkr[rPKR] = rT1
  282. add rPKR = 1, rPKR // increment PKR number
  283. shl rT2 = rT2, RR_RID
  284. ;;
  285. or rT2 = rT1, rT2
  286. ;;
  287. mov pkr[rPKR] = rT2 // pkr[1].v=1, pkr[1].key=START_GLOBAL_RID
  288. add rPKR = 1, rPKR // increment PKR number
  289. movl rT2 = START_PROCESS_RID
  290. ;;
  291. shl rT2 = rT2, RR_RID
  292. ;;
  293. or rT2 = rT1, rT2
  294. ;;
  295. mov pkr[rPKR] = rT2 // pkr[1].v=1, pkr[1].key=START_GLOBAL_RID
  296. add rPKR = 1, rPKR // increment PKR number
  297. mov rT2 = zero
  298. ;;
  299. Ksb_PKRLoop:
  300. mov pkr[rPKR] = rT2 // set PKR invalid
  301. add rPKR = 1, rPKR // increment PKR number
  302. ;;
  303. cmp.gtu pt0 = PKRNUM, rPKR // at end?
  304. (pt0) br.cond.sptk.few.clr Ksb_PKRLoop
  305. ;;
  306. //
  307. // Initialize debug registers
  308. //
  309. mov rT1 = 0
  310. ;;
  311. Ksb_DbrLoop:
  312. mov ibr[rT1] = r0
  313. mov dbr[rT1] = r0
  314. ;;
  315. #ifndef NO_12241
  316. srlz.d
  317. #endif
  318. cmp.ne pt0 = 7, rT1
  319. add rT1 = 1, rT1
  320. (pt0) br.cond.sptk.few Ksb_DbrLoop
  321. ;;
  322. //
  323. // Initialize control registers:
  324. // DCR
  325. // PSR pk, it, dt enabled
  326. //
  327. ssm (1 << PSR_DI) | (1 << PSR_PP) | (1 << PSR_IC) | (1 << PSR_DFH) | (1 << PSR_AC)
  328. ;;
  329. rsm (1 << PSR_PK) | (1 << PSR_MFH) // must clear the mfh bit
  330. ;;
  331. srlz.i
  332. movl rT1 = DCR_INITIAL
  333. ;;
  334. mov cr.dcr = rT1
  335. //
  336. // Clear TC
  337. //
  338. // Set up ITR entry 2 with EPC page for system call
  339. //
  340. movl rT4 = KiNormalSystemCall
  341. ptc.e zero
  342. add rpT1 = LpbKernelVirtualBase, rpLpb
  343. add rpT2 = LpbKernelPhysicalBase, rpLpb
  344. ;;
  345. LDPTR (rT2, rpT1) // virtual load point
  346. LDPTR (rT3, rpT2) // physical load point
  347. shr rT4 = rT4, PAGE_SHIFT // page number for syscall page
  348. ;;
  349. shr rT2 = rT2, PAGE_SHIFT // page number
  350. shr rT3 = rT3, PAGE_SHIFT // page number
  351. ;;
  352. sub rT2 = rT4, rT2 // page offset
  353. movl rVa = MM_EPC_VA
  354. ;;
  355. add rT3 = rT3, rT2 // compute pfn of syscall page
  356. movl rT2 = TR_VALUE(1,0,7,0,1,1,0,1)
  357. ;;
  358. shl rT3 = rT3, PAGE_SHIFT // set page number in TR
  359. ;;
  360. or rT2 = rT2, rT3
  361. mov rT3 = ITR_EPC_INDEX
  362. ;;
  363. //
  364. // Clear PSR.IC bit
  365. //
  366. add rpT1 = LpbPcrPage2, a0
  367. ;;
  368. ld8 rPcr2Pfn = [rpT1] // set second PCR page
  369. mov rT1 = PAGE_SHIFT << IDTR_PS
  370. rsm 1 << PSR_IC // PSR.ic = 0
  371. ;;
  372. srlz.d
  373. mov cr.ifa = rVa // virtual address of epc page
  374. mov cr.itir = rT1
  375. ;;
  376. itr.i itr[rT3] = rT2
  377. movl rVa = KiPcr2 // set virtual address of PCR
  378. ;;
  379. mov cr.ifa = rVa // setup IFA for insert
  380. movl rPcrTr = KIPCR_TR_INITIAL // PCR translation except for PPN
  381. mov cr.itir = rT1 // setup IDTR
  382. mov rT2 = DTR_KIPCR2_INDEX
  383. shl rPcr2Pfn = rPcr2Pfn, PAGE_SHIFT // shift to PPN field
  384. ;;
  385. or rPcrTr = rPcr2Pfn, rPcrTr // form full TR
  386. ;;
  387. itr.d dtr[rT2] = rPcrTr // insert PCR TR to DTR
  388. ssm 1 << PSR_IC // PSR.ic = 1
  389. ;;
  390. srlz.i // I serialize
  391. //
  392. // Set the cache policy for cached memory.
  393. // **** TBD ****
  394. //
  395. // Set the first level data and instruction cache fill size and size.
  396. //
  397. // **** TBD
  398. //
  399. // Set the second level data and instruction cache fill size and size.
  400. //
  401. // ***** TBD
  402. //
  403. // Set the data cache fill size and alignment values.
  404. //
  405. // **** TBD
  406. //
  407. // Set the instruction cache fill size and alignment values.
  408. //
  409. // **** TBD
  410. //
  411. // Sweep the data and instruction caches.
  412. //
  413. // **** TBD
  414. //
  415. // Initialize the fixed entries that map the PDR pages.
  416. // Setup page directory, pte's for page dir
  417. // **** TBD ****
  418. //
  419. //
  420. // Initialize the Processor Control Registers (PCR).
  421. //
  422. //
  423. // Initialize the minor and major version numbers.
  424. //
  425. mov rT1 = PCR_MINOR_VERSION // set minor version number
  426. movl rpPcr = KiPcr // get PCR address
  427. ;;
  428. add rpT1 = PcMinorVersion, rpPcr
  429. add rpT2 = PcMajorVersion, rpPcr
  430. mov rT2 = PCR_MAJOR_VERSION // set major version number
  431. ;;
  432. st2 [rpT1] = rT1 // store minor
  433. st2 [rpT2] = rT2 // store major
  434. add rpT3 = PcPrcb, rpPcr // -> PCR.Prcb
  435. ;;
  436. //
  437. // Set address of processor block.
  438. //
  439. st8 [rpT3] = rPrcb // store Prcb address
  440. //
  441. // Initialize the addresses of various data structures that are referenced
  442. // from the exception and interrupt handling code.
  443. //
  444. // N.B. The panic stack is a separate stack that is used when the current
  445. // kernel stack overlfows.
  446. //
  447. add rpT1 = PcInitialStack,rpPcr // -> initial kernel stack address in PCR
  448. add rpT2 = LpbPanicStack, rpLpb // -> lpb panic stack address
  449. add rpT3 = PcPanicStack, rpPcr // -> panic stack address in PCR
  450. ;;
  451. LDPTRINC (rT2, rpT2, LpbThread-LpbPanicStack) // panic stack address
  452. st8 [rpT1] = rKstack, PcKernelGP-PcInitialStack
  453. ;;
  454. LDPTR (rThread, rpT2) // -> current (idle) thread
  455. st8 [rpT3] = rT2, PcCurrentThread-PcPanicStack // set PCR panic stack address
  456. ;;
  457. st8 [rpT3] = rThread // set PCR current thread
  458. st8 [rpT1] = gp // save GP
  459. mov rT1 = HIGH_LEVEL
  460. ;;
  461. SET_IRQL(rT1) // Set to highest IRQL
  462. //
  463. // Clear floating status and zero the count and compare registers.
  464. //
  465. mov ar.ccv = zero
  466. movl rT1 = FPSR_FOR_KERNEL
  467. ;;
  468. mov ar.fpsr = rT1
  469. mov ar.ec = zero
  470. mov ar.lc = zero
  471. //
  472. // Set system dispatch address limits used by get and set context.
  473. // ***** TBD ******
  474. //
  475. // Set the default cache error routine address.
  476. // ****** TBD *******
  477. //
  478. // Sweep the data and instruction caches.
  479. // **** TBD *******
  480. //
  481. // Setup arguments and call kernel initialization routine.
  482. //
  483. add rpT1 = LpbProcess, rpLpb // -> idle process address
  484. add rpT2 = PbNumber, rPrcb
  485. mov out3 = rPrcb // arg 4 is current PRCB
  486. ;;
  487. LDPTR (out0, rpT1) // arg 1 is process
  488. mov out1 = rThread // arg 2 is thread
  489. mov out2 = rKstack // arg 3 is kernel stack
  490. ld1 out4 = [rpT2] // get processor number
  491. mov out5 = rpLpb // arg 6 is pointer to LPB
  492. br.call.sptk.many.clr brp = KiInitializeKernel
  493. ;; // (C code)
  494. alloc t0 = ar.pfs,0,0,0,0
  495. mov brp = zero // setup a bogus brp to stop debugger
  496. br KiIdleLoop // branch to KIIdleLoop()
  497. ;;
  498. //
  499. // Never get to this point!
  500. //
  501. NESTED_EXIT(KiSystemBegin)
  502. //
  503. //++
  504. //
  505. // VOID
  506. // KiIdleLoop (
  507. // VOID
  508. // )
  509. //
  510. // Routine Description:
  511. //
  512. // This is the idle loop for NT. This code runs in a thread for
  513. // each processor in the system. The idle thread runs at IRQL
  514. // DISPATCH_LEVEL and polls for work.
  515. //
  516. // Arguments:
  517. //
  518. // None.
  519. //
  520. // Return Value:
  521. //
  522. // None. (This routine never returns).
  523. //
  524. // When another thread is selected to run, SwapContext is called.
  525. // Normally, SwapContext saves and restores the non-volatile context.
  526. // The idle loop never returns so the preserved registers of the caller
  527. // do not need to be saved.
  528. // In other architectures, the idle loop pre-initializes the storage area
  529. // (switch frame) where SwapContext would normally save the preserved
  530. // registers with values that the idle loop needs
  531. // in those registers upon return from SwapContext and skips over the
  532. // register save on the way into SwapContext (alternate entry point
  533. // SwapFromIdle).
  534. // In this design the idle loop registers are preserved in
  535. // the register stack which is saved in the kernel backing store for the
  536. // idle thread. This allows us to skip the restore in SwapContext (not yet
  537. // implemented).
  538. //
  539. // All callers to SwapContext pass the following arguments:
  540. //
  541. // -- s0 = Prcb
  542. // -- s1 = current (previous) thread
  543. // -- s2 = new (next) thread
  544. //
  545. // Idle also enters SwapContext at SwapFromIdle with sp pointing to the switch
  546. // frame for preserved state.
  547. //
  548. // Since all registers used by the idle are saved in the register stack,
  549. // no registers need be recomputed on return from SwapContext.
  550. //
  551. //--
  552. NESTED_ENTRY(KiIdleLoop)
  553. NESTED_SETUP(0,6,2,0)
  554. //
  555. // allocate and build switch frame
  556. //
  557. .fframe SwitchFrameLength
  558. add sp = -SwitchFrameLength, sp
  559. ;;
  560. add t0 = ExFltS3+SwExFrame+STACK_SCRATCH_AREA, sp
  561. add t1 = ExFltS2+SwExFrame+STACK_SCRATCH_AREA, sp
  562. ;;
  563. .save.f 0xC
  564. stf.spill [t0] = fs3, ExFltS1-ExFltS3 // save fs3
  565. stf.spill [t1] = fs2, ExFltS0-ExFltS2 // save fs2
  566. mov t10 = bs4
  567. ;;
  568. .save.f 0x3
  569. stf.spill [t0] = fs1, ExIntS3-ExFltS1 // save fs1
  570. stf.spill [t1] = fs0, ExIntS2-ExFltS0 // save fs0
  571. mov t11 = bs3
  572. ;;
  573. .save.g 0xC
  574. .mem.offset 0,0
  575. st8.spill [t0] = s3, ExIntS1-ExIntS3 // save s3
  576. .mem.offset 8,0
  577. st8.spill [t1] = s2, ExIntS0-ExIntS2 // save s2
  578. mov t12 = bs2
  579. ;;
  580. .save.g 0x3
  581. .mem.offset 0,0
  582. st8.spill [t0] = s1, ExBrS4-ExIntS1 // save s1
  583. .mem.offset 8,0
  584. st8.spill [t1] = s0, ExBrS3-ExIntS0 // save s0
  585. mov t13 = bs1
  586. ;;
  587. .save.b 0x18
  588. st8 [t0] = t10, ExBrS2-ExBrS4 // save bs4
  589. st8 [t1] = t11, ExBrS1-ExBrS3 // save bs3
  590. mov t4 = ar.unat // captured Nats of s0-s3
  591. ;;
  592. .save.b 0x6
  593. st8 [t0] = t12, ExBrS0-ExBrS2 // save bs2
  594. st8 [t1] = t13, ExApEC-ExBrS1 // save bs1
  595. mov t14 = bs0
  596. ;;
  597. .save.b 0x1
  598. st8 [t0] = t14, ExApLC-ExBrS0 // save bs0
  599. .savepsp ar.pfs, ExceptionFrameLength-ExApEC-STACK_SCRATCH_AREA
  600. st8 [t1] = t16, ExIntNats-ExApEC
  601. mov t15 = ar.lc
  602. ;;
  603. .savepsp ar.lc, ExceptionFrameLength-ExApLC-STACK_SCRATCH_AREA
  604. st8 [t0] = t15
  605. .savepsp @priunat, ExceptionFrameLength-ExIntNats-STACK_SCRATCH_AREA
  606. st8 [t1] = t4 // save Nats of s0-s3
  607. nop.i 0
  608. ;;
  609. PROLOGUE_END
  610. //
  611. // Register aliases
  612. //
  613. rpT1 = t0
  614. rpT2 = t1
  615. rpT3 = t2
  616. rT1 = t3
  617. rT2 = t4
  618. rT3 = t5
  619. #if !defined(NT_UP)
  620. rpNumProc = t7
  621. rpBWait = t8
  622. rpDispLock = t9
  623. #endif // !defined(NT_UP)
  624. rpNextTh = t10
  625. #if DBG
  626. rDbgCount = t11
  627. rKdEnable = t12
  628. #endif //DBG
  629. pEmty = pt1
  630. pIdle = pt2
  631. #if !defined(NT_UP)
  632. pLoop = pt6
  633. #endif // !defined(NT_UP)
  634. #if DBG
  635. pBrk = ps2
  636. pNotZero = ps3
  637. #endif // DBG
  638. rpHPI = loc2
  639. rHalGP = loc3
  640. rKerGP = loc4
  641. #if !defined(NT_UP)
  642. rProcNum = loc5
  643. #endif // !defined(NT_UP)
  644. //
  645. // Initialize SwitchFPSR, SwitchPFS, SwitchRp in the switch frame
  646. //
  647. mov rT3 = ar.bsp
  648. movl rT2 = KiIdleReturn
  649. add rpT1 = SwPFS+STACK_SCRATCH_AREA, sp
  650. mov rKerGP = gp // save the kernel's gp
  651. mov rT1 = 0x308 // must match the values specified
  652. // by the alloc instruction at
  653. // the entry of the KiIdleLoop
  654. ;;
  655. st8.nta [rpT1] = rT1, SwRp-SwPFS // set pfs in the switch frame
  656. add rT3 = 0x30, rT3 // 6 local registers
  657. ;;
  658. st8.nta [rpT1] = rT2, SwFPSR-SwRp // set brp in the switch frame
  659. movl rT1 = FPSR_FOR_KERNEL
  660. ;;
  661. extr.u rpT3 = rT3, 0, 9
  662. st8.nta [rpT1] = rT1, SwRnat-SwFPSR
  663. ;;
  664. cmp.gtu pt1 = 0x30, rpT3 // Is there a slot for NAT bits?
  665. st8.nta [rpT1] = zero, SwBsp-SwRnat
  666. ;;
  667. (pt1) add rT3 = 8, rT3 // Adjust for NAT bits.
  668. ;;
  669. st8.nta [rpT1] = rT3
  670. movl rpT1 = KiPcr + PcPrcb
  671. ;;
  672. //
  673. // In a multiprocessor system the boot processor proceeds directly into
  674. // the idle loop. As other processors start executing, however, they do
  675. // not directly enter the idle loop and spin until all processors have
  676. // been started and the boot master allows them to proceed.
  677. //
  678. //
  679. // Setup initial idle loop register values
  680. //
  681. LDPTRINC (s0, rpT1, PcCurrentThread-PcPrcb) // address of PRCB
  682. add rpT2 = @gprel(__imp_HalProcessorIdle), gp
  683. ;;
  684. ld8 s2 = [rpT1], PcSetMember-PcCurrentThread // idle thread
  685. LDPTR (rpT2, rpT2) // -> function pointer
  686. ;;
  687. ld8 rProcNum = [rpT1] // Processor mask.
  688. ld8 rpHPI = [rpT2], PlGlobalPointer-PlEntryPoint // entry point
  689. ;;
  690. //
  691. // Control reaches here with IRQL at HIGH_LEVEL. Lower IRQL to
  692. // DISPATCH_LEVEL and set wait IRQL of idle thread.
  693. //
  694. ld8 rHalGP = [rpT2] // Hal GP
  695. add rpT1 = ThWaitIrql, s2 // -> thread WaitIrql
  696. mov out0 = DISPATCH_LEVEL // get dispatch level IRQL
  697. ;;
  698. add rProcNum = -1, rProcNum // Generate mask of lower numbered processors.
  699. st1 [rpT1] = out0 // set wait IRQL of idle thread
  700. br.call.sptk.few.clr brp = KeLowerIrql // call KeLowerIrql(IRQL)
  701. ;;
  702. FAST_ENABLE_INTERRUPTS
  703. mov gp = rKerGP
  704. ;;
  705. //
  706. // In a multiprocessor system the boot processor proceeds directly into
  707. // the idle loop. As other processors start executing, however, they do
  708. // not directly enter the idle loop and spin until all processors have
  709. // been started and the boot master allows them to proceed.
  710. //
  711. #if !defined(NT_UP)
  712. add rpBWait = @gprel(KiBarrierWait), gp
  713. ;;
  714. Kil_WaitLoop:
  715. YIELD
  716. ld4 rT1 = [rpBWait] // get barrier wait value
  717. ;;
  718. cmp.ne pLoop = zero, rT1 // loop if not zero
  719. (pLoop) br.dpnt.few.clr Kil_WaitLoop // spin until allowed to proceed
  720. #endif // !defined(NT_UP)
  721. KiIdleReturn:
  722. mov s1 = s2 // s1 <- IdleThread
  723. #if DBG
  724. mov rDbgCount = 20 * 1000 // set breakin loop counter
  725. #endif // DBG
  726. ;;
  727. KiIdleSwitchBlocked:
  728. mov rT1 = DISPATCH_LEVEL
  729. ;;
  730. SET_IRQL(rT1)
  731. //
  732. // The following loop is executed for the life of the system.
  733. //
  734. Kil_TopOfIdleLoop::
  735. mov gp = rKerGP // restore gp
  736. //
  737. // If processor 0, check for debugger breakin, otherwise just check for
  738. // DPCs again.
  739. //
  740. #if DBG
  741. #if !defined(NT_UP)
  742. ;;
  743. add rpT1 = @gprel(KiIdleSummary), gp
  744. ;;
  745. ld8 rT1 = [rpT1] // Get the current idle summary.
  746. ;;
  747. and rT1 = rT1, rProcNum // Are mask out higher number processors
  748. ;;
  749. cmp4.ne pNotZero = zero, rT1 // pNotZero = not processor zero
  750. (pNotZero) br.cond.dptk.few.clr Kil_CheckDpcList // br if not processor zero
  751. #endif // !defined(NT_UP)
  752. //
  753. // Check if the debugger is enabled, and whether it is time to poll
  754. // for a debugger breakin. (This check is only performed on cpu 0).
  755. //
  756. sub rDbgCount = rDbgCount,zero,1 // decrement poll counter
  757. ;;
  758. add rKdEnable = @gprel(KdDebuggerEnabled), gp
  759. cmp.eq pBrk = rDbgCount, zero // zero yet?
  760. ;;
  761. (pBrk) ld1 rKdEnable = [rKdEnable] // check if debugger enabled
  762. (pBrk) mov rDbgCount = 20 * 1000 // set breakin loop counter
  763. ;;
  764. (pBrk) cmp.ne pBrk = rKdEnable, zero // pBrk = 1 if Kd enabled
  765. (pBrk) br.call.dpnt.few.clr brp=KdPollBreakIn // check if breakin requested
  766. ;;
  767. mov gp = rKerGP // restore gp
  768. (pBrk) cmp.ne pBrk = v0, zero // ne => break in requested
  769. mov out0 = DBG_STATUS_CONTROL_C
  770. (pBrk) br.call.sptk brp = DbgBreakPointWithStatus
  771. ;;
  772. mov gp = rKerGP // restore gp
  773. #endif // DBG
  774. //
  775. // Disable interrupts and check if there is any work in the DPC list.
  776. //
  777. Kil_CheckDpcList:
  778. //
  779. // Process the deferred procedure call list for the current processor.
  780. //
  781. FAST_ENABLE_INTERRUPTS // give interrupts a chance
  782. ;;
  783. srlz.d
  784. add rpT1 = PbDpcQueueDepth, s0
  785. add rpT2 = PbTimerHand, s0
  786. add rpT3 = PbDeferredReadyListHead, s0
  787. ;;
  788. FAST_DISABLE_INTERRUPTS // disable interrupts
  789. ;;
  790. ld8.nta rT2 = [rpT2] // Load Prcb->TimerHand
  791. ld4.nta rT1 = [rpT1] // Load Prcb->DpcQueueDepth
  792. ld8.nta rT3 = [rpT3] // Load Prcb->DeferredReadyListHead
  793. mov out0 = s0 // PRCB
  794. ;;
  795. cmp4.eq pt0, pt1 = rT1, zero // if eq, queue empty
  796. movl rpT1 = KiPcr+PcDispatchInterrupt
  797. ;;
  798. add rpNextTh = PbNextThread, s0 // -> next thread
  799. (pt0) cmp.eq pt0, pt1 = rT2, zero // if eq, TimerHand zero
  800. ;;
  801. (pt0) cmp.eq pt0, pt1 = rT3, zero // if equal then no deferred ready list
  802. ;;
  803. (pt1) st1 [rpT1] = zero // clear dispatch interrupt req
  804. (pt0) br.cond.dpnt Kil_CheckNextThread
  805. ;;
  806. #ifndef _CAPKERN
  807. (pt1) br.call.sptk.few.clr brp = KiRetireDpcList
  808. #else
  809. ;;
  810. CAPSTART(KiIdleLoop,KiRetireDpcList)
  811. mov out0 = s0 // restore PRCB
  812. br.call.sptk.few.clr brp = KiRetireDpcList
  813. #endif
  814. ;;
  815. CAPEND(KiIdleLoop)
  816. add rpNextTh = PbNextThread, s0 // -> next thread
  817. mov gp = rKerGP // restore gp
  818. #if DBG
  819. mov rDbgCount = 20 * 1000 // set breakin loop counter
  820. #endif // DBG
  821. ;;
  822. //
  823. // Check if a thread has been selected to run on this processor
  824. //
  825. Kil_CheckNextThread:
  826. #if DBG // Debug code.
  827. add rT1 = PbIdleThread, s0;;
  828. ld8 rT1 = [rT1];;
  829. cmp.ne pt0 = rT1, s1;;
  830. (pt0) break.i BREAKPOINT_STOP
  831. #endif
  832. ld8 s2 = [rpNextTh] // next thread
  833. mov rT1 = SYNCH_LEVEL
  834. ;;
  835. cmp.eq pIdle = s2, zero // if no thread to run
  836. (pIdle) br.dpnt.few.clr Kil_Idle // br to Idle
  837. //
  838. // A thread has been selected for execution on this processor. Acquire
  839. // the context swap lock, get the thread address again (it may have
  840. // changed), clear the address of the next thread in the processor block,
  841. // and call swap context to start execution of the selected thread.
  842. //
  843. SET_IRQL(rT1)
  844. FAST_ENABLE_INTERRUPTS
  845. #if !defined(NT_UP)
  846. ;;
  847. add out0 = ThSwapBusy, s1 // Get swap busy flag address
  848. mov rT1 = 1
  849. ;;
  850. #if DBG
  851. ld1 rT2 = [out0] ;;
  852. cmp.ne pt0 = rT2, r0 ;;
  853. (pt0) break.i BREAKPOINT_STOP
  854. #endif
  855. st1.rel [out0] = rT1 // Set swap busy flag
  856. add s2 = PbNextThread, s0 // -> next thread
  857. add out0 = PbPrcbLock, s0 // Get address of PRCB lock
  858. br.call.sptk brp = KiAcquireSpinLock // Acquire PRCB lock
  859. ;;
  860. //
  861. // Reread the next thread because it may be changed in a MP system.
  862. //
  863. // The selected thread may be blocked from switching at this time
  864. // if it is being scheduled on this processor because it is being
  865. // removed from another processor. The switch is blocked until
  866. // the thread is completely removed from the other processor. In
  867. // this case, drop the idle thread lock and continue execution as
  868. // if resuming from a context switch.
  869. //
  870. ld8 s2 = [s2] // reread next thread
  871. mov rT1 = 1 // Load lock acquired value
  872. ;;
  873. add rpT1 = ThSwapBusy, s2 // &NewThread->SwapBusy
  874. cmp.eq pt0, pt1 = s2, s1 // check for swap idle to idle
  875. ;;
  876. (pt1) ld1.acq rT1 = [rpT1] // Fetch swap busy flag
  877. ;;
  878. (pt1) cmp.ne pt1 = 0, rT1
  879. (pt0) br.cond.spnt Kil_Idle2Idle // rare case, idle to idle
  880. (pt1) br.cond.spnt kil_target_busy // undo what we have done and loop
  881. ;;
  882. #endif // !defined(NT_UP)
  883. add rpT2 = PbCurrentThread, s0 // -> address of current thread
  884. ;;
  885. add rpT1 = ThState, s2
  886. // set new thread as current
  887. st8 [rpT2] = s2, PbNextThread-PbCurrentThread
  888. mov rT1 = Running
  889. add out0 = PbPrcbLock, s0 // Get address of PRCB lock
  890. add out1 = PbIdleSchedule, s0 // get idle schedule flag
  891. ;;
  892. #if DBG
  893. ld8 rT2 = [out0] ;;
  894. cmp.eq pt0 = rT2, r0 ;;
  895. (pt0) break.i BREAKPOINT_STOP
  896. #endif
  897. st1.rel [rpT1] = rT1 // set new thread state to running
  898. st8 [rpT2] = zero // clear address of next thread
  899. st1 [out1] = zero // clear idle schedule
  900. st8.rel [out0] = zero // release prcb lock
  901. swap_context:
  902. #if !defined(NT_UP)
  903. #if DBG // Debug code.
  904. add rT1 = PbIdleThread, s0;;
  905. ld8 rT1 = [rT1];;
  906. cmp.ne pt0 = rT1, s1;;
  907. (pt0) break.i BREAKPOINT_STOP
  908. #endif
  909. //
  910. // When queueing APCs to target threads we need the store to the threads
  911. // state to be ordered first wrt the load of the KernelApcPending flag.
  912. //
  913. mf
  914. #endif // !defined(NT_UP)
  915. //
  916. // Swap context to new thread
  917. // (returns to KiIdleReturn above).
  918. //
  919. CAPSTART(KiIdleLoop,SwapContext)
  920. br.call.sptk.few.clr brp = SwapFromIdle
  921. ;;
  922. CAPEND(KiIdleLoop)
  923. ;;
  924. //
  925. // There are no entries in the DPC list and a thread has not been selected
  926. // for execution on this processor. Call the HAL so power managment can be
  927. // performed.
  928. //
  929. // N.B. The HAL is called with interrupts disabled. The HAL will return
  930. // with interrupts enabled.
  931. //
  932. Kil_Idle:
  933. //
  934. // See if we need to schedule something
  935. //
  936. add out1 = PbIdleSchedule, s0 // get idle schedule flag
  937. ;;
  938. ld1 out0 = [out1]
  939. ;;
  940. cmp.ne pt0 = out0, zero
  941. ;;
  942. (pt0) br.cond.spnt kil_idle_sched
  943. mov bt0 = rpHPI // set target routine
  944. movl rT1 = Kil_TopOfIdleLoop // set return address
  945. ;;
  946. YIELD
  947. mov gp = rHalGP // set Hal GP
  948. mov brp = rT1 // return to top of idle loop
  949. br.call.dpnt.few.clr bt1 = bt0 // call HalProcessorIdle
  950. ;; // does not return here.
  951. kil_idle_sched:
  952. SET_IRQL(rT1)
  953. FAST_ENABLE_INTERRUPTS
  954. ;;
  955. mov out0 = s0
  956. br.call.sptk brp = KiIdleSchedule
  957. ;;
  958. cmp.eq pt0, pt1 = v0, zero
  959. (pt0) br.cond.spnt Kil_TopOfIdleLoop
  960. ;;
  961. mov s2 = v0
  962. add rpT1 = ThSwapBusy, v0 // &NewThread->SwapBusy
  963. ;;
  964. kil_idle_swapbusy:
  965. (pt0) YIELD
  966. ld1.acq rT1 = [rpT1] // Fetch swap busy flag
  967. ;;
  968. cmp.eq pt1, pt0 = 0, rT1
  969. (pt1) br.cond.sptk swap_context
  970. (pt0) br.cond.spnt kil_idle_swapbusy
  971. //
  972. // In the event that a thread was scheduled to run on this processor
  973. // but before the idle loop picked it up, it was made inelligible for
  974. // this processor and there is no other thread to run, the idle thread
  975. // will have been selected as the NextThread for this processor and
  976. // this processor will have been marked idle in KiIdleSummary.
  977. //
  978. // It is then possible for another thread to be selected for this processor
  979. // between the time the idle loop picks up the NextThread field and clears
  980. // it.
  981. //
  982. Kil_Idle2Idle:
  983. ;;
  984. add out0 = PbNextThread, s0 // -> next thread
  985. ;;
  986. st8.rel [out0] = zero // clear next thread
  987. ;;
  988. kil_target_busy:
  989. add out0 = ThSwapBusy, s1 // Get swap busy flag address
  990. ;;
  991. #if DBG
  992. ld1 rT2 = [out0] ;;
  993. cmp.eq pt0 = rT2, r0 ;;
  994. (pt0) break.i BREAKPOINT_STOP
  995. #endif
  996. st1.rel [out0] = zero // Clear swap busy flag
  997. add out0 = PbPrcbLock, s0 // Get address of PRCB lock
  998. ;;
  999. #if DBG
  1000. ld8 rT2 = [out0] ;;
  1001. cmp.eq pt0 = rT2, r0 ;;
  1002. (pt0) break.i BREAKPOINT_STOP
  1003. #endif
  1004. st8.rel [out0] = zero
  1005. ;;
  1006. br KiIdleSwitchBlocked // loop.
  1007. NESTED_EXIT(KiIdleLoop)
  1008. #if !defined(NT_UP)
  1009. //++
  1010. // Routine:
  1011. //
  1012. // VOID
  1013. // KiOSRendezvous (
  1014. // )
  1015. //
  1016. // Routine Description:
  1017. //
  1018. // OS rendezvous entry point called from SAL for MP boot.
  1019. // Establish kernel mapping and rfi to KiInitializeSystem with
  1020. // translation turned on.
  1021. //
  1022. // Arguments:
  1023. //
  1024. // Return Value:
  1025. //
  1026. // None.
  1027. //
  1028. //--
  1029. .global MmSystemParentTablePage
  1030. .global MiNtoskrnlPhysicalBase
  1031. .global MiNtoskrnlVirtualBase
  1032. .global MiNtoskrnlPageShift
  1033. LEAF_ENTRY(KiOSRendezvous)
  1034. mov t5 = ip // get the physical addr for KiOSRendezvous
  1035. mov psr.l = zero // initialize psr.l
  1036. movl t0 = KSEG0_BASE
  1037. ;;
  1038. mov ar.rsc = zero // invalidate register stack
  1039. mov t1 = (START_GLOBAL_RID << RR_RID) | (PAGE_SHIFT << RR_PS) | (1 << RR_VE)
  1040. ;;
  1041. //
  1042. // Initialize Region Register for kernel
  1043. //
  1044. loadrs
  1045. mov rr[t0] = t1
  1046. //
  1047. // Setup translation for kernel/hal binary.
  1048. //
  1049. movl t0 = KSEG0_BASE;
  1050. ;;
  1051. movl t2 = MiNtoskrnlPhysicalBase
  1052. movl t4 = MiNtoskrnlPageShift
  1053. movl t0 = MiNtoskrnlVirtualBase
  1054. movl t3 = KiOSRendezvous
  1055. ;;
  1056. sub t6 = t2, t3
  1057. sub t7 = t4, t3
  1058. sub t0 = t0, t3
  1059. ;;
  1060. add t6 = t5, t6 // get a physical addr for MiNtoskrnlPhysicalBase
  1061. add t7 = t5, t7 // get a physical addr for MiNtoskrnlPageShift
  1062. add t0 = t5, t0 // get a physical addr for MiNtoskrnlVirtualBase
  1063. ;;
  1064. ld8 t6 = [t6]
  1065. ld4 t7 = [t7]
  1066. ld8 t0 = [t0]
  1067. movl t8 = VALID_KERNEL_EXECUTE_PTE
  1068. ;;
  1069. mov cr.ifa = t0
  1070. or t2 = t6, t8
  1071. shl t1 = t7, PS_SHIFT
  1072. ;;
  1073. mov cr.itir = t1
  1074. mov t3 = DTR_KERNEL_INDEX
  1075. ;;
  1076. itr.d dtr[t3] = t2
  1077. ;;
  1078. itr.i itr[t3] = t2
  1079. //
  1080. // Setup VHPT
  1081. //
  1082. movl t0 = KiIA64PtaContents
  1083. movl t3 = KiOSRendezvous
  1084. ;;
  1085. sub t6 = t0, t3
  1086. ;;
  1087. add t6 = t5, t6
  1088. ;;
  1089. ld8 t6 = [t6]
  1090. ;;
  1091. mov cr.pta = t6
  1092. //
  1093. // Turn on address translation
  1094. //
  1095. movl t1 = (1 << PSR_BN) | (1 << PSR_IT) | (1 << PSR_DA) | (1 << PSR_RT) | (1 << PSR_DT) | (1 << PSR_IC)
  1096. ;;
  1097. mov cr.ipsr = t1
  1098. //
  1099. // Branch to KiInitializeSystem
  1100. //
  1101. // Need to do a "rfi" in order set "it" bits in the PSR.
  1102. // This is the only way to set them.
  1103. //
  1104. movl t0 = KiOSRendezvousStub
  1105. ;;
  1106. mov cr.iip = t0
  1107. ;;
  1108. rfi
  1109. ;;
  1110. .global KeLoaderBlock
  1111. KiOSRendezvousStub:
  1112. alloc t0 = 0,0,1,0
  1113. movl gp = _gp
  1114. mov t9 = PAGE_SHIFT << PS_SHIFT
  1115. movl t8 = KADDRESS_BASE
  1116. ;;
  1117. //
  1118. // Set up the VHPT table
  1119. //
  1120. thash t8 = t8
  1121. add t7 = @gprel(MmSystemParentTablePage), gp
  1122. ;;
  1123. ld8 t7 = [t7]
  1124. rsm 1 << PSR_IC // PSR.ic = 0
  1125. ;;
  1126. srlz.d
  1127. thash t8 = t8
  1128. movl t6 = PDR_TR_INITIAL
  1129. ;;
  1130. //
  1131. // Install DTR for the kernel parent page table
  1132. //
  1133. thash t8 = t8
  1134. mov t10 = DTR_KTBASE_INDEX
  1135. shl t7 = t7, PAGE_SHIFT
  1136. ;;
  1137. mov cr.ifa = t8
  1138. or t7 = t7, t6
  1139. mov cr.itir = t9
  1140. ;;
  1141. itr.d dtr[t10] = t7
  1142. ssm 1 << PSR_IC // PSR.ic = 1
  1143. ;;
  1144. srlz.i // I serialize
  1145. add out0 = @gprel(KeLoaderBlock), gp
  1146. ;;
  1147. ld8 out0 = [out0] // dereference pointer
  1148. movl t0 = KiInitializeSystem
  1149. ;;
  1150. mov bt0 = t0
  1151. br.call.sptk brp = bt0 // branch to entry point
  1152. LEAF_EXIT(KiOSRendezvous)
  1153. #endif // !defined(NT_UP)