1/* 2 * relocate_kernel.S - put the kernel image in place to boot 3 * 2005.9.17 kogiidena@eggplant.ddo.jp 4 * 5 * LANDISK/sh4 is supported. Maybe, SH archtecture works well. 6 * 7 * 2009-03-18 Magnus Damm - Added Kexec Jump support 8 * 9 * This source code is licensed under the GNU General Public License, 10 * Version 2. See the file COPYING for more details. 11 */ 12#include <linux/linkage.h> 13#include <asm/addrspace.h> 14#include <asm/page.h> 15 16 .globl relocate_new_kernel 17relocate_new_kernel: 18 /* r4 = indirection_page */ 19 /* r5 = reboot_code_buffer */ 20 /* r6 = start_address */ 21 22 mov.l 10f, r0 /* PAGE_SIZE */ 23 add r5, r0 /* setup new stack at end of control page */ 24 25 /* save r15->r8 to new stack */ 26 mov.l r15, @-r0 27 mov r0, r15 28 mov.l r14, @-r15 29 mov.l r13, @-r15 30 mov.l r12, @-r15 31 mov.l r11, @-r15 32 mov.l r10, @-r15 33 mov.l r9, @-r15 34 mov.l r8, @-r15 35 36 /* save other random registers */ 37 sts.l macl, @-r15 38 sts.l mach, @-r15 39 stc.l gbr, @-r15 40 stc.l ssr, @-r15 41 stc.l sr, @-r15 42 sts.l pr, @-r15 43 stc.l spc, @-r15 44 45 /* switch to bank1 and save r7->r0 */ 46 mov.l 12f, r9 47 stc sr, r8 48 or r9, r8 49 ldc r8, sr 50 mov.l r7, @-r15 51 mov.l r6, @-r15 52 mov.l r5, @-r15 53 mov.l r4, @-r15 54 mov.l r3, @-r15 55 mov.l r2, @-r15 56 mov.l r1, @-r15 57 mov.l r0, @-r15 58 59 /* switch to bank0 and save r7->r0 */ 60 mov.l 12f, r9 61 not r9, r9 62 stc sr, r8 63 and r9, r8 64 ldc r8, sr 65 mov.l r7, @-r15 66 mov.l r6, @-r15 67 mov.l r5, @-r15 68 mov.l r4, @-r15 69 mov.l r3, @-r15 70 mov.l r2, @-r15 71 mov.l r1, @-r15 72 mov.l r0, @-r15 73 74 mov.l r4, @-r15 /* save indirection page again */ 75 76 bsr swap_pages /* swap pages before jumping to new kernel */ 77 nop 78 79 mova 11f, r0 80 mov.l r15, @r0 /* save pointer to stack */ 81 82 jsr @r6 /* hand over control to new kernel */ 83 nop 84 85 mov.l 11f, r15 /* get pointer to stack */ 86 mov.l @r15+, r4 /* restore r4 to get indirection page */ 87 88 bsr swap_pages /* swap pages back to previous state */ 89 nop 90 91 /* make sure bank0 is active and restore r0->r7 */ 92 mov.l 12f, r9 93 not r9, r9 94 stc sr, r8 95 and r9, r8 96 ldc r8, sr 97 mov.l @r15+, r0 98 mov.l @r15+, r1 99 mov.l @r15+, r2 100 mov.l @r15+, r3 101 mov.l @r15+, r4 102 mov.l @r15+, r5 103 mov.l @r15+, r6 104 mov.l @r15+, r7 105 106 /* switch to bank1 and restore r0->r7 */ 107 mov.l 12f, r9 108 stc sr, r8 109 or r9, r8 110 ldc r8, sr 111 mov.l @r15+, r0 112 mov.l @r15+, r1 113 mov.l @r15+, r2 114 mov.l @r15+, r3 115 mov.l @r15+, r4 116 mov.l @r15+, r5 117 mov.l @r15+, r6 118 mov.l @r15+, r7 119 120 /* switch back to bank0 */ 121 mov.l 12f, r9 122 not r9, r9 123 stc sr, r8 124 and r9, r8 125 ldc r8, sr 126 127 /* restore other random registers */ 128 ldc.l @r15+, spc 129 lds.l @r15+, pr 130 ldc.l @r15+, sr 131 ldc.l @r15+, ssr 132 ldc.l @r15+, gbr 133 lds.l @r15+, mach 134 lds.l @r15+, macl 135 136 /* restore r8->r15 */ 137 mov.l @r15+, r8 138 mov.l @r15+, r9 139 mov.l @r15+, r10 140 mov.l @r15+, r11 141 mov.l @r15+, r12 142 mov.l @r15+, r13 143 mov.l @r15+, r14 144 mov.l @r15+, r15 145 rts 146 nop 147 148swap_pages: 149 bra 1f 150 mov r4,r0 /* cmd = indirection_page */ 1510: 152 mov.l @r4+,r0 /* cmd = *ind++ */ 153 1541: /* addr = cmd & 0xfffffff0 */ 155 mov r0,r2 156 mov #-16,r1 157 and r1,r2 158 159 /* if(cmd & IND_DESTINATION) dst = addr */ 160 tst #1,r0 161 bt 2f 162 bra 0b 163 mov r2,r5 164 1652: /* else if(cmd & IND_INDIRECTION) ind = addr */ 166 tst #2,r0 167 bt 3f 168 bra 0b 169 mov r2,r4 170 1713: /* else if(cmd & IND_DONE) return */ 172 tst #4,r0 173 bt 4f 174 rts 175 nop 176 1774: /* else if(cmd & IND_SOURCE) memcpy(dst,addr,PAGE_SIZE) */ 178 tst #8,r0 179 bt 0b 180 181 mov.l 10f,r3 /* PAGE_SIZE */ 182 shlr2 r3 183 shlr2 r3 1845: 185 dt r3 186 187 /* regular kexec just overwrites the destination page 188 * with the contents of the source page. 189 * for the kexec jump case we need to swap the contents 190 * of the pages. 191 * to keep it simple swap the contents for both cases. 192 */ 193 mov.l @(0, r2), r8 194 mov.l @(0, r5), r1 195 mov.l r8, @(0, r5) 196 mov.l r1, @(0, r2) 197 198 mov.l @(4, r2), r8 199 mov.l @(4, r5), r1 200 mov.l r8, @(4, r5) 201 mov.l r1, @(4, r2) 202 203 mov.l @(8, r2), r8 204 mov.l @(8, r5), r1 205 mov.l r8, @(8, r5) 206 mov.l r1, @(8, r2) 207 208 mov.l @(12, r2), r8 209 mov.l @(12, r5), r1 210 mov.l r8, @(12, r5) 211 mov.l r1, @(12, r2) 212 213 add #16,r5 214 add #16,r2 215 bf 5b 216 217 bra 0b 218 nop 219 220 .align 2 22110: 222 .long PAGE_SIZE 22311: 224 .long 0 22512: 226 .long 0x20000000 ! RB=1 227 228relocate_new_kernel_end: 229 230 .globl relocate_new_kernel_size 231relocate_new_kernel_size: 232 .long relocate_new_kernel_end - relocate_new_kernel 233