ARM.Initializer.Mod 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. MODULE Initializer;
  2. (**
  3. AUTHOR "Timothée Martiel";
  4. PURPOSE "Processor initialization code for ARM kernel";
  5. This module provides initialization for CPUs. It contains the initial procedure that begins the execution of
  6. the kernel. It also provides a mechanism for starting secondary processors: all processors should start executing
  7. at the beginning of the kernel image (i.e. Init): only CPU with id 0 will continue and start the kernel. The other
  8. processors will be sleeping in Init, waiting to be started later.
  9. *)
  10. IMPORT SYSTEM (* Needed to avoid Runtime importing Heaps *);
  11. VAR
  12. (**
  13. Wakeup address for secondary processors: if set # 0, the CPU with id matching "secondaryProcId" will jump to
  14. that address.
  15. *)
  16. secondaryBootProc *: ADDRESS;
  17. (**
  18. Wakup id for secondary processors: when executing SEV, all CPUs wakup. Only the CPU with id matching this field
  19. will read and jump to "secondaryBootProc".
  20. *)
  21. secondaryProcId *: LONGINT;
  22. (** Configuration string base address *)
  23. configBase *: ADDRESS;
  24. (** Configuration string size *)
  25. configSize *: LONGINT;
  26. (**
  27. Initial kernel code: this code is placed at the beginning of the kernel image and is executed by all CPUs.
  28. This code:
  29. - sets up a stack
  30. - disables interrupts and MMU
  31. - sets the interrupt vector to 0
  32. - invalidates caches
  33. - put secondary processors into the sleeping loop
  34. - allow CPU0 to continue kernel initialization
  35. *)
  36. PROCEDURE {INITIAL,NOPAF} Init;
  37. CODE
  38. ; set IRQ vector base register to zero
  39. MOV R2, #0
  40. MCR P15, 0, R2, C12, C0, 0
  41. ; disable MMU
  42. MRC P15, 0, R2, C1, C0, 0
  43. BIC R2, R2, #1
  44. MCR P15, 0, R2, C1, C0, 0
  45. LDR FP, [pc, #InitialFP-$-8] ; set stack pointer
  46. LDR SP, [pc, #InitialFP-$-8] ; set frame pointer
  47. B getProcId
  48. InitialFP: d32 0001B000H ; initial frame pointer address, internal memory bank
  49. ; Set SMP mode
  50. MRC p15, 0, R2, C1, C0, 1
  51. ORR R2, R2, #041H
  52. MCR p15, 0, R2, C1, C0, 1
  53. ISB
  54. ; Filter CPUs: only CPU0 must initialize the kernel, other are started later on demand
  55. MOV R2, #0
  56. getProcId:
  57. MRC P15, 0, R3, C0, C0, 5
  58. AND R3, R3, #0FH
  59. CMP R3, #0
  60. BEQ bootProc ; CPU 0 continues to booting the kernel
  61. secondaryProcLoop: ; Secondary CPUs (i.e. CPUs that do not start the kernel) are
  62. BL InvalidateDCache
  63. WFE ; sleeping and waiting to be started by SEV.
  64. LDR R0, [PC, #sndProcIdAdr-$-8]
  65. LDR R0, [R0, #0] ; R0 := secondaryProcId
  66. MRC P15, 0, R1, C0, C0, 5
  67. AND R1, R1, #0FH ; R1 := CPU ID
  68. CMP R0, R1 ; IF R1 # R0: loop again
  69. BNE secondaryProcLoop
  70. LDR R0, [PC, #sndBootProcAdr-$-8]
  71. LDR R1, [R0, #0] ; R1 := secondaryBootProc
  72. CMP R1, #0 ; IF R1 = 0: loop again
  73. BEQ secondaryProcLoop
  74. BX R1 ; Jump to secondaryBootProc
  75. sndBootProcAdr: d32 secondaryBootProc
  76. sndProcIdAdr: d32 secondaryProcId
  77. bootProc: ; CPU0 continues executing the kernel image
  78. ; Save configuration parameters
  79. LDR R2, [PC, #CfgBase - 8 - $]
  80. STR R0, [R2, #0]
  81. LDR R2, [PC, #CfgSize - 8 - $]
  82. STR R1, [R2, #0]
  83. BL InvalidateDCache ; After invalidating DCache
  84. ; Setup the interrupt vector: copy it from the data section below
  85. MOV R0, #0 ; R0 := dst
  86. LDR R1, [PC, #intVecAdr - $ - 8] ; R1 := src
  87. MOV R2, #fiq - RESET + 4 ; R2 := LEN(src) in bytes
  88. copyInts:
  89. LDR R4, [R1, #0]
  90. STR R4, [R0, #0]
  91. ADD R0, R0, #4
  92. ADD R1, R1, #4
  93. SUBS R2, R2, #4
  94. BNE copyInts
  95. ; Start the kernel now
  96. B startKernel
  97. ; Interrupt vector data: to install the interrupt vector, we just have to copy
  98. ; from RESET to fiq (included) at address 0.
  99. RESET: LDR PC, [PC, #reset-$-8] ; RESET
  100. UNDEF: LDR PC, [PC, #undef-$-8] ; UNDEF
  101. SWI: LDR PC, [PC, #swi-$-8] ; SWI
  102. PREF: LDR PC, [PC, #prefetch-$-8] ; Prefetch Abort
  103. DATA: LDR PC, [PC, #data-$-8] ; Data Abort
  104. INVALID: B INVALID ; (not assigned)
  105. IRQ: LDR PC, [PC, #irq-$-8] ; IRQ
  106. FIQ: LDR PC, [PC, #fiq-$-8] ; FIQ
  107. ; initial interrupt vector setup such that inifinte loop is triggered
  108. reset: d32 Init ; Reset starts the kernel
  109. undef: d32 04H
  110. swi: d32 08H
  111. prefetch: d32 0CH
  112. data: d32 10H
  113. empty: d32 0
  114. irq: d32 14H
  115. fiq: d32 1CH
  116. ; Address of the interrupt vector data to copy
  117. intVecAdr: d32 RESET
  118. CfgBase: d32 configBase
  119. CfgSize: d32 configSize
  120. startKernel:
  121. END Init;
  122. PROCEDURE {NOPAF} InvalidateDCache *;
  123. CODE
  124. invalidate_dcache:
  125. mrc p15, 1, r0, c0, c0, 1 ; read CLIDR
  126. ands r3, r0, #7000000H
  127. mov r3, r3, lsr #23 ; cache level value (naturally aligned)
  128. beq finished
  129. mov r10, #0 ; start with level 0
  130. loop1:
  131. add r2, r10, r10, lsr #1 ; work out 3xcachelevel
  132. mov r1, r0, lsr r2 ; bottom 3 bits are the Cache type for this level
  133. and r1, r1, #7 ; get those 3 bits alone
  134. cmp r1, #2
  135. blt skip ; no cache or only instruction cache at this level
  136. mcr p15, 2, r10, c0, c0, 0 ; write the Cache Size selection register
  137. isb ; isb to sync the change to the CacheSizeID reg
  138. mrc p15, 1, r1, c0, c0, 0 ; reads current Cache Size ID register
  139. and r2, r1, #7 ; extract the line length field
  140. add r2, r2, #4 ; add 4 for the line length offset (log2 16 bytes)
  141. ldr r4, [pc, #H0x3ff-$-8]
  142. ands r4, r4, r1, lsr #3 ; r4 is the max number on the way size (right aligned)
  143. clz r5, r4 ; r5 is the bit position of the way size increment
  144. ldr r7, [pc, #H0x7fff-$-8]
  145. ands r7, r7, r1, lsr #13 ; r7 is the max number of the index size (right aligned)
  146. loop2:
  147. mov r9, r4 ; r9 working copy of the max way size (right aligned)
  148. loop3:
  149. orr r11, r10, r9, lsl r5 ; factor in the way number and cache number into r11
  150. orr r11, r11, r7, lsl r2 ; factor in the index number
  151. mcr p15, 0, r11, c7, c14, 2 ; clean & invalidate by set/way
  152. subs r9, r9, #1 ; decrement the way number
  153. bge loop3
  154. subs r7, r7, #1 ; decrement the index
  155. bge loop2
  156. skip:
  157. add r10, r10, #2 ; increment the cache number
  158. cmp r3, r10
  159. bgt loop1
  160. finished:
  161. mov r10, #0 ; swith back to cache level 0
  162. mcr p15, 2, r10, c0, c0, 0 ; select current cache level in cssr
  163. dsb ; dsb
  164. isb ; isb
  165. bx lr
  166. H0x3ff: d32 03FFH
  167. H0x7fff: d32 07FFFH
  168. END InvalidateDCache;
  169. END Initializer.
  170. FoxARMInstructionSet.Disassemble A2.Bin -a=100120H ~