relocate_kernel.S 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #include <linux/linkage.h>
  3. #include <asm/asm-offsets.h>
  4. #include <asm/page.h>
  5. #include <asm/setup.h>
  6. #define MMU_BASE 8 /* MMU flags base in cpu_mmu_flags */
  7. .text
  8. ENTRY(relocate_new_kernel)
  9. movel %sp@(4),%a0 /* a0 = ptr */
  10. movel %sp@(8),%a1 /* a1 = start */
  11. movel %sp@(12),%d1 /* d1 = cpu_mmu_flags */
  12. movew #PAGE_MASK,%d2 /* d2 = PAGE_MASK */
  13. /* Disable MMU */
  14. btst #MMU_BASE + MMUB_68851,%d1
  15. jeq 3f
  16. 1: /* 68851 or 68030 */
  17. lea %pc@(.Lcopy),%a4
  18. 2: addl #0x00000000,%a4 /* virt_to_phys() */
  19. .section ".m68k_fixup","aw"
  20. .long M68K_FIXUP_MEMOFFSET, 2b+2
  21. .previous
  22. .chip 68030
  23. pmove %tc,%d0 /* Disable MMU */
  24. bclr #7,%d0
  25. pmove %d0,%tc
  26. jmp %a4@ /* Jump to physical .Lcopy */
  27. .chip 68k
  28. 3:
  29. btst #MMU_BASE + MMUB_68030,%d1
  30. jne 1b
  31. btst #MMU_BASE + MMUB_68040,%d1
  32. jeq 6f
  33. 4: /* 68040 or 68060 */
  34. lea %pc@(.Lcont040),%a4
  35. 5: addl #0x00000000,%a4 /* virt_to_phys() */
  36. .section ".m68k_fixup","aw"
  37. .long M68K_FIXUP_MEMOFFSET, 5b+2
  38. .previous
  39. movel %a4,%d0
  40. andl #0xff000000,%d0
  41. orw #0xe020,%d0 /* Map 16 MiB, enable, cacheable */
  42. .chip 68040
  43. movec %d0,%itt0
  44. movec %d0,%dtt0
  45. .chip 68k
  46. jmp %a4@ /* Jump to physical .Lcont040 */
  47. .Lcont040:
  48. moveq #0,%d0
  49. .chip 68040
  50. movec %d0,%tc /* Disable MMU */
  51. movec %d0,%itt0
  52. movec %d0,%itt1
  53. movec %d0,%dtt0
  54. movec %d0,%dtt1
  55. .chip 68k
  56. jra .Lcopy
  57. 6:
  58. btst #MMU_BASE + MMUB_68060,%d1
  59. jne 4b
  60. .Lcopy:
  61. movel %a0@+,%d0 /* d0 = entry = *ptr */
  62. jeq .Lflush
  63. btst #2,%d0 /* entry & IND_DONE? */
  64. jne .Lflush
  65. btst #1,%d0 /* entry & IND_INDIRECTION? */
  66. jeq 1f
  67. andw %d2,%d0
  68. movel %d0,%a0 /* ptr = entry & PAGE_MASK */
  69. jra .Lcopy
  70. 1:
  71. btst #0,%d0 /* entry & IND_DESTINATION? */
  72. jeq 2f
  73. andw %d2,%d0
  74. movel %d0,%a2 /* a2 = dst = entry & PAGE_MASK */
  75. jra .Lcopy
  76. 2:
  77. btst #3,%d0 /* entry & IND_SOURCE? */
  78. jeq .Lcopy
  79. andw %d2,%d0
  80. movel %d0,%a3 /* a3 = src = entry & PAGE_MASK */
  81. movew #PAGE_SIZE/32 - 1,%d0 /* d0 = PAGE_SIZE/32 - 1 */
  82. 3:
  83. movel %a3@+,%a2@+ /* *dst++ = *src++ */
  84. movel %a3@+,%a2@+ /* *dst++ = *src++ */
  85. movel %a3@+,%a2@+ /* *dst++ = *src++ */
  86. movel %a3@+,%a2@+ /* *dst++ = *src++ */
  87. movel %a3@+,%a2@+ /* *dst++ = *src++ */
  88. movel %a3@+,%a2@+ /* *dst++ = *src++ */
  89. movel %a3@+,%a2@+ /* *dst++ = *src++ */
  90. movel %a3@+,%a2@+ /* *dst++ = *src++ */
  91. dbf %d0, 3b
  92. jra .Lcopy
  93. .Lflush:
  94. /* Flush all caches */
  95. btst #CPUB_68020,%d1
  96. jeq 2f
  97. 1: /* 68020 or 68030 */
  98. .chip 68030
  99. movec %cacr,%d0
  100. orw #0x808,%d0
  101. movec %d0,%cacr
  102. .chip 68k
  103. jra .Lreincarnate
  104. 2:
  105. btst #CPUB_68030,%d1
  106. jne 1b
  107. btst #CPUB_68040,%d1
  108. jeq 4f
  109. 3: /* 68040 or 68060 */
  110. .chip 68040
  111. nop
  112. cpusha %bc
  113. nop
  114. cinva %bc
  115. nop
  116. .chip 68k
  117. jra .Lreincarnate
  118. 4:
  119. btst #CPUB_68060,%d1
  120. jne 3b
  121. .Lreincarnate:
  122. jmp %a1@
  123. relocate_new_kernel_end:
  124. ENTRY(relocate_new_kernel_size)
  125. .long relocate_new_kernel_end - relocate_new_kernel