Source code of Windows XP (NT5)
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.

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