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.

1046 lines
34 KiB

  1. // TITLE( "Start System" )
  2. //++
  3. //
  4. // Copyright (c) 1992 Digital Equipment Corporation
  5. //
  6. // Module:
  7. //
  8. // start.s
  9. //
  10. // Abstract:
  11. //
  12. // This module implements the code necessary to iniitially start NT
  13. // on an alpha - it includes the routine that first receives control
  14. // when the loader executes the kernel.
  15. //
  16. // Author:
  17. //
  18. // Joe Notarangelo 02-Apr-1992
  19. //
  20. // Environment:
  21. //
  22. // Kernel Mode only.
  23. //
  24. // Revision History:
  25. //
  26. //--
  27. #include "ksalpha.h"
  28. //
  29. // Define the total frame size.
  30. //
  31. #define TotalFrameLength (KERNEL_STACK_SIZE - (TrapFrameLength + \
  32. ExceptionFrameLength) )
  33. //
  34. // Define variables to hold the address of the PCR and current thread
  35. // on uniprocessor systems.
  36. //
  37. .data
  38. #ifdef NT_UP
  39. .globl KiPcrBaseAddress
  40. KiPcrBaseAddress:
  41. .quad 0 : 1
  42. .globl KiCurrentThread
  43. KiCurrentThread:
  44. .quad 0 : 1
  45. #endif //NT_UP
  46. SBTTL( "System Startup" )
  47. //++
  48. //
  49. // Routine Description:
  50. //
  51. // This routine represents the final stage of the loader and is also
  52. // executed as each additional processor is brought online is a multi-
  53. // processor system. It is responsible for installing the loaded PALcode
  54. // image and transfering control kernel startup code.
  55. //
  56. // N.B. This code assumes that the I-cache is coherent.
  57. //
  58. // N.B. This routine does not execute in the context of the operating
  59. // system but instead executes in the context of the firmware
  60. // PAL environment. This routine can only use those services
  61. // guaranteed to exist in the firmware. The only PAL services
  62. // that can be counted on are: swppal, imb, and halt.
  63. //
  64. // Arguments:
  65. //
  66. // a0 - Supplies pointer to loader parameter block.
  67. //
  68. // Return Value:
  69. //
  70. // None.
  71. //
  72. //--
  73. .struct 0
  74. SsRa: .space 8 // Save ra
  75. .space 8 // for stack alignment
  76. SsFrameLength: //
  77. NESTED_ENTRY(KiSystemStartup, SsFrameLength, ra)
  78. ALTERNATE_ENTRY(KiStartProcessor)
  79. lda sp, -SsFrameLength(sp) // allocate stack frame
  80. stq ra, SsRa(sp) // save return address
  81. PROLOGUE_END
  82. //
  83. // Save the loader block address in a register that is preserved during
  84. // the pal swap.
  85. //
  86. ldl s0, LpbPcrPage(a0) // get PCR page frame number
  87. LDIP s1, KSEG0_BASE // get kseg0 base address
  88. bis a0, zero, s2 //
  89. ldl s3, LpbPdrPage(s2) // get pdr page number
  90. sll s3, PAGE_SHIFT, s3 // compute virtual address of PDR
  91. bis s3, s1, s3 //
  92. //
  93. // Swap PAL code and enter the kernel initialization routine.
  94. //
  95. // a0 - Physical base address of PAL.
  96. // a1 - Page frame number of PCR.
  97. // a2 - The virtual address of the PDR (AXP64 systems only).
  98. // ra - Return address from PAL call.
  99. //
  100. LDP a0, LpbPalBaseAddress(s2) // get PAL base address
  101. sll a0, 32 + 3, a0 // clear upper address bits
  102. srl a0, 32 + 3, a0 //
  103. bis s0, zero, a1 // set PCR page frame number
  104. bis s3, zero, a2 // set level 1 page directory address
  105. lda ra, KiStartupContinue // set return address
  106. SWPPAL // swap PAL images
  107. //
  108. // Control should never get here!
  109. //
  110. ldq ra, SsRa(sp) // Restore ra
  111. lda sp, SsFrameLength(sp) // Restore stack pointer
  112. ret zero, (ra) // shouldn't get here
  113. .end KiSystemStartup
  114. SBTTL( "Startup Continue" )
  115. //++
  116. //
  117. // Routine Description:
  118. //
  119. // This routine is called when NT begins execution after loading the
  120. // Kernel environment from the PAL. It registers exception routines
  121. // and system values with the pal code, calls kernel initialization
  122. // and falls into the idle thread code.
  123. //
  124. // Arguments:
  125. //
  126. // s0 - Supplies the PCR page frame number.
  127. //
  128. // s1 - Supplies the base address of KSEG0.
  129. //
  130. // s2 - Supplies a pointer to the loader parameter block.
  131. //
  132. // s3 - Supplies the virtual address of the PDR.
  133. //
  134. // Return Value:
  135. //
  136. // None.
  137. //
  138. //--
  139. LEAF_ENTRY(KiStartupContinue)
  140. //
  141. // Set kernel stack pointer and kernel global pointer from loader
  142. // parameter block.
  143. //
  144. LDP sp, LpbKernelStack(s2) // set kernel stack pointer
  145. LDP gp, LpbGpBase(s2) // set kernel global pointer
  146. //
  147. // Initialize PAL values, sp, gp, pcr, pdr, initial thread.
  148. //
  149. // sp - Kernel stack pointer.
  150. // gp - System global pointer.
  151. // a0 - Page directory (PDR) address.
  152. // a1 - Idle thread address.
  153. // a2 - Idle thread Teb address.
  154. // a3 - Panic stack address.
  155. // a4 - Maximum kernel stack allocation size.
  156. //
  157. bis s3, zero, a0 // set level 1 page directory address
  158. LDP a1, LpbThread(s2) // get idle thread address
  159. bis zero, zero, a2 // zero Teb for initial thread
  160. LDP a3, LpbPanicStack(s2) // get panic stack base
  161. ldil a4, TotalFrameLength // set maximum kernel stack size
  162. INITIALIZE_PAL
  163. //
  164. // Save copies of the per processor values in global variables for
  165. // uniprocessor systems.
  166. //
  167. sll s0, PAGE_SHIFT, s0 // compute physical address of pcr
  168. bis s0, s1, s0 // compute address of pcr
  169. #ifdef NT_UP
  170. lda t0, KiPcrBaseAddress // save PCR address
  171. STP s0, 0(t0) //
  172. LDP t1, LpbThread(s2) // get idle thread address
  173. lda t0, KiCurrentThread // save idle thread address
  174. STP t1, 0(t0) //
  175. #endif //NT_UP
  176. #if 0
  177. lda a0, BdSystemName // set system name address
  178. bis zero, zero, a1 // set system base address
  179. lda a2, BdDebugOptions // set debug options address
  180. bsr ra, BdInitDebugger // initialize special debugger
  181. bsr ra, DbgBreakPoint // break into debugger
  182. #endif
  183. //
  184. // Register kernel exception entry points with the PALcode.
  185. //
  186. lda a0, KiPanicException // bugcheck entry point
  187. ldil a1, entryBugCheck //
  188. WRITE_KERNEL_ENTRY_POINT //
  189. lda a0, KiGeneralException // general exception entry point
  190. ldil a1, entryGeneral //
  191. WRITE_KERNEL_ENTRY_POINT //
  192. lda a0, KiMemoryManagementException // memory mgmt exception entry
  193. ldil a1, entryMM //
  194. WRITE_KERNEL_ENTRY_POINT //
  195. lda a0, KiInterruptException // interrupt exception entry point
  196. ldil a1, entryInterrupt //
  197. WRITE_KERNEL_ENTRY_POINT //
  198. lda a0, KiSystemServiceException // syscall entry point
  199. ldil a1, entrySyscall //
  200. WRITE_KERNEL_ENTRY_POINT //
  201. //
  202. // Initialize fields in the pcr.
  203. //
  204. ldil t1, PCR_MINOR_VERSION // get minor version
  205. ldil t2, PCR_MAJOR_VERSION // get major version
  206. stl t1, PcMinorVersion(s0) // store minor version number
  207. stl t2, PcMajorVersion(s0) // store major version number
  208. LDP t0, LpbThread(s2) // save idle thread in pcr
  209. STP t0, PcIdleThread(s0) //
  210. LDP t0, LpbPanicStack(s2) // save panic stack in pcr
  211. STP t0, PcPanicStack(s0) //
  212. ldl t0, LpbProcessorType(s2) // save processor type in pcr
  213. stl t0, PcProcessorType(s0) //
  214. ldl t0, LpbProcessorRevision(s2) // save processor revision
  215. stl t0, PcProcessorRevision(s0) //
  216. ldl t0, LpbPhysicalAddressBits(s2) // save physical address bits
  217. stl t0, PcPhysicalAddressBits(s0) //
  218. ldl t0, LpbMaximumAddressSpaceNumber(s2) // save max asn
  219. stl t0, PcMaximumAddressSpaceNumber(s0) //
  220. ldl t0, LpbFirstLevelDcacheSize(s2) // save first level dcache size
  221. stl t0, PcFirstLevelDcacheSize(s0) //
  222. ldl t0, LpbFirstLevelDcacheFillSize(s2) // save dcache fill size
  223. stl t0, PcFirstLevelDcacheFillSize(s0) //
  224. ldl t0, LpbFirstLevelIcacheSize(s2) // save first level icache size
  225. stl t0, PcFirstLevelIcacheSize(s0) //
  226. ldl t0, LpbFirstLevelIcacheFillSize(s2) // save icache fill size
  227. stl t0, PcFirstLevelIcacheFillSize(s0) //
  228. ldl t0, LpbSystemType(s2) // save system type
  229. stl t0, PcSystemType(s0) //
  230. ldl t0, LpbSystemType+4(s2) //
  231. stl t0, PcSystemType+4(s0) //
  232. ldl t0, LpbSystemVariant(s2) // save system variant
  233. stl t0, PcSystemVariant(s0) //
  234. ldl t0, LpbSystemRevision(s2) // save system revision
  235. stl t0, PcSystemRevision(s0) //
  236. ldl t0, LpbSystemSerialNumber(s2) // save system serial number
  237. stl t0, PcSystemSerialNumber(s0) //
  238. ldl t0, LpbSystemSerialNumber+4(s2) //
  239. stl t0, PcSystemSerialNumber+4(s0) //
  240. ldl t0, LpbSystemSerialNumber+8(s2) //
  241. stl t0, PcSystemSerialNumber+8(s0) //
  242. ldl t0, LpbSystemSerialNumber+12(s2) //
  243. stl t0, PcSystemSerialNumber+12(s0) //
  244. ldl t0, LpbCycleClockPeriod(s2) // save cycle counter period
  245. stl t0, PcCycleClockPeriod(s0) //
  246. LDP t0, LpbRestartBlock(s2) // save Restart Block address
  247. STP t0, PcRestartBlock(s0) //
  248. ldq t0, LpbFirmwareRestartAddress(s2) // save firmware restart
  249. stq t0, PcFirmwareRestartAddress(s0) //
  250. ldl t0, LpbFirmwareRevisionId(s2) // save firmware revision
  251. stl t0, PcFirmwareRevisionId(s0) //
  252. LDP t0, LpbDpcStack(s2) // save Dpc Stack address
  253. STP t0, PcDpcStack(s0) //
  254. LDP t0, LpbPrcb(s2) // save Prcb address
  255. STP t0, PcPrcb(s0) //
  256. stl zero, PbDpcRoutineActive(t0) // clear DPC Active flag
  257. stl zero, PcMachineCheckError(s0) // indicate no HAL mchk handler
  258. //
  259. // Set system service dispatch address limits used by get and set context.
  260. //
  261. lda t0, KiSystemServiceDispatchStart // set start address of range
  262. STP t0, PcSystemServiceDispatchStart(s0) //
  263. lda t0, KiSystemServiceDispatchEnd // set end address of range
  264. STP t0, PcSystemServiceDispatchEnd(s0) //
  265. //
  266. // Initialize the system.
  267. //
  268. LDP a0, LpbProcess(s2) // get idle process address
  269. LDP a1, LpbThread(s2) // get idle thread address
  270. bis a1, zero, s1 // save idle thread address
  271. LDP a2, LpbKernelStack(s2) // get idle thread stack
  272. LDP a3, LpbPrcb(s2) // get processor block address
  273. bis a3, zero, s0 // save processor block address
  274. LoadByte(a4, PbNumber(a3)) // get processor number
  275. bis s2, zero, a5 // get loader parameter block
  276. bsr ra, KiInitializeKernel // initialize system data
  277. //
  278. // Set the wait IRQL of the idle thread, and lower IRQL to DISPATCH_LEVEL.
  279. //
  280. ldil a0, DISPATCH_LEVEL // get dispatch level IRQL
  281. StoreByte(a0, ThWaitIrql(s1)) // set wait IRQL of idle thread
  282. bsr ra, KeLowerIrql // lower IRQL
  283. ENABLE_INTERRUPTS // enable interrupts
  284. bis zero, zero, ra // set bogus RA to stop debugger
  285. br zero, KiIdleLoop // continue in idle loop
  286. .end KiStartupContinue
  287. //
  288. // The following code represents the idle loop for all processors. The idle
  289. // loop executes at DISPATCH_LEVEL and continually polls for work.
  290. //
  291. NESTED_ENTRY(KiIdleLoop, ExceptionFrameLength, zero)
  292. lda sp, -ExceptionFrameLength(sp) // allocate context frame
  293. stq ra, ExIntRa(sp) // set bogus RA to stop debugger
  294. PROLOGUE_END
  295. lda t0, KiIdleReturn // set swap context return address
  296. stq t0, ExSwapReturn(sp) //
  297. //
  298. // Lower IRQL back to DISPATCH_LEVEL and restore global register values.
  299. //
  300. // N.B. The address of the current processor block (s0) is preserved across
  301. // the switch from idle call.
  302. //
  303. KiIdleReturn: //
  304. ldil a0, DISPATCH_LEVEL // set IRQL to dispatch level
  305. SWAP_IRQL //
  306. #if DBG
  307. bis zero, zero, s2 // reset breakin loop counter
  308. #endif
  309. lda s3, PbDpcListHead(s0) // get DPC listhead address
  310. #if !defined(NT_UP)
  311. ldil s4, LockQueueDispatcherLock * 2 // compute per processor
  312. SPADDP s4, s0, s4 // lock queue entry address
  313. lda s4, PbLockQueue(s4) //
  314. lda s5, KiDispatcherLock // get address of dispatcher lock
  315. #endif
  316. //
  317. // Continually scan for debugger break in, a nonempty DPC list, or a new
  318. // thread ready for execution.
  319. //
  320. IdleLoop: //
  321. #if DBG
  322. subl s2, 1, s2 // decrement breakin loop counter
  323. bge s2, 5f // if ge, not time for breakin check
  324. ldil s2, 200 * 1000 // set breakin loop counter
  325. bsr ra, KdPollBreakIn // check if breakin is requested
  326. beq v0, 5f // if eq, then no breakin requested
  327. lda a0, DBG_STATUS_CONTROL_C //
  328. bsr ra, DbgBreakPointWithStatus //
  329. 5: //
  330. #endif //DBG
  331. //
  332. // Disable interrupts and check if there is any work in the DPC list
  333. // of the current processor or a target processor.
  334. //
  335. CheckDpcList: //
  336. ENABLE_INTERRUPTS // give interrupts a chance
  337. DISABLE_INTERRUPTS // to interrupt spinning
  338. //
  339. // Process the deferred procedure call list for the current processor.
  340. //
  341. ldl t0, PbDpcQueueDepth(s0) // get current queue depth
  342. beq t0, CheckNextThread // if eq, DPC list is empty
  343. //
  344. // Clear dispatch interrupt.
  345. //
  346. ldil a0, DISPATCH_LEVEL //clear any pending software interrupts
  347. ldl t0, PbSoftwareInterrupts(s0) //
  348. bic t0, a0, t1
  349. stl t1, PbSoftwareInterrupts(s0) //
  350. DEASSERT_SOFTWARE_INTERRUPT // clear any PAL-requested interrupts.
  351. bsr ra, KiRetireDpcList // process the DPC list
  352. #if DBG
  353. bis zero, zero, s2 // clear breakin loop counter
  354. #endif
  355. //
  356. // Check if a thread has been selected to run on this processor.
  357. //
  358. CheckNextThread: //
  359. LDP a0, PbNextThread(s0) // get address of next thread object
  360. beq a0, IdleProcessor // if eq, no thread selected
  361. //
  362. // A thread has been selected for execution on this processor. Acquire
  363. // dispatcher database lock, get the thread address again (it may have
  364. // changed), clear the address of the next thread in the processor block,
  365. // and call swap context to start execution of the selected thread.
  366. //
  367. // N.B. If the dispatcher database lock cannot be obtained immediately,
  368. // then attempt to process another DPC rather than spinning on the
  369. // dispatcher database lock.
  370. //
  371. // N.B. This is a very special acquire of the dispatcher lock in that it
  372. // will not be acquired unless it is free. Therefore, it is known
  373. // that there cannot be any queued lock requests.
  374. //
  375. #if !defined(NT_UP)
  376. 130: LDP_L t0, 0(s5) // get current lock value
  377. bis s4, zero, t1 // set lock ownership value
  378. bne t0, CheckDpcList // if ne, spin lock owned
  379. STP_C t1, 0(s5) // set spin lock owned
  380. beq t1, 135f // if eq, store conditional failed
  381. mb // synchronize reads after acquire
  382. bis s5, LOCK_QUEUE_OWNER, t0 // set lock owner bit in lock entry
  383. STP t0, LqLock(s4) //
  384. #endif
  385. //
  386. // Raise IRQL to sync level and re-enable interrupts
  387. //
  388. ldl a0, KiSynchIrql //
  389. SWAP_IRQL //
  390. ENABLE_INTERRUPTS //
  391. LDP s2, PbNextThread(s0) // get address of next thread
  392. LDP s1, PbIdleThread(s0) // get address of current thread
  393. STP zero, PbNextThread(s0) // clear next thread address
  394. STP s2, PbCurrentThread(s0) // set address of current thread
  395. //
  396. // Set new thread's state to running. Note this must be done under the
  397. // dispatcher lock so that KiSetPriorityThread sees the correct state.
  398. //
  399. ldil t0, Running // set thread state to running
  400. StoreByte(t0, ThState(s2)) //
  401. //
  402. // Acquire the context swap lock so the address space of the old thread
  403. // cannot be deleted and then release the dispatcher database lock. In
  404. // this case the old thread is the idle thread, but the context swap code
  405. // releases the context swap lock so it must be acquired.
  406. //
  407. // N.B. This lock is used to protect the address space until the context
  408. // switch has sufficiently progressed to the point where the address
  409. // space is no longer needed. This lock is also acquired by the reaper
  410. // thread before it finishes thread termination.
  411. //
  412. #if !defined(NT_UP)
  413. ldil a0, LockQueueContextSwapLock * 2 // compute per processor
  414. SPADDP a0, s0, a0 // lock queue entry address
  415. lda a0, PbLockQueue(a0) //
  416. bsr ra, KeAcquireQueuedSpinLockAtDpcLevel // acquire context swap lock
  417. bis s4, zero, a0 // set lock queue endtry address
  418. bsr ra, KeReleaseQueuedSpinLockFromDpcLevel // release dispatcher lock
  419. #endif
  420. //
  421. // Swap context to the new thread from the idle thread.
  422. //
  423. // N.B. Control returns directly from this call to the top of the idle
  424. // loop.
  425. //
  426. bsr ra, SwapFromIdle // swap context to new thread
  427. br zero, KiIdleReturn // control should not reach here
  428. //
  429. // There are no entries in the DPC list and a thread has not been selected
  430. // for execution on this processor. Call the HAL so power management can
  431. // be performed.
  432. //
  433. // N.B. The HAL is called with interrupts disabled. The HAL will return
  434. // with interrupts enabled.
  435. //
  436. IdleProcessor: //
  437. lda ra, IdleLoop // set return address
  438. lda a0, PbPowerState(s0) // Get the Pointer to the current
  439. // C State Handler and Jump to it.
  440. // The Handler that gets called expects
  441. // A0 to contain the PState pointer.
  442. LDP t0, PpIdleFunction(a0)
  443. jmp zero, (t0) //
  444. //
  445. // Conditional store of dispatcher lock failed. Retry. Do not spin in cache
  446. // here. If the lock is owned, we want to check the DPC list again.
  447. //
  448. #if !defined(NT_UP)
  449. 135: ENABLE_INTERRUPTS // enable interrupts
  450. DISABLE_INTERRUPTS // disable interrupts
  451. br zero, 130b // try again
  452. #endif
  453. .end KiIdleLoop
  454. SBTTL("Retire Deferred Procedure Call List")
  455. //++
  456. //
  457. // Routine Description:
  458. //
  459. // This routine is called to retire the specified deferred procedure
  460. // call list.
  461. //
  462. // N.B. Interrupts must be disabled entry to this routine. Control is
  463. // returned to the caller with the same conditions true.
  464. //
  465. // Arguments:
  466. //
  467. // s0 - Address of the processor control block.
  468. //
  469. // Return value:
  470. //
  471. // None.
  472. //
  473. //--
  474. .struct 0
  475. DpRa: .space 8 // return address
  476. .space 8 // fill
  477. DpcFrameLength: // frame length
  478. NESTED_ENTRY(KiRetireDpcList, DpcFrameLength, zero)
  479. lda sp, -DpcFrameLength(sp) // allocate stack frame
  480. stq ra, DpRa(sp) // save return address
  481. PROLOGUE_END
  482. //
  483. // Process the DPC list.
  484. //
  485. 10: ldl t0, PbDpcQueueDepth(s0) // get current DPC queue depth
  486. beq t0, 60f // if eq, list is empty
  487. 15: stl t0, PbDpcRoutineActive(s0) // set DPC routine active
  488. lda t2, PbDpcListHead(s0) // compute DPC list head address
  489. #if !defined(NT_UP)
  490. 20: LDP_L t1, PbDpcLock(s0) // get current lock value
  491. bis s0, zero, t3 // set lock ownership value
  492. bne t1, 25f // if ne, spin lock owned
  493. STP_C t3, PbDpcLock(s0) // set spin lock owned
  494. beq t3, 25f // if eq, store conditional failed
  495. mb // synchronize memory access
  496. ldl t0, PbDpcQueueDepth(s0) // get current DPC queue depth
  497. beq t0, 50f // if eq, DPC list is empty
  498. #endif
  499. LDP a0, LsFlink(t2) // get address of next entry
  500. LDP t1, LsFlink(a0) // get address of next entry
  501. lda a0, -DpDpcListEntry(a0) // compute address of DPC object
  502. STP t1, LsFlink(t2) // set address of next in header
  503. STP t2, LsBlink(t1) // set address of previous in next
  504. LDP a1, DpDeferredContext(a0) // get deferred context argument
  505. LDP a2, DpSystemArgument1(a0) // get first system argument
  506. LDP a3, DpSystemArgument2(a0) // get second system argument
  507. LDP t1, DpDeferredRoutine(a0) // get deferred routine address
  508. STP zero, DpLock(a0) // clear DPC inserted state
  509. subl t0, 1, t0 // decrement DPC queue depth
  510. stl t0, PbDpcQueueDepth(s0) // update DPC queue depth
  511. #if DBG
  512. stl zero, PbDebugDpcTime(s0) // clear the time spent in dpc
  513. #endif
  514. #if !defined(NT_UP)
  515. mb // synchronize previous writes
  516. STP zero, PbDpcLock(s0) // set spinlock not owned
  517. #endif
  518. ENABLE_INTERRUPTS // enable interrupts
  519. jsr ra, (t1) // call DPC routine
  520. DISABLE_INTERRUPTS // disable interrupts
  521. br zero, 10b //
  522. //
  523. // Unlock DPC list and clear DPC active.
  524. //
  525. 50: //
  526. #if !defined(NT_UP)
  527. mb // synchronize previous writes
  528. STP zero, PbDpcLock(s0) // set spin lock not owned
  529. #endif
  530. 60: stl zero, PbDpcRoutineActive(s0) // clear DPC routine active
  531. stl zero, PbDpcInterruptRequested(s0) // clear DPC interrupt requested
  532. //
  533. // Check one last time that the DPC list is empty. This is required to
  534. // close a race condition with the DPC queuing code where it appears that
  535. // a DPC routine is active (and thus an interrupt is not requested), but
  536. // this code has decided the DPC list is empty and is clearing the DPC
  537. // active flag.
  538. //
  539. #if !defined(NT_UP)
  540. mb //
  541. #endif
  542. ldl t0, PbDpcQueueDepth(s0) // get current DPC queue depth
  543. bne t0, 65f // if ne, DPC list not empty
  544. ldq ra, DpRa(sp) // restore return address
  545. lda sp, DpcFrameLength(sp) // deallocate stack frame
  546. ret zero, (ra) // return
  547. 65: br zero, 15b //
  548. #if !defined(NT_UP)
  549. 25: LDP t1, PbDpcLock(s0) // spin in cache until lock free
  550. beq t1, 20b // retry spinlock
  551. br zero, 25b //
  552. #endif
  553. .end KiRetireDpcList
  554. #if 0
  555. SBTTL("Initialize Traps")
  556. //++
  557. //
  558. // Routine Description:
  559. //
  560. // This function connects the PAL code to the boot debugger trap
  561. // routines.
  562. //
  563. // Arguments:
  564. //
  565. // None.
  566. //
  567. // Return Value:
  568. //
  569. // None.
  570. //
  571. //--
  572. NESTED_ENTRY(BdInitializeTraps, 8, ra)
  573. lda sp, -8(sp) // allocate stack frame
  574. stq ra, 0(sp) // save return address
  575. lda a0, BdGeneralException // general exception entry point
  576. ldil a1, entryGeneral //
  577. WRITE_KERNEL_ENTRY_POINT //
  578. lda a0, BdMemoryManagementException // memory mgmt exception entry
  579. ldil a1, entryMM //
  580. WRITE_KERNEL_ENTRY_POINT //
  581. ldq ra, 0(sp) // restore return address
  582. lda sp, 8(sp) // deallocate stack frame
  583. ret zero, (ra) // return
  584. .end BdInitializeTraps
  585. SBTTL("General Exception Dispatch")
  586. //++
  587. //
  588. // Routine Description:
  589. //
  590. // The following code is never executed. Its purpose is to allow the
  591. // kernel debugger to walk call frames backwards through an exception
  592. // to support unwinding through exceptions for system services, and to
  593. // support get/set user context.
  594. //
  595. // N.B. The volatile registers must be saved in this prologue because
  596. // the compiler will occasionally generate code that uses volatile
  597. // registers to save the contents of nonvolatile registers when
  598. // a function only calls another function with a known register
  599. // signature (such as _OtsDivide).
  600. //
  601. //--
  602. NESTED_ENTRY(BdGeneralExceptionDispatch, TrapFrameLength, zero)
  603. .set noreorder
  604. stq sp, TrIntSp(sp) // save stack pointer
  605. stq ra, TrIntRa(sp) // save return address
  606. stq ra, TrFir(sp) // save return address
  607. stq fp, TrIntFp(sp) // save frame pointer
  608. stq gp, TrIntGp(sp) // save global pointer
  609. bis sp, sp, fp // set frame pointer
  610. .set reorder
  611. stq v0, TrIntV0(sp) // save integer register v0
  612. stq t0, TrIntT0(sp) // save integer registers t0 - t7
  613. stq t1, TrIntT1(sp) //
  614. stq t2, TrIntT2(sp) //
  615. stq t3, TrIntT3(sp) //
  616. stq t4, TrIntT4(sp) //
  617. stq t5, TrIntT5(sp) //
  618. stq t6, TrIntT6(sp) //
  619. stq t7, TrIntT7(sp) //
  620. stq a4, TrIntA4(sp) // save integer registers a4 - a5
  621. stq a5, TrIntA5(sp) //
  622. stq t8, TrIntT8(sp) // save integer registers t8 - t12
  623. stq t9, TrIntT9(sp) //
  624. stq t10, TrIntT10(sp) //
  625. stq t11, TrIntT11(sp) //
  626. stq t12, TrIntT12(sp) //
  627. .set noat
  628. stq AT, TrIntAt(sp) // save integer register AT
  629. .set at
  630. PROLOGUE_END
  631. //++
  632. //
  633. // Routine Description:
  634. //
  635. // PALcode dispatches to this kernel entry point when a "general"
  636. // exception occurs. These general exceptions are any exception
  637. // other than an interrupt, system service call or memory management
  638. // fault. The types of exceptions that will dispatch through this
  639. // routine will be: breakpoints, unaligned accesses, machine check
  640. // errors, illegal instruction exceptions, and arithmetic exceptions.
  641. // The purpose of this routine is to save the volatile state and
  642. // enter the common exception dispatch code.
  643. //
  644. // Arguments:
  645. //
  646. // fp - Supplies a pointer to the trap frame.
  647. // gp - Supplies a pointer to the system short data area.
  648. // sp - Supplies a pointer to the trap frame.
  649. // a0 = Supplies a pointer to the exception record.
  650. // a3 = Supplies the previous psr.
  651. //
  652. // Note: Control registers, ra, sp, fp, gp have already been saved
  653. // argument registers a0-a3 have been saved as well
  654. //
  655. //--
  656. ALTERNATE_ENTRY(BdGeneralException)
  657. bsr ra, KiGenerateTrapFrame // store volatile state
  658. br ra, BdExceptionDispatch // handle the exception
  659. .end BdGeneralExceptionDispatch
  660. SBTTL("Exception Dispatch")
  661. //++
  662. //
  663. // Routine Description:
  664. //
  665. // This routine begins the common code for raising an exception.
  666. // The routine saves the non-volatile state and dispatches to the
  667. // next level exception dispatcher.
  668. //
  669. // Arguments:
  670. //
  671. // fp - Supplies a pointer to the trap frame.
  672. // sp - Supplies a pointer to the trap frame.
  673. // a0 = Supplies a pointer to the exception record.
  674. // a3 = Supplies the previous psr.
  675. //
  676. // gp, ra - saved in trap frame
  677. // a0-a3 - saved in trap frame
  678. //
  679. // Return Value:
  680. //
  681. // None.
  682. //
  683. //--
  684. NESTED_ENTRY(BdExceptionDispatch, ExceptionFrameLength, zero )
  685. //
  686. // Build exception frame
  687. //
  688. lda sp, -ExceptionFrameLength(sp) // allocate exception frame
  689. stq ra, ExIntRa(sp) // save ra
  690. stq s0, ExIntS0(sp) // save integer registers s0 - s5
  691. stq s1, ExIntS1(sp) //
  692. stq s2, ExIntS2(sp) //
  693. stq s3, ExIntS3(sp) //
  694. stq s4, ExIntS4(sp) //
  695. stq s5, ExIntS5(sp) //
  696. stt f2, ExFltF2(sp) // save floating registers f2 - f9
  697. stt f3, ExFltF3(sp) //
  698. stt f4, ExFltF4(sp) //
  699. stt f5, ExFltF5(sp) //
  700. stt f6, ExFltF6(sp) //
  701. stt f7, ExFltF7(sp) //
  702. stt f8, ExFltF8(sp) //
  703. stt f9, ExFltF9(sp) //
  704. PROLOGUE_END
  705. ldil a4, TRUE // first chance to true
  706. bis zero, zero, a3 // set previous mode
  707. bis fp, zero, a2 // set pointer to trap frame
  708. bis sp, zero, a1 // set pointer to exception frame
  709. lda a0, TrExceptionRecord(fp) // set address of exception record
  710. LDP t0, BdDebugRoutine // get address of debug routine
  711. jsr ra, (t0) // call kernel debugger
  712. ldq s0, ExIntS0(sp) // restore integer registers s0 - s5
  713. ldq s1, ExIntS1(sp) //
  714. ldq s2, ExIntS2(sp) //
  715. ldq s3, ExIntS3(sp) //
  716. ldq s4, ExIntS4(sp) //
  717. ldq s5, ExIntS5(sp) //
  718. ldl a0, TrPsr(fp) // get previous psr
  719. bsr ra, KiRestoreNonVolatileFloatState // restore nv float state
  720. bsr ra, KiRestoreTrapFrame // restore volatile state
  721. bis zero, zero, a1 // assume softwareinterrupt requested
  722. //
  723. // a0 = previous psr
  724. // a1 = sfw interrupt requests
  725. //
  726. RETURN_FROM_TRAP_OR_INTERRUPT // return from exception
  727. .end BdExceptionDispatch
  728. SBTTL("Memory Management Exception Dispatch")
  729. //++
  730. //
  731. // Routine Description:
  732. //
  733. // The following code is never executed. Its purpose is to allow the
  734. // kernel debugger to walk call frames backwards through an exception
  735. // to support unwinding through exceptions for system services, and to
  736. // support get/set user context.
  737. //
  738. // N.B. The volatile registers must be saved in this prologue because
  739. // the compiler will occasionally generate code that uses volatile
  740. // registers to save the contents of nonvolatile registers when
  741. // a function only calls another function with a known register
  742. // signature (such as _OtsMove).
  743. //
  744. //--
  745. NESTED_ENTRY(BdMemoryManagementDispatch, TrapFrameLength, zero)
  746. .set noreorder
  747. stq sp, TrIntSp(sp) // save stack pointer
  748. stq ra, TrIntRa(sp) // save return address
  749. stq ra, TrFir(sp) // save return address
  750. stq fp, TrIntFp(sp) // save frame pointer
  751. stq gp, TrIntGp(sp) // save global pointer
  752. bis sp, sp, fp // set frame pointer
  753. .set reorder
  754. stq v0, TrIntV0(sp) // save integer register v0
  755. stq t0, TrIntT0(sp) // save integer registers t0 - t7
  756. stq t1, TrIntT1(sp) //
  757. stq t2, TrIntT2(sp) //
  758. stq t3, TrIntT3(sp) //
  759. stq t4, TrIntT4(sp) //
  760. stq t5, TrIntT5(sp) //
  761. stq t6, TrIntT6(sp) //
  762. stq t7, TrIntT7(sp) //
  763. stq a4, TrIntA4(sp) // save integer registers a4 - a5
  764. stq a5, TrIntA5(sp) //
  765. stq t8, TrIntT8(sp) // save integer registers t8 - t12
  766. stq t9, TrIntT9(sp) //
  767. stq t10, TrIntT10(sp) //
  768. stq t11, TrIntT11(sp) //
  769. stq t12, TrIntT12(sp) //
  770. .set noat
  771. stq AT, TrIntAt(sp) // save integer register AT
  772. .set at
  773. PROLOGUE_END
  774. //++
  775. //
  776. // Routine Description:
  777. //
  778. // This routine is called from the PALcode when a translation not valid
  779. // fault or an access violation is encountered. This routine will
  780. // call MmAccessFault to attempt to resolve the fault. If the fault
  781. // cannot be resolved then the routine will dispatch to the exception
  782. // dispatcher so the exception can be raised.
  783. //
  784. // Arguments:
  785. //
  786. // fp - Supplies a pointer to the trap frame.
  787. // gp - Supplies a pointer to the system short data area.
  788. // sp - Supplies a pointer to the trap frame.
  789. // a0 = Supplies the load/store indicator, 1 = store, 0 = load.
  790. // a1 = Supplies the bad virtual address.
  791. // a2 = Supplies the previous mode.
  792. // a3 = Supplies the previous psr.
  793. //
  794. // gp, ra - saved in trap frame
  795. // a0-a3 - saved in trap frame
  796. //
  797. // Return Value:
  798. //
  799. // None.
  800. //
  801. //--
  802. ALTERNATE_ENTRY(BdMemoryManagementException)
  803. bsr ra, KiGenerateTrapFrame // store volatile state
  804. STP a0, TrExceptionRecord + ErExceptionInformation(fp) // set load/store
  805. #if defined(_AXP64_)
  806. stq a1, TrExceptionRecord + ErExceptionInformation + 8(fp) // set bad va
  807. #else
  808. stl a1, TrExceptionRecord + ErExceptionInformation + 4(fp) // set bad va
  809. #endif
  810. lda a0, TrExceptionRecord(fp) // get exception record address
  811. ldil v0, STATUS_ACCESS_VIOLATION // get access violation code
  812. stl v0, ErExceptionCode(a0) // save exception code
  813. stl zero, ErExceptionFlags(a0) // set exception flags
  814. STP zero, ErExceptionRecord(a0) // set associated record
  815. bis zero, 2, t0 // set number of parameters
  816. stl t0, ErNumberParameters(a0) // set number of parameters
  817. br ra, BdExceptionDispatch // dispatch exception
  818. .end BdMemoryManagementDispatch
  819. #endif