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