head.S 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright (C) 2009 Wind River Systems Inc
  3. * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
  4. * Copyright (C) 2004 Microtronix Datacom Ltd
  5. * Copyright (C) 2001 Vic Phillips, Microtronix Datacom Ltd.
  6. *
  7. * Based on head.S for Altera's Excalibur development board with nios processor
  8. *
  9. * Based on the following from the Excalibur sdk distribution:
  10. * NA_MemoryMap.s, NR_JumpToStart.s, NR_Setup.s, NR_CWPManager.s
  11. *
  12. * This file is subject to the terms and conditions of the GNU General Public
  13. * License. See the file "COPYING" in the main directory of this archive
  14. * for more details.
  15. */
  16. #include <linux/init.h>
  17. #include <linux/linkage.h>
  18. #include <asm/thread_info.h>
  19. #include <asm/processor.h>
  20. #include <asm/cache.h>
  21. #include <asm/page.h>
  22. #include <asm/asm-offsets.h>
  23. #include <asm/asm-macros.h>
  24. /*
  25. * ZERO_PAGE is a special page that is used for zero-initialized
  26. * data and COW.
  27. */
  28. .data
  29. .global empty_zero_page
  30. .align 12
  31. empty_zero_page:
  32. .space PAGE_SIZE
  33. /*
  34. * This global variable is used as an extension to the nios'
  35. * STATUS register to emulate a user/supervisor mode.
  36. */
  37. .data
  38. .align 2
  39. .set noat
  40. .global _current_thread
  41. _current_thread:
  42. .long 0
  43. /*
  44. * Input(s): passed from u-boot
  45. * r4 - Optional pointer to a board information structure.
  46. * r5 - Optional pointer to the physical starting address of the init RAM
  47. * disk.
  48. * r6 - Optional pointer to the physical ending address of the init RAM
  49. * disk.
  50. * r7 - Optional pointer to the physical starting address of any kernel
  51. * command-line parameters.
  52. */
  53. /*
  54. * First executable code - detected and jumped to by the ROM bootstrap
  55. * if the code resides in flash (looks for "Nios" at offset 0x0c from
  56. * the potential executable image).
  57. */
  58. __HEAD
  59. ENTRY(_start)
  60. wrctl status, r0 /* Disable interrupts */
  61. /* Initialize all cache lines within the instruction cache */
  62. movia r1, NIOS2_ICACHE_SIZE
  63. movui r2, NIOS2_ICACHE_LINE_SIZE
  64. icache_init:
  65. initi r1
  66. sub r1, r1, r2
  67. bgt r1, r0, icache_init
  68. br 1f
  69. /*
  70. * This is the default location for the exception handler. Code in jump
  71. * to our handler
  72. */
  73. ENTRY(exception_handler_hook)
  74. movia r24, inthandler
  75. jmp r24
  76. ENTRY(fast_handler)
  77. nextpc et
  78. helper:
  79. stw r3, r3save - helper(et)
  80. rdctl r3 , pteaddr
  81. srli r3, r3, 12
  82. slli r3, r3, 2
  83. movia et, pgd_current
  84. ldw et, 0(et)
  85. add r3, et, r3
  86. ldw et, 0(r3)
  87. rdctl r3, pteaddr
  88. andi r3, r3, 0xfff
  89. add et, r3, et
  90. ldw et, 0(et)
  91. wrctl tlbacc, et
  92. nextpc et
  93. helper2:
  94. ldw r3, r3save - helper2(et)
  95. subi ea, ea, 4
  96. eret
  97. r3save:
  98. .word 0x0
  99. ENTRY(fast_handler_end)
  100. 1:
  101. /*
  102. * After the instruction cache is initialized, the data cache must
  103. * also be initialized.
  104. */
  105. movia r1, NIOS2_DCACHE_SIZE
  106. movui r2, NIOS2_DCACHE_LINE_SIZE
  107. dcache_init:
  108. initd 0(r1)
  109. sub r1, r1, r2
  110. bgt r1, r0, dcache_init
  111. nextpc r1 /* Find out where we are */
  112. chkadr:
  113. movia r2, chkadr
  114. beq r1, r2,finish_move /* We are running in RAM done */
  115. addi r1, r1,(_start - chkadr) /* Source */
  116. movia r2, _start /* Destination */
  117. movia r3, __bss_start /* End of copy */
  118. loop_move: /* r1: src, r2: dest, r3: last dest */
  119. ldw r8, 0(r1) /* load a word from [r1] */
  120. stw r8, 0(r2) /* store a word to dest [r2] */
  121. flushd 0(r2) /* Flush cache for safety */
  122. addi r1, r1, 4 /* inc the src addr */
  123. addi r2, r2, 4 /* inc the dest addr */
  124. blt r2, r3, loop_move
  125. movia r1, finish_move /* VMA(_start)->l1 */
  126. jmp r1 /* jmp to _start */
  127. finish_move:
  128. /* Mask off all possible interrupts */
  129. wrctl ienable, r0
  130. /* Clear .bss */
  131. movia r2, __bss_start
  132. movia r1, __bss_stop
  133. 1:
  134. stb r0, 0(r2)
  135. addi r2, r2, 1
  136. bne r1, r2, 1b
  137. movia r1, init_thread_union /* set stack at top of the task union */
  138. addi sp, r1, THREAD_SIZE
  139. movia r2, _current_thread /* Remember current thread */
  140. stw r1, 0(r2)
  141. movia r1, nios2_boot_init /* save args r4-r7 passed from u-boot */
  142. callr r1
  143. movia r1, start_kernel /* call start_kernel as a subroutine */
  144. callr r1
  145. /* If we return from start_kernel, break to the oci debugger and
  146. * buggered we are.
  147. */
  148. break
  149. /* End of startup code */
  150. .set at