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