Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | /* SPDX-License-Identifier: GPL-2.0-only */ /* * kexec trampoline * * Based on code taken from kexec-tools and kexec-lite. * * Copyright (C) 2004 - 2005, Milton D Miller II, IBM Corporation * Copyright (C) 2006, Mohan Kumar M, IBM Corporation * Copyright (C) 2013, Anton Blanchard, IBM Corporation */ #include <asm/asm-compat.h> #include <asm/crashdump-ppc64.h> .balign 256 .globl purgatory_start purgatory_start: b master /* ABI: possible run_at_load flag at 0x5c */ .org purgatory_start + 0x5c .globl run_at_load run_at_load: .long 0 .size run_at_load, . - run_at_load /* ABI: slaves start at 60 with r3=phys */ .org purgatory_start + 0x60 slave: b . /* ABI: end of copied region */ .org purgatory_start + 0x100 .size purgatory_start, . - purgatory_start /* * The above 0x100 bytes at purgatory_start are replaced with the * code from the kernel (or next stage) by setup_purgatory(). */ master: or %r1,%r1,%r1 /* low priority to let other threads catchup */ isync mr %r17,%r3 /* save cpu id to r17 */ mr %r15,%r4 /* save physical address in reg15 */ /* Work out where we're running */ bcl 20, 31, 0f 0: mflr %r18 /* * Copy BACKUP_SRC_SIZE bytes from BACKUP_SRC_START to * backup_start 8 bytes at a time. * * Use r3 = dest, r4 = src, r5 = size, r6 = count */ ld %r3, (backup_start - 0b)(%r18) cmpdi %cr0, %r3, 0 beq .Lskip_copy /* skip if there is no backup region */ lis %r5, BACKUP_SRC_SIZE@h ori %r5, %r5, BACKUP_SRC_SIZE@l cmpdi %cr0, %r5, 0 beq .Lskip_copy /* skip if copy size is zero */ lis %r4, BACKUP_SRC_START@h ori %r4, %r4, BACKUP_SRC_START@l li %r6, 0 .Lcopy_loop: ldx %r0, %r6, %r4 stdx %r0, %r6, %r3 addi %r6, %r6, 8 cmpld %cr0, %r6, %r5 blt .Lcopy_loop .Lskip_copy: or %r3,%r3,%r3 /* ok now to high priority, lets boot */ lis %r6,0x1 mtctr %r6 /* delay a bit for slaves to catch up */ bdnz . /* before we overwrite 0-100 again */ /* load device-tree address */ ld %r3, (dt_offset - 0b)(%r18) mr %r16,%r3 /* save dt address in reg16 */ li %r4,20 LWZX_BE %r6,%r3,%r4 /* fetch __be32 version number at byte 20 */ cmpwi %cr0,%r6,2 /* v2 or later? */ blt 1f li %r4,28 STWX_BE %r17,%r3,%r4 /* Store my cpu as __be32 at byte 28 */ 1: /* Load opal base and entry values in r8 & r9 respectively */ ld %r8,(opal_base - 0b)(%r18) ld %r9,(opal_entry - 0b)(%r18) /* load the kernel address */ ld %r4,(kernel - 0b)(%r18) /* load the run_at_load flag */ /* possibly patched by kexec */ ld %r6,(run_at_load - 0b)(%r18) /* and patch it into the kernel */ stw %r6,(0x5c)(%r4) mr %r3,%r16 /* restore dt address */ li %r5,0 /* r5 will be 0 for kernel */ mfmsr %r11 andi. %r10,%r11,1 /* test MSR_LE */ bne .Little_endian mtctr %r4 /* prepare branch to */ bctr /* start kernel */ .Little_endian: mtsrr0 %r4 /* prepare branch to */ clrrdi %r11,%r11,1 /* clear MSR_LE */ mtsrr1 %r11 rfid /* update MSR and start kernel */ .balign 8 .globl kernel kernel: .8byte 0x0 .size kernel, . - kernel .balign 8 .globl dt_offset dt_offset: .8byte 0x0 .size dt_offset, . - dt_offset .balign 8 .globl backup_start backup_start: .8byte 0x0 .size backup_start, . - backup_start .balign 8 .globl opal_base opal_base: .8byte 0x0 .size opal_base, . - opal_base .balign 8 .globl opal_entry opal_entry: .8byte 0x0 .size opal_entry, . - opal_entry .data .balign 8 .globl purgatory_sha256_digest purgatory_sha256_digest: .skip 32 .size purgatory_sha256_digest, . - purgatory_sha256_digest .balign 8 .globl purgatory_sha_regions purgatory_sha_regions: .skip 8 * 2 * 16 .size purgatory_sha_regions, . - purgatory_sha_regions |