1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Copyright IBM Corp. 2005 4 * 5 * Author(s): Rolf Adelsberger, 6 * Heiko Carstens <heiko.carstens@de.ibm.com> 7 * 8 */ 9 10#include <linux/linkage.h> 11#include <asm/page.h> 12#include <asm/sigp.h> 13 14/* 15 * moves the new kernel to its destination... 16 * %r2 = pointer to first kimage_entry_t 17 * %r3 = start address - where to jump to after the job is done... 18 * 19 * %r5 will be used as temp. storage 20 * %r6 holds the destination address 21 * %r7 = PAGE_SIZE 22 * %r8 holds the source address 23 * %r9 = PAGE_SIZE 24 * 25 * 0xf000 is a page_mask 26 */ 27 28 .text 29ENTRY(relocate_kernel) 30 basr %r13,0 # base address 31 .base: 32 stnsm sys_msk-.base(%r13),0xfb # disable DAT 33 stctg %c0,%c15,ctlregs-.base(%r13) 34 stmg %r0,%r15,gprregs-.base(%r13) 35 lghi %r0,3 36 sllg %r0,%r0,31 37 stg %r0,0x1d0(%r0) 38 la %r0,.back_pgm-.base(%r13) 39 stg %r0,0x1d8(%r0) 40 la %r1,load_psw-.base(%r13) 41 mvc 0(8,%r0),0(%r1) 42 la %r0,.back-.base(%r13) 43 st %r0,4(%r0) 44 oi 4(%r0),0x80 45 lghi %r0,0 46 diag %r0,%r0,0x308 47 .back: 48 lhi %r1,1 # mode 1 = esame 49 sigp %r1,%r0,SIGP_SET_ARCHITECTURE # switch to esame mode 50 sam64 # switch to 64 bit addressing mode 51 basr %r13,0 52 .back_base: 53 oi have_diag308-.back_base(%r13),0x01 54 lctlg %c0,%c15,ctlregs-.back_base(%r13) 55 lmg %r0,%r15,gprregs-.back_base(%r13) 56 j .top 57 .back_pgm: 58 lmg %r0,%r15,gprregs-.base(%r13) 59 .top: 60 lghi %r7,PAGE_SIZE # load PAGE_SIZE in r7 61 lghi %r9,PAGE_SIZE # load PAGE_SIZE in r9 62 lg %r5,0(%r2) # read another word for indirection page 63 aghi %r2,8 # increment pointer 64 tml %r5,0x1 # is it a destination page? 65 je .indir_check # NO, goto "indir_check" 66 lgr %r6,%r5 # r6 = r5 67 nill %r6,0xf000 # mask it out and... 68 j .top # ...next iteration 69 .indir_check: 70 tml %r5,0x2 # is it a indirection page? 71 je .done_test # NO, goto "done_test" 72 nill %r5,0xf000 # YES, mask out, 73 lgr %r2,%r5 # move it into the right register, 74 j .top # and read next... 75 .done_test: 76 tml %r5,0x4 # is it the done indicator? 77 je .source_test # NO! Well, then it should be the source indicator... 78 j .done # ok, lets finish it here... 79 .source_test: 80 tml %r5,0x8 # it should be a source indicator... 81 je .top # NO, ignore it... 82 lgr %r8,%r5 # r8 = r5 83 nill %r8,0xf000 # masking 84 0: mvcle %r6,%r8,0x0 # copy PAGE_SIZE bytes from r8 to r6 - pad with 0 85 jo 0b 86 j .top 87 .done: 88 sgr %r0,%r0 # clear register r0 89 la %r4,load_psw-.base(%r13) # load psw-address into the register 90 o %r3,4(%r4) # or load address into psw 91 st %r3,4(%r4) 92 mvc 0(8,%r0),0(%r4) # copy psw to absolute address 0 93 tm have_diag308-.base(%r13),0x01 94 jno .no_diag308 95 diag %r0,%r0,0x308 96 .no_diag308: 97 sam31 # 31 bit mode 98 sr %r1,%r1 # erase register r1 99 sr %r2,%r2 # erase register r2 100 sigp %r1,%r2,SIGP_SET_ARCHITECTURE # set cpuid to zero 101 lpsw 0 # hopefully start new kernel... 102 103 .align 8 104 load_psw: 105 .long 0x00080000,0x80000000 106 sys_msk: 107 .quad 0 108 ctlregs: 109 .rept 16 110 .quad 0 111 .endr 112 gprregs: 113 .rept 16 114 .quad 0 115 .endr 116 have_diag308: 117 .byte 0 118 .align 8 119 relocate_kernel_end: 120 .align 8 121 .globl relocate_kernel_len 122 relocate_kernel_len: 123 .quad relocate_kernel_end - relocate_kernel 124