entry_point.S 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * Copyright (c) 2006-2020, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Date Author Notes
  7. * 2020-01-15 bigmagic the first version
  8. */
  9. .section ".text.entrypoint"
  10. .set EL1_stack, __el1_stack
  11. .global _start
  12. // This symbol is set to 0x80000 in ld script. That is the address that raspi3's firmware
  13. // loads 'kernel8.img' file in.
  14. _start:
  15. // read cpu id, stop slave cores
  16. mrs x1, mpidr_el1 // MPIDR_EL1: Multi-Processor Affinity Register
  17. and x1, x1, #3
  18. cbz x1, .L__cpu_0 // .L prefix is the local label in ELF
  19. // cpu id > 0, stop
  20. // cpu id == 0 will also goto here after returned from entry() if possible
  21. .L__current_cpu_idle:
  22. wfe
  23. b .L__current_cpu_idle
  24. .L__cpu_0: // cpu id == 0
  25. // set stack before our code
  26. /* Define stack pointer for current exception level */
  27. // ldr x2, =EL1_stack
  28. // mov sp, x2
  29. ldr x1, =_start
  30. // set up EL1
  31. mrs x0, CurrentEL // CurrentEL Register. bit 2, 3. Others reserved
  32. and x0, x0, #12 // clear reserved bits
  33. // running at EL3?
  34. cmp x0, #12 // 1100b. So, EL3
  35. bne .L__not_in_el3 // 11? !EL3 -> 5:
  36. // should never be executed, just for completeness. (EL3)
  37. mov x2, #0x5b1
  38. msr scr_el3, x2 // SCR_ELn Secure Configuration Register
  39. mov x2, #0x3c9
  40. msr spsr_el3, x2 // SPSR_ELn. Saved Program Status Register. 1111001001
  41. adr x2, .L__not_in_el3
  42. msr elr_el3, x2
  43. eret // Exception Return: from EL3, continue from .L__not_in_el3
  44. // running at EL2 or EL1
  45. .L__not_in_el3:
  46. cmp x0, #4 // 0x04 0100 EL1
  47. beq .L__in_el1 // EL1 -> 5:
  48. // in EL2
  49. msr sp_el1, x1 // Set sp of EL1 to _start
  50. // enable CNTP for EL1
  51. mrs x0, cnthctl_el2 // Counter-timer Hypervisor Control register
  52. orr x0, x0, #3
  53. msr cnthctl_el2, x0
  54. msr cntvoff_el2, xzr
  55. // enable AArch64 in EL1
  56. mov x0, #(1 << 31) // AArch64
  57. orr x0, x0, #(1 << 1) // SWIO hardwired on Pi3
  58. msr hcr_el2, x0
  59. mrs x0, hcr_el2
  60. // change execution level to EL1
  61. mov x2, #0x3c4
  62. msr spsr_el2, x2 // 1111000100
  63. adr x2, .L__in_el1
  64. msr elr_el2, x2
  65. eret // exception return. from EL2. continue from .L__in_el1
  66. .L__in_el1:
  67. mov sp, x1 // in EL1. Set sp to _start
  68. // Set CPACR_EL1 (Architecture Feature Access Control Register) to avoid trap from SIMD or float point instruction
  69. mov x1, #0x00300000 // Don't trap any SIMD/FP instructions in both EL0 and EL1
  70. msr cpacr_el1, x1
  71. mrs x1, sctlr_el1
  72. orr x1, x1, #(1 << 12)
  73. bic x1, x1, #(3 << 3)
  74. bic x1, x1, #(1 << 1)
  75. msr sctlr_el1, x1
  76. // clear bss
  77. ldr x1, =__bss_start
  78. ldr w2, =__bss_size
  79. .L__clean_bss_loop:
  80. cbz w2, .L__jump_to_entry
  81. str xzr, [x1], #8
  82. sub w2, w2, #1
  83. cbnz w2, .L__clean_bss_loop
  84. // jump to C code, should not return
  85. .L__jump_to_entry:
  86. bl entry
  87. // for failsafe, halt this core too
  88. b .L__current_cpu_idle