^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright IBM Corp. 2005
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author(s): Rolf Adelsberger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Heiko Carstens <heiko.carstens@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/linkage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/sigp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * moves the new kernel to its destination...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * %r2 = pointer to first kimage_entry_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * %r3 = start address - where to jump to after the job is done...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * %r5 will be used as temp. storage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * %r6 holds the destination address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * %r7 = PAGE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * %r8 holds the source address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * %r9 = PAGE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * 0xf000 is a page_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) .text
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) ENTRY(relocate_kernel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) basr %r13,0 # base address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) .base:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) lghi %r7,PAGE_SIZE # load PAGE_SIZE in r7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) lghi %r9,PAGE_SIZE # load PAGE_SIZE in r9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) lg %r5,0(%r2) # read another word for indirection page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) aghi %r2,8 # increment pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) tml %r5,0x1 # is it a destination page?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) je .indir_check # NO, goto "indir_check"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) lgr %r6,%r5 # r6 = r5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) nill %r6,0xf000 # mask it out and...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) j .base # ...next iteration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .indir_check:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) tml %r5,0x2 # is it a indirection page?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) je .done_test # NO, goto "done_test"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) nill %r5,0xf000 # YES, mask out,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) lgr %r2,%r5 # move it into the right register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) j .base # and read next...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .done_test:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) tml %r5,0x4 # is it the done indicator?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) je .source_test # NO! Well, then it should be the source indicator...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) j .done # ok, lets finish it here...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .source_test:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) tml %r5,0x8 # it should be a source indicator...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) je .base # NO, ignore it...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) lgr %r8,%r5 # r8 = r5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) nill %r8,0xf000 # masking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) 0: mvcle %r6,%r8,0x0 # copy PAGE_SIZE bytes from r8 to r6 - pad with 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) jo 0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) j .base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) sgr %r0,%r0 # clear register r0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) cghi %r3,0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) je .diag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) la %r4,load_psw-.base(%r13) # load psw-address into the register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) o %r3,4(%r4) # or load address into psw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) st %r3,4(%r4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) mvc 0(8,%r0),0(%r4) # copy psw to absolute address 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .diag:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) diag %r0,%r0,0x308
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ENDPROC(relocate_kernel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .align 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) load_psw:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .long 0x00080000,0x80000000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) relocate_kernel_end:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) .align 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) .globl relocate_kernel_len
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) relocate_kernel_len:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .quad relocate_kernel_end - relocate_kernel