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.

281 lines
8.9 KiB

  1. title "System Startup"
  2. ;++
  3. ;
  4. ; Copyright (c) 2000 Microsoft Corporation
  5. ;
  6. ; Module Name:
  7. ;
  8. ; start.asm
  9. ;
  10. ; Abstract:
  11. ;
  12. ; This module implements the code necessary to initially startup the NT
  13. ; system on an AMD64 system.
  14. ;
  15. ; Author:
  16. ;
  17. ; David N. Cutler (davec) 22-Sep-2000
  18. ;
  19. ; Environment:
  20. ;
  21. ; Kernel mode only.
  22. ;
  23. ;--
  24. include ksamd64.inc
  25. extern KdInitSystem:proc
  26. extern KeLoaderBlock:qword
  27. extern KiBarrierWait:dword
  28. extern KiIdleLoop:proc
  29. extern KiInitializeBootStructures:proc
  30. extern KiInitializeKernel:proc
  31. extern KiInitialPCR:byte
  32. TotalFrameLength EQU (LEGACY_SAVE_AREA_LENGTH + KEXCEPTION_FRAME_LENGTH + KSWITCH_FRAME_LENGTH)
  33. subttl "System Startup"
  34. ;++
  35. ;
  36. ; Routine Description:
  37. ;
  38. ; This routine is called at system startup to perform early initialization
  39. ; and to inititialize the kernel debugger. This allows breaking into the
  40. ; kernel debugger very early during system startup. After kernel debugger
  41. ; initialization, kernel initialization is performed. On return from kernel
  42. ; initialization the idle loop is entered. The idle loop begins execution
  43. ; and immediately finds the system startup (phase 1) thread ready to run.
  44. ; Phase 1 initialization is performed and all other processors are started.
  45. ; As each process starts it also passes through the system startup code, but
  46. ; it does not initialization the kernel debugger.
  47. ;
  48. ; Arguments:
  49. ;
  50. ; LoaderBlock (rcx) - Supplies a pointer to the loader block.
  51. ;
  52. ; Implicit Arguments:
  53. ;
  54. ; When the system starts up the loader has done some initialization. In
  55. ; particular all structures have at least been zeroed and the GDT and
  56. ; TSS have been completely initialized.
  57. ;
  58. ; The loader block has been reformatted by the loader into a 64-bit loader
  59. ; block and all pertinent fields have been filled in.
  60. ;
  61. ; The address of the PRCB is passed in the loader block (only for processors
  62. ; other than zero).
  63. ;
  64. ; The address of the idle thread and idle process are passed in the loader
  65. ; block (only for processors other than zero).
  66. ;
  67. ; The GDT and IDT address and limits are contained in the gdtr and idtr
  68. ; registers.
  69. ;
  70. ; The address of the TSS must be extraced from the appropriate GDT entry
  71. ; and stored in the PCR.
  72. ;
  73. ; The stack register (RSP) is loaded with the idle thread stack and the
  74. ; kernel stack field of the loader block contains the address of the DPC
  75. ; stack.
  76. ;
  77. ; Return Value:
  78. ;
  79. ; None - function does not return.
  80. ;
  81. ;--
  82. SsFrame struct
  83. P1Home dq ? ;
  84. P2Home dq ? ;
  85. P3Home dq ? ;
  86. P4Home dq ? ;
  87. P5 dq ? ; parameter 5
  88. P6 dq ? ; parameter 6
  89. Fill dq ? ; fill to 8 mode 16
  90. SsFrame ends
  91. NESTED_ENTRY KiSystemStartup, INIT
  92. alloc_stack (sizeof SsFrame) ; allocate stack frame
  93. END_PROLOGUE
  94. ;
  95. ; Save the address of the loader block.
  96. ;
  97. ; N.B. This is the same address for all processors.
  98. ;
  99. mov KeLoaderBlock, rcx ; save loader block address
  100. ;
  101. ; Initialize PCR self address and the current PRCB address.
  102. ;
  103. mov rdx, LpbPrcb[rcx] ; get specified PRCB address
  104. lea rax, KiInitialPCR + PcPrcb ; get builtin PRCB address
  105. test rdx, rdx ; test if PRCB address specified
  106. cmovz rdx, rax ; if z, set builtin PRCB address
  107. mov LpbPrcb[rcx], rdx ; set loader block PRCB address
  108. mov r8, rdx ; copy PRCB address
  109. sub rdx, PcPrcb ; compute PCR address
  110. mov PcSelf[rdx], rdx ; set PCR self address
  111. mov PcCurrentPrcb[rdx], r8 ; set current PRCB address
  112. ;
  113. ; Initialize kernel special registers and the address of the GDT, TSS, and
  114. ; IDT in the PRCB and PCR.
  115. ;
  116. ; N.B. The debug registers are zeroed in the PRCB.
  117. ;
  118. mov r8, cr0 ; save CR0
  119. mov PcCr0[rdx], r8 ;
  120. mov r8, cr2 ; save CR2
  121. mov PcCr2[rdx], r8 ;
  122. mov r8, cr3 ; save CR3
  123. mov PcCr3[rdx], r8 ;
  124. mov r8, cr4 ; save CR4
  125. mov PcCr4[rdx], r8 ;
  126. sgdt PcGdtrLimit[rdx] ; save GDT limit and base
  127. mov r8, PcGdtrBase[rdx] ; set GDT base address
  128. mov PcGdt[rdx], r8 ;
  129. sidt PcIdtrLimit[rdx] ; save IDT limit and base
  130. mov r9, PcIdtrBase[rdx] ; set IDT base address
  131. mov PcIdt[rdx], r9 ;
  132. str word ptr PcTr[rdx] ; save TR selector
  133. sldt word ptr PcLdtr[rdx] ; save LDT selector
  134. mov dword ptr PcMxCsr[rdx], INITIAL_MXCSR ; set initial MXCSR
  135. ;
  136. ; Set connical selector values (note CS, GS, and SS are already set).
  137. ;
  138. mov ax, KGDT64_R3_DATA or RPL_MASK ;
  139. mov ds, ax ;
  140. mov es, ax ;
  141. mov ax, KGDT64_R3_CMTEB or RPL_MASK ;
  142. mov fs, ax ;
  143. ;
  144. ; Load a NULL selector into the LDT.
  145. ;
  146. xor eax, eax ; set NULL selector for LDT
  147. lldt ax ;
  148. ;
  149. ; Extract TSS address from GDT entry and store in PCR.
  150. ;
  151. mov ax, KGDT64_SYS_TSS + KgdtBaseLow[r8] ; set low 16-bits
  152. mov PcTss[rdx], ax ;
  153. mov al, KGDT64_SYS_TSS + KgdtBaseMiddle[r8] ; set middle 8-bits
  154. mov PcTss + 2[rdx], al ;
  155. mov al, KGDT64_SYS_TSS + KgdtBaseHigh[r8] ; set high 8-bits
  156. mov PcTss + 3[rdx], al ;
  157. mov eax, KGDT64_SYS_TSS +KgdtBaseUpper[r8] ; set upper 32-bits
  158. mov PcTss + 4[rdx], eax ;
  159. ;
  160. ; Initialize the GS base and swap addresses.
  161. ;
  162. mov eax, edx ; set low 32-bits of address
  163. shr rdx, 32 ; set high 32-bits of address
  164. mov ecx, MSR_GS_BASE ; get GS base address MSR number
  165. wrmsr ; write GS base address
  166. mov ecx, MSR_GS_SWAP ; get GS swap base MSR number
  167. wrmsr ; write GS swap base address
  168. ;
  169. ; Initialize boot structures.
  170. ;
  171. mov rcx, KeLoaderBlock ; set loader block address
  172. call KiInitializeBootStructures ; initialize boot structures
  173. ;
  174. ; Initialize the kernel debugger if this is processor zero.
  175. ;
  176. xor ecx, ecx ; set phase to 0
  177. mov rdx, KeLoaderBlock ; set loader block address
  178. call KdInitSystem ; initialize debugger
  179. ;
  180. ; Raise IRQL to high level and initialize the kernel.
  181. ;
  182. KiSS10: mov ecx, HIGH_LEVEL ; set high IRQL
  183. SetIrql ;
  184. ;
  185. ; Reserve space for idle thread stack initialization.
  186. ;
  187. ; N.B. This reservation ensures that the initialization of the thread stack
  188. ; does not overwrite any information on the current stack which is the
  189. ; same stack.
  190. ;
  191. sub rsp, TotalFrameLength ; allocate stack
  192. ;
  193. ; Initialize kernel.
  194. ;
  195. mov rax, KeLoaderBlock ; set loader block address
  196. mov rcx, LpbProcess[rax] ; set idle process address
  197. mov rdx, LpbThread[rax] ; set idle thread address
  198. mov r8, gs:[PcTss] ; set idle stack address
  199. mov r8, TssRsp0[r8] ;
  200. mov r9, LpbPrcb[rax] ; set PRCB address
  201. mov r10b, PbNumber[r9] ; set processor number
  202. mov SsFrame.P5[rsp], r10 ;
  203. mov SsFrame.P6[rsp], rax ; set loader block address
  204. call KiInitializeKernel ; Initialize kernel
  205. ;
  206. ; Reset stack to include only the space for the legacy NPX state.
  207. ;
  208. mov rcx, gs:[PcTss] ; get TSS address
  209. mov rcx, TssRsp0[rcx] ; get idle stack address
  210. lea rsp, (-LEGACY_SAVE_AREA_LENGTH)[rcx] ; deallocate stack space
  211. ;
  212. ; Enable interrupts, lower IRQL to dispatch level, and set the wait IRQL for
  213. ; the idle thread.
  214. ;
  215. sti ; enable interrupts
  216. mov ecx, DISPATCH_LEVEL ; set dispatch IRQL
  217. SetIrql ;
  218. mov rcx, gs:[PcCurrentThread] ; get current thread address
  219. mov byte ptr ThWaitIrql[rcx], DISPATCH_LEVEL ; set wait IRQL
  220. ;
  221. ; In a multiprocessor system the boot processor proceeds directly into the
  222. ; idle loop. As other processors start executing, however, they do not enter
  223. ; the idle loop directly - they spin until all processors have been started
  224. ; and the boot master allows them to proceed.
  225. ;
  226. ifndef NT_UP
  227. KiSS20: cmp KiBarrierWait, 0 ; check if barrier set
  228. jnz short KiSS20 ; if nz, barrier set
  229. endif
  230. call KiIdleLoop ; enter idle loop - no return
  231. NESTED_END KisystemStartup, INIT
  232. end