head-nommu.S 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * linux/arch/arm/kernel/head-nommu.S
  4. *
  5. * Copyright (C) 1994-2002 Russell King
  6. * Copyright (C) 2003-2006 Hyok S. Choi
  7. *
  8. * Common kernel startup code (non-paged MM)
  9. */
  10. #include <linux/linkage.h>
  11. #include <linux/init.h>
  12. #include <linux/errno.h>
  13. #include <asm/assembler.h>
  14. #include <asm/ptrace.h>
  15. #include <asm/asm-offsets.h>
  16. #include <asm/page.h>
  17. #include <asm/cp15.h>
  18. #include <asm/thread_info.h>
  19. #include <asm/v7m.h>
  20. #include <asm/mpu.h>
  21. /*
  22. * Kernel startup entry point.
  23. * ---------------------------
  24. *
  25. * This is normally called from the decompressor code. The requirements
  26. * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
  27. * r1 = machine nr.
  28. *
  29. * See linux/arch/arm/tools/mach-types for the complete list of machine
  30. * numbers for r1.
  31. *
  32. */
  33. __HEAD
  34. #ifdef CONFIG_CPU_THUMBONLY
  35. .thumb
  36. ENTRY(stext)
  37. #else
  38. .arm
  39. ENTRY(stext)
  40. THUMB( badr r9, 1f ) @ Kernel is always entered in ARM.
  41. THUMB( bx r9 ) @ If this is a Thumb-2 kernel,
  42. THUMB( .thumb ) @ switch to Thumb now.
  43. THUMB(1: )
  44. #endif
  45. #ifdef CONFIG_ARM_VIRT_EXT
  46. bl __hyp_stub_install
  47. #endif
  48. @ ensure svc mode and all interrupts masked
  49. safe_svcmode_maskall r9
  50. @ and irqs disabled
  51. #if defined(CONFIG_CPU_CP15)
  52. mrc p15, 0, r9, c0, c0 @ get processor id
  53. #elif defined(CONFIG_CPU_V7M)
  54. ldr r9, =BASEADDR_V7M_SCB
  55. ldr r9, [r9, V7M_SCB_CPUID]
  56. #else
  57. ldr r9, =CONFIG_PROCESSOR_ID
  58. #endif
  59. bl __lookup_processor_type @ r5=procinfo r9=cpuid
  60. movs r10, r5 @ invalid processor (r5=0)?
  61. beq __error_p @ yes, error 'p'
  62. #ifdef CONFIG_ARM_MPU
  63. bl __setup_mpu
  64. #endif
  65. badr lr, 1f @ return (PIC) address
  66. ldr r12, [r10, #PROCINFO_INITFUNC]
  67. add r12, r12, r10
  68. ret r12
  69. 1: ldr lr, =__mmap_switched
  70. b __after_proc_init
  71. ENDPROC(stext)
  72. #ifdef CONFIG_SMP
  73. .text
  74. ENTRY(secondary_startup)
  75. /*
  76. * Common entry point for secondary CPUs.
  77. *
  78. * Ensure that we're in SVC mode, and IRQs are disabled. Lookup
  79. * the processor type - there is no need to check the machine type
  80. * as it has already been validated by the primary processor.
  81. */
  82. #ifdef CONFIG_ARM_VIRT_EXT
  83. bl __hyp_stub_install_secondary
  84. #endif
  85. safe_svcmode_maskall r9
  86. #ifndef CONFIG_CPU_CP15
  87. ldr r9, =CONFIG_PROCESSOR_ID
  88. #else
  89. mrc p15, 0, r9, c0, c0 @ get processor id
  90. #endif
  91. bl __lookup_processor_type @ r5=procinfo r9=cpuid
  92. movs r10, r5 @ invalid processor?
  93. beq __error_p @ yes, error 'p'
  94. ldr r7, __secondary_data
  95. #ifdef CONFIG_ARM_MPU
  96. bl __secondary_setup_mpu @ Initialize the MPU
  97. #endif
  98. badr lr, 1f @ return (PIC) address
  99. ldr r12, [r10, #PROCINFO_INITFUNC]
  100. add r12, r12, r10
  101. ret r12
  102. 1: bl __after_proc_init
  103. ldr r7, __secondary_data @ reload r7
  104. ldr sp, [r7, #12] @ set up the stack pointer
  105. ldr r0, [r7, #16] @ set up task pointer
  106. mov fp, #0
  107. b secondary_start_kernel
  108. ENDPROC(secondary_startup)
  109. .type __secondary_data, %object
  110. __secondary_data:
  111. .long secondary_data
  112. #endif /* CONFIG_SMP */
  113. /*
  114. * Set the Control Register and Read the process ID.
  115. */
  116. .text
  117. __after_proc_init:
  118. M_CLASS(movw r12, #:lower16:BASEADDR_V7M_SCB)
  119. M_CLASS(movt r12, #:upper16:BASEADDR_V7M_SCB)
  120. #ifdef CONFIG_ARM_MPU
  121. M_CLASS(ldr r3, [r12, 0x50])
  122. AR_CLASS(mrc p15, 0, r3, c0, c1, 4) @ Read ID_MMFR0
  123. and r3, r3, #(MMFR0_PMSA) @ PMSA field
  124. teq r3, #(MMFR0_PMSAv7) @ PMSA v7
  125. beq 1f
  126. teq r3, #(MMFR0_PMSAv8) @ PMSA v8
  127. /*
  128. * Memory region attributes for PMSAv8:
  129. *
  130. * n = AttrIndx[2:0]
  131. * n MAIR
  132. * DEVICE_nGnRnE 000 00000000
  133. * NORMAL 001 11111111
  134. */
  135. ldreq r3, =PMSAv8_MAIR(0x00, PMSAv8_RGN_DEVICE_nGnRnE) | \
  136. PMSAv8_MAIR(0xff, PMSAv8_RGN_NORMAL)
  137. AR_CLASS(mcreq p15, 0, r3, c10, c2, 0) @ MAIR 0
  138. M_CLASS(streq r3, [r12, #PMSAv8_MAIR0])
  139. moveq r3, #0
  140. AR_CLASS(mcreq p15, 0, r3, c10, c2, 1) @ MAIR 1
  141. M_CLASS(streq r3, [r12, #PMSAv8_MAIR1])
  142. 1:
  143. #endif
  144. #ifdef CONFIG_CPU_CP15
  145. /*
  146. * CP15 system control register value returned in r0 from
  147. * the CPU init function.
  148. */
  149. #ifdef CONFIG_ARM_MPU
  150. biceq r0, r0, #CR_BR @ Disable the 'default mem-map'
  151. orreq r0, r0, #CR_M @ Set SCTRL.M (MPU on)
  152. #endif
  153. #if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6
  154. orr r0, r0, #CR_A
  155. #else
  156. bic r0, r0, #CR_A
  157. #endif
  158. #ifdef CONFIG_CPU_DCACHE_DISABLE
  159. bic r0, r0, #CR_C
  160. #endif
  161. #ifdef CONFIG_CPU_BPREDICT_DISABLE
  162. bic r0, r0, #CR_Z
  163. #endif
  164. #ifdef CONFIG_CPU_ICACHE_DISABLE
  165. bic r0, r0, #CR_I
  166. #endif
  167. mcr p15, 0, r0, c1, c0, 0 @ write control reg
  168. instr_sync
  169. #elif defined (CONFIG_CPU_V7M)
  170. #ifdef CONFIG_ARM_MPU
  171. ldreq r3, [r12, MPU_CTRL]
  172. biceq r3, #MPU_CTRL_PRIVDEFENA
  173. orreq r3, #MPU_CTRL_ENABLE
  174. streq r3, [r12, MPU_CTRL]
  175. isb
  176. #endif
  177. /* For V7M systems we want to modify the CCR similarly to the SCTLR */
  178. #ifdef CONFIG_CPU_DCACHE_DISABLE
  179. bic r0, r0, #V7M_SCB_CCR_DC
  180. #endif
  181. #ifdef CONFIG_CPU_BPREDICT_DISABLE
  182. bic r0, r0, #V7M_SCB_CCR_BP
  183. #endif
  184. #ifdef CONFIG_CPU_ICACHE_DISABLE
  185. bic r0, r0, #V7M_SCB_CCR_IC
  186. #endif
  187. str r0, [r12, V7M_SCB_CCR]
  188. /* Pass exc_ret to __mmap_switched */
  189. mov r0, r10
  190. #endif /* CONFIG_CPU_CP15 elif CONFIG_CPU_V7M */
  191. ret lr
  192. ENDPROC(__after_proc_init)
  193. .ltorg
  194. #ifdef CONFIG_ARM_MPU
  195. #ifndef CONFIG_CPU_V7M
  196. /* Set which MPU region should be programmed */
  197. .macro set_region_nr tmp, rgnr, unused
  198. mov \tmp, \rgnr @ Use static region numbers
  199. mcr p15, 0, \tmp, c6, c2, 0 @ Write RGNR
  200. .endm
  201. /* Setup a single MPU region, either D or I side (D-side for unified) */
  202. .macro setup_region bar, acr, sr, side = PMSAv7_DATA_SIDE, unused
  203. mcr p15, 0, \bar, c6, c1, (0 + \side) @ I/DRBAR
  204. mcr p15, 0, \acr, c6, c1, (4 + \side) @ I/DRACR
  205. mcr p15, 0, \sr, c6, c1, (2 + \side) @ I/DRSR
  206. .endm
  207. #else
  208. .macro set_region_nr tmp, rgnr, base
  209. mov \tmp, \rgnr
  210. str \tmp, [\base, #PMSAv7_RNR]
  211. .endm
  212. .macro setup_region bar, acr, sr, unused, base
  213. lsl \acr, \acr, #16
  214. orr \acr, \acr, \sr
  215. str \bar, [\base, #PMSAv7_RBAR]
  216. str \acr, [\base, #PMSAv7_RASR]
  217. .endm
  218. #endif
  219. /*
  220. * Setup the MPU and initial MPU Regions. We create the following regions:
  221. * Region 0: Use this for probing the MPU details, so leave disabled.
  222. * Region 1: Background region - covers the whole of RAM as strongly ordered
  223. * Region 2: Normal, Shared, cacheable for RAM. From PHYS_OFFSET, size from r6
  224. * Region 3: Normal, shared, inaccessible from PL0 to protect the vectors page
  225. *
  226. * r6: Value to be written to DRSR (and IRSR if required) for PMSAv7_RAM_REGION
  227. */
  228. __HEAD
  229. ENTRY(__setup_mpu)
  230. /* Probe for v7 PMSA compliance */
  231. M_CLASS(movw r12, #:lower16:BASEADDR_V7M_SCB)
  232. M_CLASS(movt r12, #:upper16:BASEADDR_V7M_SCB)
  233. AR_CLASS(mrc p15, 0, r0, c0, c1, 4) @ Read ID_MMFR0
  234. M_CLASS(ldr r0, [r12, 0x50])
  235. and r0, r0, #(MMFR0_PMSA) @ PMSA field
  236. teq r0, #(MMFR0_PMSAv7) @ PMSA v7
  237. beq __setup_pmsa_v7
  238. teq r0, #(MMFR0_PMSAv8) @ PMSA v8
  239. beq __setup_pmsa_v8
  240. ret lr
  241. ENDPROC(__setup_mpu)
  242. ENTRY(__setup_pmsa_v7)
  243. /* Calculate the size of a region covering just the kernel */
  244. ldr r5, =PLAT_PHYS_OFFSET @ Region start: PHYS_OFFSET
  245. ldr r6, =(_end) @ Cover whole kernel
  246. sub r6, r6, r5 @ Minimum size of region to map
  247. clz r6, r6 @ Region size must be 2^N...
  248. rsb r6, r6, #31 @ ...so round up region size
  249. lsl r6, r6, #PMSAv7_RSR_SZ @ Put size in right field
  250. orr r6, r6, #(1 << PMSAv7_RSR_EN) @ Set region enabled bit
  251. /* Determine whether the D/I-side memory map is unified. We set the
  252. * flags here and continue to use them for the rest of this function */
  253. AR_CLASS(mrc p15, 0, r0, c0, c0, 4) @ MPUIR
  254. M_CLASS(ldr r0, [r12, #MPU_TYPE])
  255. ands r5, r0, #MPUIR_DREGION_SZMASK @ 0 size d region => No MPU
  256. bxeq lr
  257. tst r0, #MPUIR_nU @ MPUIR_nU = 0 for unified
  258. /* Setup second region first to free up r6 */
  259. set_region_nr r0, #PMSAv7_RAM_REGION, r12
  260. isb
  261. /* Full access from PL0, PL1, shared for CONFIG_SMP, cacheable */
  262. ldr r0, =PLAT_PHYS_OFFSET @ RAM starts at PHYS_OFFSET
  263. ldr r5,=(PMSAv7_AP_PL1RW_PL0RW | PMSAv7_RGN_NORMAL)
  264. setup_region r0, r5, r6, PMSAv7_DATA_SIDE, r12 @ PHYS_OFFSET, shared, enabled
  265. beq 1f @ Memory-map not unified
  266. setup_region r0, r5, r6, PMSAv7_INSTR_SIDE, r12 @ PHYS_OFFSET, shared, enabled
  267. 1: isb
  268. /* First/background region */
  269. set_region_nr r0, #PMSAv7_BG_REGION, r12
  270. isb
  271. /* Execute Never, strongly ordered, inaccessible to PL0, rw PL1 */
  272. mov r0, #0 @ BG region starts at 0x0
  273. ldr r5,=(PMSAv7_ACR_XN | PMSAv7_RGN_STRONGLY_ORDERED | PMSAv7_AP_PL1RW_PL0NA)
  274. mov r6, #PMSAv7_RSR_ALL_MEM @ 4GB region, enabled
  275. setup_region r0, r5, r6, PMSAv7_DATA_SIDE, r12 @ 0x0, BG region, enabled
  276. beq 2f @ Memory-map not unified
  277. setup_region r0, r5, r6, PMSAv7_INSTR_SIDE r12 @ 0x0, BG region, enabled
  278. 2: isb
  279. #ifdef CONFIG_XIP_KERNEL
  280. set_region_nr r0, #PMSAv7_ROM_REGION, r12
  281. isb
  282. ldr r5,=(PMSAv7_AP_PL1RO_PL0NA | PMSAv7_RGN_NORMAL)
  283. ldr r0, =CONFIG_XIP_PHYS_ADDR @ ROM start
  284. ldr r6, =(_exiprom) @ ROM end
  285. sub r6, r6, r0 @ Minimum size of region to map
  286. clz r6, r6 @ Region size must be 2^N...
  287. rsb r6, r6, #31 @ ...so round up region size
  288. lsl r6, r6, #PMSAv7_RSR_SZ @ Put size in right field
  289. orr r6, r6, #(1 << PMSAv7_RSR_EN) @ Set region enabled bit
  290. setup_region r0, r5, r6, PMSAv7_DATA_SIDE, r12 @ XIP_PHYS_ADDR, shared, enabled
  291. beq 3f @ Memory-map not unified
  292. setup_region r0, r5, r6, PMSAv7_INSTR_SIDE, r12 @ XIP_PHYS_ADDR, shared, enabled
  293. 3: isb
  294. #endif
  295. ret lr
  296. ENDPROC(__setup_pmsa_v7)
  297. ENTRY(__setup_pmsa_v8)
  298. mov r0, #0
  299. AR_CLASS(mcr p15, 0, r0, c6, c2, 1) @ PRSEL
  300. M_CLASS(str r0, [r12, #PMSAv8_RNR])
  301. isb
  302. #ifdef CONFIG_XIP_KERNEL
  303. ldr r5, =CONFIG_XIP_PHYS_ADDR @ ROM start
  304. ldr r6, =(_exiprom) @ ROM end
  305. sub r6, r6, #1
  306. bic r6, r6, #(PMSAv8_MINALIGN - 1)
  307. orr r5, r5, #(PMSAv8_AP_PL1RW_PL0NA | PMSAv8_RGN_SHARED)
  308. orr r6, r6, #(PMSAv8_LAR_IDX(PMSAv8_RGN_NORMAL) | PMSAv8_LAR_EN)
  309. AR_CLASS(mcr p15, 0, r5, c6, c8, 0) @ PRBAR0
  310. AR_CLASS(mcr p15, 0, r6, c6, c8, 1) @ PRLAR0
  311. M_CLASS(str r5, [r12, #PMSAv8_RBAR_A(0)])
  312. M_CLASS(str r6, [r12, #PMSAv8_RLAR_A(0)])
  313. #endif
  314. ldr r5, =KERNEL_START
  315. ldr r6, =KERNEL_END
  316. sub r6, r6, #1
  317. bic r6, r6, #(PMSAv8_MINALIGN - 1)
  318. orr r5, r5, #(PMSAv8_AP_PL1RW_PL0NA | PMSAv8_RGN_SHARED)
  319. orr r6, r6, #(PMSAv8_LAR_IDX(PMSAv8_RGN_NORMAL) | PMSAv8_LAR_EN)
  320. AR_CLASS(mcr p15, 0, r5, c6, c8, 4) @ PRBAR1
  321. AR_CLASS(mcr p15, 0, r6, c6, c8, 5) @ PRLAR1
  322. M_CLASS(str r5, [r12, #PMSAv8_RBAR_A(1)])
  323. M_CLASS(str r6, [r12, #PMSAv8_RLAR_A(1)])
  324. /* Setup Background: 0x0 - min(KERNEL_START, XIP_PHYS_ADDR) */
  325. #ifdef CONFIG_XIP_KERNEL
  326. ldr r6, =KERNEL_START
  327. ldr r5, =CONFIG_XIP_PHYS_ADDR
  328. cmp r6, r5
  329. movcs r6, r5
  330. #else
  331. ldr r6, =KERNEL_START
  332. #endif
  333. cmp r6, #0
  334. beq 1f
  335. mov r5, #0
  336. sub r6, r6, #1
  337. bic r6, r6, #(PMSAv8_MINALIGN - 1)
  338. orr r5, r5, #(PMSAv8_AP_PL1RW_PL0NA | PMSAv8_RGN_SHARED | PMSAv8_BAR_XN)
  339. orr r6, r6, #(PMSAv8_LAR_IDX(PMSAv8_RGN_DEVICE_nGnRnE) | PMSAv8_LAR_EN)
  340. AR_CLASS(mcr p15, 0, r5, c6, c9, 0) @ PRBAR2
  341. AR_CLASS(mcr p15, 0, r6, c6, c9, 1) @ PRLAR2
  342. M_CLASS(str r5, [r12, #PMSAv8_RBAR_A(2)])
  343. M_CLASS(str r6, [r12, #PMSAv8_RLAR_A(2)])
  344. 1:
  345. /* Setup Background: max(KERNEL_END, _exiprom) - 0xffffffff */
  346. #ifdef CONFIG_XIP_KERNEL
  347. ldr r5, =KERNEL_END
  348. ldr r6, =(_exiprom)
  349. cmp r5, r6
  350. movcc r5, r6
  351. #else
  352. ldr r5, =KERNEL_END
  353. #endif
  354. mov r6, #0xffffffff
  355. bic r6, r6, #(PMSAv8_MINALIGN - 1)
  356. orr r5, r5, #(PMSAv8_AP_PL1RW_PL0NA | PMSAv8_RGN_SHARED | PMSAv8_BAR_XN)
  357. orr r6, r6, #(PMSAv8_LAR_IDX(PMSAv8_RGN_DEVICE_nGnRnE) | PMSAv8_LAR_EN)
  358. AR_CLASS(mcr p15, 0, r5, c6, c9, 4) @ PRBAR3
  359. AR_CLASS(mcr p15, 0, r6, c6, c9, 5) @ PRLAR3
  360. M_CLASS(str r5, [r12, #PMSAv8_RBAR_A(3)])
  361. M_CLASS(str r6, [r12, #PMSAv8_RLAR_A(3)])
  362. #ifdef CONFIG_XIP_KERNEL
  363. /* Setup Background: min(_exiprom, KERNEL_END) - max(KERNEL_START, XIP_PHYS_ADDR) */
  364. ldr r5, =(_exiprom)
  365. ldr r6, =KERNEL_END
  366. cmp r5, r6
  367. movcs r5, r6
  368. ldr r6, =KERNEL_START
  369. ldr r0, =CONFIG_XIP_PHYS_ADDR
  370. cmp r6, r0
  371. movcc r6, r0
  372. sub r6, r6, #1
  373. bic r6, r6, #(PMSAv8_MINALIGN - 1)
  374. orr r5, r5, #(PMSAv8_AP_PL1RW_PL0NA | PMSAv8_RGN_SHARED | PMSAv8_BAR_XN)
  375. orr r6, r6, #(PMSAv8_LAR_IDX(PMSAv8_RGN_DEVICE_nGnRnE) | PMSAv8_LAR_EN)
  376. #ifdef CONFIG_CPU_V7M
  377. /* There is no alias for n == 4 */
  378. mov r0, #4
  379. str r0, [r12, #PMSAv8_RNR] @ PRSEL
  380. isb
  381. str r5, [r12, #PMSAv8_RBAR_A(0)]
  382. str r6, [r12, #PMSAv8_RLAR_A(0)]
  383. #else
  384. mcr p15, 0, r5, c6, c10, 0 @ PRBAR4
  385. mcr p15, 0, r6, c6, c10, 1 @ PRLAR4
  386. #endif
  387. #endif
  388. ret lr
  389. ENDPROC(__setup_pmsa_v8)
  390. #ifdef CONFIG_SMP
  391. /*
  392. * r6: pointer at mpu_rgn_info
  393. */
  394. .text
  395. ENTRY(__secondary_setup_mpu)
  396. /* Use MPU region info supplied by __cpu_up */
  397. ldr r6, [r7] @ get secondary_data.mpu_rgn_info
  398. /* Probe for v7 PMSA compliance */
  399. mrc p15, 0, r0, c0, c1, 4 @ Read ID_MMFR0
  400. and r0, r0, #(MMFR0_PMSA) @ PMSA field
  401. teq r0, #(MMFR0_PMSAv7) @ PMSA v7
  402. beq __secondary_setup_pmsa_v7
  403. teq r0, #(MMFR0_PMSAv8) @ PMSA v8
  404. beq __secondary_setup_pmsa_v8
  405. b __error_p
  406. ENDPROC(__secondary_setup_mpu)
  407. /*
  408. * r6: pointer at mpu_rgn_info
  409. */
  410. ENTRY(__secondary_setup_pmsa_v7)
  411. /* Determine whether the D/I-side memory map is unified. We set the
  412. * flags here and continue to use them for the rest of this function */
  413. mrc p15, 0, r0, c0, c0, 4 @ MPUIR
  414. ands r5, r0, #MPUIR_DREGION_SZMASK @ 0 size d region => No MPU
  415. beq __error_p
  416. ldr r4, [r6, #MPU_RNG_INFO_USED]
  417. mov r5, #MPU_RNG_SIZE
  418. add r3, r6, #MPU_RNG_INFO_RNGS
  419. mla r3, r4, r5, r3
  420. 1:
  421. tst r0, #MPUIR_nU @ MPUIR_nU = 0 for unified
  422. sub r3, r3, #MPU_RNG_SIZE
  423. sub r4, r4, #1
  424. set_region_nr r0, r4
  425. isb
  426. ldr r0, [r3, #MPU_RGN_DRBAR]
  427. ldr r6, [r3, #MPU_RGN_DRSR]
  428. ldr r5, [r3, #MPU_RGN_DRACR]
  429. setup_region r0, r5, r6, PMSAv7_DATA_SIDE
  430. beq 2f
  431. setup_region r0, r5, r6, PMSAv7_INSTR_SIDE
  432. 2: isb
  433. mrc p15, 0, r0, c0, c0, 4 @ Reevaluate the MPUIR
  434. cmp r4, #0
  435. bgt 1b
  436. ret lr
  437. ENDPROC(__secondary_setup_pmsa_v7)
  438. ENTRY(__secondary_setup_pmsa_v8)
  439. ldr r4, [r6, #MPU_RNG_INFO_USED]
  440. #ifndef CONFIG_XIP_KERNEL
  441. add r4, r4, #1
  442. #endif
  443. mov r5, #MPU_RNG_SIZE
  444. add r3, r6, #MPU_RNG_INFO_RNGS
  445. mla r3, r4, r5, r3
  446. 1:
  447. sub r3, r3, #MPU_RNG_SIZE
  448. sub r4, r4, #1
  449. mcr p15, 0, r4, c6, c2, 1 @ PRSEL
  450. isb
  451. ldr r5, [r3, #MPU_RGN_PRBAR]
  452. ldr r6, [r3, #MPU_RGN_PRLAR]
  453. mcr p15, 0, r5, c6, c3, 0 @ PRBAR
  454. mcr p15, 0, r6, c6, c3, 1 @ PRLAR
  455. cmp r4, #0
  456. bgt 1b
  457. ret lr
  458. ENDPROC(__secondary_setup_pmsa_v8)
  459. #endif /* CONFIG_SMP */
  460. #endif /* CONFIG_ARM_MPU */
  461. #include "head-common.S"