prochw.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. /*++
  2. Copyright (c) 2012 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. prochw.c
  9. Abstract:
  10. This module implements support functionality for hardware that is specific
  11. to the ARM architecture.
  12. Author:
  13. Evan Green 11-Aug-2012
  14. Environment:
  15. Kernel
  16. --*/
  17. //
  18. // ------------------------------------------------------------------- Includes
  19. //
  20. #include <minoca/kernel/kernel.h>
  21. #include <minoca/kernel/arm.h>
  22. //
  23. // ---------------------------------------------------------------- Definitions
  24. //
  25. //
  26. // ----------------------------------------------- Internal Function Prototypes
  27. //
  28. VOID
  29. ArpInitializeInterrupts (
  30. BOOL PhysicalMode,
  31. BOOL BootProcessor,
  32. PVOID Idt
  33. );
  34. VOID
  35. ArpSetProcessorFeatures (
  36. PPROCESSOR_BLOCK ProcessorBlock
  37. );
  38. //
  39. // ------------------------------------------------------ Data Type Definitions
  40. //
  41. //
  42. // -------------------------------------------------------------------- Globals
  43. //
  44. //
  45. // Store globals for the per-processor data structures used by P0.
  46. //
  47. PVOID ArP0InterruptTable[MAXIMUM_VECTOR - MINIMUM_VECTOR + 1] = {NULL};
  48. PROCESSOR_BLOCK ArP0ProcessorBlock;
  49. ULONG ArP0ExceptionStacks[EXCEPTION_STACK_COUNT * EXCEPTION_STACK_SIZE];
  50. //
  51. // Remember whether the processor was initialized with translation enabled or
  52. // not.
  53. //
  54. BOOL ArTranslationEnabled = FALSE;
  55. //
  56. // Global containing a partially initialized interrupt table. This table will
  57. // be copied to the real location, either 0 or 0xFFFF0000.
  58. //
  59. extern ARM_INTERRUPT_TABLE ArArmInterruptTable;
  60. //
  61. // ------------------------------------------------------------------ Functions
  62. //
  63. VOID
  64. ArInitializeProcessor (
  65. BOOL PhysicalMode,
  66. PVOID ProcessorStructures
  67. )
  68. /*++
  69. Routine Description:
  70. This routine initializes processor-specific structures.
  71. Arguments:
  72. PhysicalMode - Supplies a boolean indicating whether or not the processor
  73. is operating in physical mode.
  74. ProcessorStructures - Supplies a pointer to the memory to use for basic
  75. processor structures, as returned by the allocate processor structures
  76. routine. For the boot processor, supply NULL here to use this routine's
  77. internal resources.
  78. Return Value:
  79. None.
  80. --*/
  81. {
  82. BOOL BootProcessor;
  83. PVOID ExceptionStacks;
  84. PVOID InterruptTable;
  85. PPROCESSOR_BLOCK ProcessorBlock;
  86. BootProcessor = TRUE;
  87. if (PhysicalMode == FALSE) {
  88. ArTranslationEnabled = TRUE;
  89. }
  90. ExceptionStacks = ArP0ExceptionStacks;
  91. InterruptTable = ArP0InterruptTable;
  92. if (PhysicalMode == FALSE) {
  93. //
  94. // Use the globals if this is the boot processor because the memory
  95. // subsystem is not yet online.
  96. //
  97. if (ProcessorStructures == NULL) {
  98. ProcessorBlock = &ArP0ProcessorBlock;
  99. } else {
  100. BootProcessor = FALSE;
  101. ProcessorBlock = (PPROCESSOR_BLOCK)ProcessorStructures;
  102. ExceptionStacks = (PVOID)(ProcessorBlock + 1);
  103. }
  104. //
  105. // The processor is executing in physical mode.
  106. //
  107. } else {
  108. ProcessorBlock = &ArP0ProcessorBlock;
  109. }
  110. //
  111. // Initialize the exception stacks.
  112. //
  113. ArpInitializeExceptionStacks(ExceptionStacks, EXCEPTION_STACK_SIZE);
  114. //
  115. // Initialize the pointer to the processor block.
  116. //
  117. ProcessorBlock->Self = ProcessorBlock;
  118. ProcessorBlock->InterruptTable = InterruptTable;
  119. ArSetProcessorBlockRegister(ProcessorBlock);
  120. ArpInitializeInterrupts(PhysicalMode, BootProcessor, NULL);
  121. ArpSetProcessorFeatures(ProcessorBlock);
  122. //
  123. // Initialize the performance monitor.
  124. //
  125. ArpInitializePerformanceMonitor();
  126. return;
  127. }
  128. KSTATUS
  129. ArFinishBootProcessorInitialization (
  130. VOID
  131. )
  132. /*++
  133. Routine Description:
  134. This routine performs additional initialization steps for processor 0 that
  135. were put off in pre-debugger initialization.
  136. Arguments:
  137. None.
  138. Return Value:
  139. Status code.
  140. --*/
  141. {
  142. return STATUS_SUCCESS;
  143. }
  144. PVOID
  145. ArAllocateProcessorStructures (
  146. ULONG ProcessorNumber
  147. )
  148. /*++
  149. Routine Description:
  150. This routine attempts to allocate and initialize early structures needed by
  151. a new processor.
  152. Arguments:
  153. ProcessorNumber - Supplies the number of the processor that these resources
  154. will go to.
  155. Return Value:
  156. Returns a pointer to the new processor resources on success.
  157. NULL on failure.
  158. --*/
  159. {
  160. PVOID Allocation;
  161. ULONG AllocationSize;
  162. PPROCESSOR_BLOCK ProcessorBlock;
  163. AllocationSize = sizeof(PROCESSOR_BLOCK) +
  164. (EXCEPTION_STACK_SIZE * EXCEPTION_STACK_COUNT);
  165. Allocation = MmAllocateNonPagedPool(AllocationSize, ARCH_POOL_TAG);
  166. if (Allocation == NULL) {
  167. return NULL;
  168. }
  169. RtlZeroMemory(Allocation, AllocationSize);
  170. ProcessorBlock = (PPROCESSOR_BLOCK)Allocation;
  171. ProcessorBlock->Self = ProcessorBlock;
  172. ProcessorBlock->ProcessorNumber = ProcessorNumber;
  173. return Allocation;
  174. }
  175. VOID
  176. ArFreeProcessorStructures (
  177. PVOID ProcessorStructures
  178. )
  179. /*++
  180. Routine Description:
  181. This routine destroys a set of processor structures that have been
  182. allocated. It should go without saying, but obviously a processor must not
  183. be actively using these resources.
  184. Arguments:
  185. ProcessorStructures - Supplies the pointer returned by the allocation
  186. routine.
  187. Return Value:
  188. None.
  189. --*/
  190. {
  191. MmFreeNonPagedPool(ProcessorStructures);
  192. return;
  193. }
  194. BOOL
  195. ArIsTranslationEnabled (
  196. VOID
  197. )
  198. /*++
  199. Routine Description:
  200. This routine determines if the processor was initialized with virtual-to-
  201. physical address translation enabled or not.
  202. Arguments:
  203. None.
  204. Return Value:
  205. TRUE if the processor is using a layer of translation between CPU accessible
  206. addresses and physical memory.
  207. FALSE if the processor was initialized in physical mode.
  208. --*/
  209. {
  210. return ArTranslationEnabled;
  211. }
  212. ULONG
  213. ArGetIoPortCount (
  214. VOID
  215. )
  216. /*++
  217. Routine Description:
  218. This routine returns the number of I/O port addresses architecturally
  219. available.
  220. Arguments:
  221. None.
  222. Return Value:
  223. Returns the number of I/O port address supported by the architecture.
  224. --*/
  225. {
  226. return IO_PORT_COUNT;
  227. }
  228. ULONG
  229. ArGetInterruptVectorCount (
  230. VOID
  231. )
  232. /*++
  233. Routine Description:
  234. This routine returns the number of interrupt vectors in the system, either
  235. architecturally defined or artificially created.
  236. Arguments:
  237. None.
  238. Return Value:
  239. Returns the number of interrupt vectors in use by the system.
  240. --*/
  241. {
  242. return INTERRUPT_VECTOR_COUNT;
  243. }
  244. ULONG
  245. ArGetMinimumDeviceVector (
  246. VOID
  247. )
  248. /*++
  249. Routine Description:
  250. This routine returns the first interrupt vector that can be used by
  251. devices.
  252. Arguments:
  253. None.
  254. Return Value:
  255. Returns the minimum interrupt vector available for use by devices.
  256. --*/
  257. {
  258. return MINIMUM_VECTOR;
  259. }
  260. ULONG
  261. ArGetMaximumDeviceVector (
  262. VOID
  263. )
  264. /*++
  265. Routine Description:
  266. This routine returns the last interrupt vector that can be used by
  267. devices.
  268. Arguments:
  269. None.
  270. Return Value:
  271. Returns the maximum interrupt vector available for use by devices.
  272. --*/
  273. {
  274. return MAXIMUM_DEVICE_VECTOR;
  275. }
  276. ULONG
  277. ArGetTrapFrameSize (
  278. VOID
  279. )
  280. /*++
  281. Routine Description:
  282. This routine returns the size of the trap frame structure, in bytes.
  283. Arguments:
  284. None.
  285. Return Value:
  286. Returns the size of the trap frame structure, in bytes.
  287. --*/
  288. {
  289. return sizeof(TRAP_FRAME);
  290. }
  291. PVOID
  292. ArGetInstructionPointer (
  293. PTRAP_FRAME TrapFrame
  294. )
  295. /*++
  296. Routine Description:
  297. This routine returns the instruction pointer out of the trap frame.
  298. Arguments:
  299. TrapFrame - Supplies the trap frame from which the instruction pointer
  300. will be returned.
  301. Return Value:
  302. Returns the instruction pointer the trap frame is pointing to.
  303. --*/
  304. {
  305. ULONG Pc;
  306. Pc = TrapFrame->Pc;
  307. if ((TrapFrame->Cpsr & PSR_FLAG_THUMB) != 0) {
  308. Pc |= ARM_THUMB_BIT;
  309. }
  310. return (PVOID)Pc;
  311. }
  312. BOOL
  313. ArIsTrapFrameFromPrivilegedMode (
  314. PTRAP_FRAME TrapFrame
  315. )
  316. /*++
  317. Routine Description:
  318. This routine determines if the given trap frame occurred in a privileged
  319. environment or not.
  320. Arguments:
  321. TrapFrame - Supplies the trap frame.
  322. Return Value:
  323. TRUE if the execution environment of the trap frame is privileged.
  324. FALSE if the execution environment of the trap frame is not privileged.
  325. --*/
  326. {
  327. return IS_TRAP_FRAME_FROM_PRIVILEGED_MODE(TrapFrame);
  328. }
  329. BOOL
  330. ArIsTrapFrameComplete (
  331. PTRAP_FRAME TrapFrame
  332. )
  333. /*++
  334. Routine Description:
  335. This routine determines if the given trap frame contains the full context
  336. or only partial context as saved by the system call handler.
  337. Arguments:
  338. TrapFrame - Supplies the trap frame.
  339. Return Value:
  340. TRUE if the trap frame has all registers filled out.
  341. FALSE if the the trap frame is largely uninitialized as left by the system
  342. call handler.
  343. --*/
  344. {
  345. return IS_TRAP_FRAME_COMPLETE(TrapFrame);
  346. }
  347. //
  348. // --------------------------------------------------------- Internal Functions
  349. //
  350. VOID
  351. ArpInitializeInterrupts (
  352. BOOL PhysicalMode,
  353. BOOL BootProcessor,
  354. PVOID Idt
  355. )
  356. /*++
  357. Routine Description:
  358. This routine initializes and enables interrupts.
  359. Arguments:
  360. PhysicalMode - Supplies a flag indicating that the processor is running
  361. with translation disabled. This is unused on x86.
  362. BootProcessor - Supplies a flag indicating whether this is processor 0 or
  363. an AP.
  364. Idt - Supplies a pointer to the Interrrupt Descriptor Table for this
  365. processor.
  366. Return Value:
  367. None.
  368. --*/
  369. {
  370. ARM_CPUID CpuInformation;
  371. ULONG SystemControl;
  372. if (BootProcessor != FALSE) {
  373. //
  374. // The interrupt table must be 32-byte aligned to make it into VBAR.
  375. //
  376. ASSERT(((UINTN)&ArArmInterruptTable & 0x0000001F) == 0);
  377. }
  378. //
  379. // Get the CPU information to determine if the processor supports security
  380. // extensions. If security extensions are supported, then the interrupt
  381. // table can be remapped to another address using the VBAR register.
  382. //
  383. SystemControl = ArGetSystemControlRegister();
  384. ArCpuid(&CpuInformation);
  385. if ((CpuInformation.ProcessorFeatures[1] &
  386. CPUID_PROCESSOR1_SECURITY_EXTENSION_MASK) !=
  387. CPUID_PROCESSOR1_SECURITY_EXTENSION_UNSUPPORTED) {
  388. //
  389. // Security extensions are supported, so turn off the high vectors and
  390. // set the address using VBAR.
  391. //
  392. SystemControl &= ~MMU_HIGH_EXCEPTION_VECTORS;
  393. ArSetVectorBaseAddress(&ArArmInterruptTable);
  394. //
  395. // Security extensions are not supported, so the vectors will have to go
  396. // at 0 or 0xFFFF0000, as VBAR may not work.
  397. //
  398. } else {
  399. if (PhysicalMode == FALSE) {
  400. //
  401. // If address translation is enabled, copy the vectors to the
  402. // "hivecs" address, and enable high vectors in the system control
  403. // register.
  404. //
  405. RtlCopyMemory((PVOID)EXCEPTION_VECTOR_ADDRESS,
  406. &ArArmInterruptTable,
  407. sizeof(ARM_INTERRUPT_TABLE));
  408. SystemControl |= MMU_HIGH_EXCEPTION_VECTORS;
  409. } else {
  410. //
  411. // In physical mode, copy the exception table over the firmware's,
  412. // whether it be at the low or high address.
  413. //
  414. if ((SystemControl & MMU_HIGH_EXCEPTION_VECTORS) != 0) {
  415. RtlCopyMemory((PVOID)EXCEPTION_VECTOR_ADDRESS,
  416. &ArArmInterruptTable,
  417. sizeof(ARM_INTERRUPT_TABLE));
  418. } else {
  419. RtlCopyMemory((PVOID)EXCEPTION_VECTOR_LOW_ADDRESS,
  420. &ArArmInterruptTable,
  421. sizeof(ARM_INTERRUPT_TABLE));
  422. }
  423. }
  424. }
  425. if ((((UINTN)ArpUndefinedInstructionEntry) & ARM_THUMB_BIT) != 0) {
  426. SystemControl |= MMU_THUMB_EXCEPTIONS;
  427. }
  428. ArSetSystemControlRegister(SystemControl);
  429. return;
  430. }
  431. VOID
  432. ArpSetProcessorFeatures (
  433. PPROCESSOR_BLOCK ProcessorBlock
  434. )
  435. /*++
  436. Routine Description:
  437. This routine reads processor features.
  438. Arguments:
  439. ProcessorBlock - Supplies a pointer to the processor block.
  440. Return Value:
  441. None.
  442. --*/
  443. {
  444. PPROCESSOR_IDENTIFICATION Identification;
  445. ULONG MainId;
  446. MainId = ArGetMainIdRegister();
  447. Identification = &(ProcessorBlock->CpuVersion);
  448. Identification->Vendor = (MainId & ARM_MAIN_ID_IMPLEMENTOR_MASK) >>
  449. ARM_MAIN_ID_IMPLEMENTER_SHIFT;
  450. Identification->Family = (MainId & ARM_MAIN_ID_PART_MASK) >>
  451. ARM_MAIN_ID_PART_SHIFT;
  452. Identification->Model = (MainId & ARM_MAIN_ID_VARIANT_MASK) >>
  453. ARM_MAIN_ID_VARIANT_SHIFT;
  454. Identification->Stepping = MainId & ARM_MAIN_ID_REVISION_MASK;
  455. return;
  456. }