/* SPDX-License-Identifier: GPL-2.01*2* relocate_kernel.S - put the kernel image in place to boot3* 2005.9.17 [email protected]4*5* LANDISK/sh4 is supported. Maybe, SH archtecture works well.6*7* 2009-03-18 Magnus Damm - Added Kexec Jump support8*/9#include <linux/linkage.h>10#include <asm/addrspace.h>11#include <asm/page.h>1213.globl relocate_new_kernel14relocate_new_kernel:15/* r4 = indirection_page */16/* r5 = reboot_code_buffer */17/* r6 = start_address */1819mov.l 10f, r0 /* PAGE_SIZE */20add r5, r0 /* setup new stack at end of control page */2122/* save r15->r8 to new stack */23mov.l r15, @-r024mov r0, r1525mov.l r14, @-r1526mov.l r13, @-r1527mov.l r12, @-r1528mov.l r11, @-r1529mov.l r10, @-r1530mov.l r9, @-r1531mov.l r8, @-r153233/* save other random registers */34sts.l macl, @-r1535sts.l mach, @-r1536stc.l gbr, @-r1537stc.l ssr, @-r1538stc.l sr, @-r1539sts.l pr, @-r1540stc.l spc, @-r154142/* switch to bank1 and save r7->r0 */43mov.l 12f, r944stc sr, r845or r9, r846ldc r8, sr47mov.l r7, @-r1548mov.l r6, @-r1549mov.l r5, @-r1550mov.l r4, @-r1551mov.l r3, @-r1552mov.l r2, @-r1553mov.l r1, @-r1554mov.l r0, @-r155556/* switch to bank0 and save r7->r0 */57mov.l 12f, r958not r9, r959stc sr, r860and r9, r861ldc r8, sr62mov.l r7, @-r1563mov.l r6, @-r1564mov.l r5, @-r1565mov.l r4, @-r1566mov.l r3, @-r1567mov.l r2, @-r1568mov.l r1, @-r1569mov.l r0, @-r157071mov.l r4, @-r15 /* save indirection page again */7273bsr swap_pages /* swap pages before jumping to new kernel */74nop7576mova 11f, r077mov.l r15, @r0 /* save pointer to stack */7879jsr @r6 /* hand over control to new kernel */80nop8182mov.l 11f, r15 /* get pointer to stack */83mov.l @r15+, r4 /* restore r4 to get indirection page */8485bsr swap_pages /* swap pages back to previous state */86nop8788/* make sure bank0 is active and restore r0->r7 */89mov.l 12f, r990not r9, r991stc sr, r892and r9, r893ldc r8, sr94mov.l @r15+, r095mov.l @r15+, r196mov.l @r15+, r297mov.l @r15+, r398mov.l @r15+, r499mov.l @r15+, r5100mov.l @r15+, r6101mov.l @r15+, r7102103/* switch to bank1 and restore r0->r7 */104mov.l 12f, r9105stc sr, r8106or r9, r8107ldc r8, sr108mov.l @r15+, r0109mov.l @r15+, r1110mov.l @r15+, r2111mov.l @r15+, r3112mov.l @r15+, r4113mov.l @r15+, r5114mov.l @r15+, r6115mov.l @r15+, r7116117/* switch back to bank0 */118mov.l 12f, r9119not r9, r9120stc sr, r8121and r9, r8122ldc r8, sr123124/* restore other random registers */125ldc.l @r15+, spc126lds.l @r15+, pr127ldc.l @r15+, sr128ldc.l @r15+, ssr129ldc.l @r15+, gbr130lds.l @r15+, mach131lds.l @r15+, macl132133/* restore r8->r15 */134mov.l @r15+, r8135mov.l @r15+, r9136mov.l @r15+, r10137mov.l @r15+, r11138mov.l @r15+, r12139mov.l @r15+, r13140mov.l @r15+, r14141mov.l @r15+, r15142rts143nop144145swap_pages:146bra 1f147mov r4,r0 /* cmd = indirection_page */1480:149mov.l @r4+,r0 /* cmd = *ind++ */1501511: /* addr = cmd & 0xfffffff0 */152mov r0,r2153mov #-16,r1154and r1,r2155156/* if(cmd & IND_DESTINATION) dst = addr */157tst #1,r0158bt 2f159bra 0b160mov r2,r51611622: /* else if(cmd & IND_INDIRECTION) ind = addr */163tst #2,r0164bt 3f165bra 0b166mov r2,r41671683: /* else if(cmd & IND_DONE) return */169tst #4,r0170bt 4f171rts172nop1731744: /* else if(cmd & IND_SOURCE) memcpy(dst,addr,PAGE_SIZE) */175tst #8,r0176bt 0b177178mov.l 10f,r3 /* PAGE_SIZE */179shlr2 r3180shlr2 r31815:182dt r3183184/* regular kexec just overwrites the destination page185* with the contents of the source page.186* for the kexec jump case we need to swap the contents187* of the pages.188* to keep it simple swap the contents for both cases.189*/190mov.l @(0, r2), r8191mov.l @(0, r5), r1192mov.l r8, @(0, r5)193mov.l r1, @(0, r2)194195mov.l @(4, r2), r8196mov.l @(4, r5), r1197mov.l r8, @(4, r5)198mov.l r1, @(4, r2)199200mov.l @(8, r2), r8201mov.l @(8, r5), r1202mov.l r8, @(8, r5)203mov.l r1, @(8, r2)204205mov.l @(12, r2), r8206mov.l @(12, r5), r1207mov.l r8, @(12, r5)208mov.l r1, @(12, r2)209210add #16,r5211add #16,r2212bf 5b213214bra 0b215nop216217.align 221810:219.long PAGE_SIZE22011:221.long 022212:223.long 0x20000000 ! RB=1224225relocate_new_kernel_end:226227.globl relocate_new_kernel_size228relocate_new_kernel_size:229.long relocate_new_kernel_end - relocate_new_kernel230231232