1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (C) 2019 FORTH-ICS/CARV 4 * Nick Kossifidis <mick@ics.forth.gr> 5 */ 6 7 #include <asm/asm.h> /* For RISCV_* and REG 8 #include <asm/csr.h> /* For CSR_* macros */ 9 #include <asm/page.h> /* For PAGE_SIZE */ 10 #include <linux/linkage.h> /* For SYM_* macros 11 12 .section ".rodata" 13 SYM_CODE_START(riscv_kexec_relocate) 14 15 /* 16 * s0: Pointer to the current entry 17 * s1: (const) Phys address to jump to 18 * s2: (const) Phys address of the FDT 19 * s3: (const) The hartid of the curre 20 * s4: (const) kernel_map.va_pa_offset 21 * s5: Pointer to the destination addr 22 * s6: (const) Physical address of the 23 */ 24 mv s0, a0 25 mv s1, a1 26 mv s2, a2 27 mv s3, a3 28 mv s4, a4 29 mv s5, zero 30 mv s6, zero 31 32 /* Disable / cleanup interrupts */ 33 csrw CSR_SIE, zero 34 csrw CSR_SIP, zero 35 36 /* 37 * When we switch SATP.MODE to "Bare" 38 * play with physical addresses. Howev 39 * we try to jump somewhere, the offse 40 * will be relative to pc which will s 41 * deal with this we set stvec to the 42 * the start of the loop below so that 43 * any case. 44 */ 45 la s6, 1f 46 sub s6, s6, s4 47 csrw CSR_STVEC, s6 48 49 /* 50 * With C-extension, here we get 42 By 51 * .align directive would pad zeros he 52 * So manually put a nop here to avoid 53 */ 54 nop 55 56 /* Process entries in a loop */ 57 .align 2 58 1: 59 REG_L t0, 0(s0) /* t0 60 addi s0, s0, RISCV_SZPTR /* ima 61 62 /* IND_DESTINATION entry ? -> save des 63 andi t1, t0, 0x1 64 beqz t1, 2f 65 andi s5, t0, ~0x1 66 j 1b 67 68 2: 69 /* IND_INDIRECTION entry ? -> update n 70 andi t1, t0, 0x2 71 beqz t1, 2f 72 andi s0, t0, ~0x2 73 csrw CSR_SATP, zero 74 jr s6 75 76 2: 77 /* IND_DONE entry ? -> jump to done la 78 andi t1, t0, 0x4 79 beqz t1, 2f 80 j 4f 81 82 2: 83 /* 84 * IND_SOURCE entry ? -> copy page wor 85 * destination address we got from IND 86 */ 87 andi t1, t0, 0x8 88 beqz t1, 1b /* Unknown ent 89 andi t0, t0, ~0x8 90 li t3, (PAGE_SIZE / RISCV_SZPTR) 91 3: /* copy loop */ 92 REG_L t1, (t0) /* t1 = *src_p 93 REG_S t1, (s5) /* *dst_ptr = 94 addi t0, t0, RISCV_SZPTR /* stc_ptr 95 addi s5, s5, RISCV_SZPTR /* dst_ptr 96 addi t3, t3, -0x1 /* i-- */ 97 beqz t3, 1b /* copy done ? 98 j 3b 99 100 4: 101 /* Pass the arguments to the next kern 102 mv a0, s3 103 mv a1, s2 104 mv a2, s1 105 106 /* Cleanup */ 107 mv a3, zero 108 mv a4, zero 109 mv a5, zero 110 mv a6, zero 111 mv a7, zero 112 113 mv s0, zero 114 mv s1, zero 115 mv s2, zero 116 mv s3, zero 117 mv s4, zero 118 mv s5, zero 119 mv s6, zero 120 mv s7, zero 121 mv s8, zero 122 mv s9, zero 123 mv s10, zero 124 mv s11, zero 125 126 mv t0, zero 127 mv t1, zero 128 mv t2, zero 129 mv t3, zero 130 mv t4, zero 131 mv t5, zero 132 mv t6, zero 133 csrw CSR_SEPC, zero 134 csrw CSR_SCAUSE, zero 135 csrw CSR_SSCRATCH, zero 136 137 /* 138 * Make sure the relocated code is vis 139 * and jump to the new kernel 140 */ 141 fence.i 142 143 jr a2 144 145 SYM_CODE_END(riscv_kexec_relocate) 146 riscv_kexec_relocate_end: 147 148 149 /* Used for jumping to crashkernel */ 150 .section ".text" 151 SYM_CODE_START(riscv_kexec_norelocate) 152 /* 153 * s0: (const) Phys address to jump to 154 * s1: (const) Phys address of the FDT 155 * s2: (const) The hartid of the curre 156 */ 157 mv s0, a1 158 mv s1, a2 159 mv s2, a3 160 161 /* Disable / cleanup interrupts */ 162 csrw CSR_SIE, zero 163 csrw CSR_SIP, zero 164 165 /* Pass the arguments to the next kern 166 mv a0, s2 167 mv a1, s1 168 mv a2, s0 169 170 /* Cleanup */ 171 mv a3, zero 172 mv a4, zero 173 mv a5, zero 174 mv a6, zero 175 mv a7, zero 176 177 mv s0, zero 178 mv s1, zero 179 mv s2, zero 180 mv s3, zero 181 mv s4, zero 182 mv s5, zero 183 mv s6, zero 184 mv s7, zero 185 mv s8, zero 186 mv s9, zero 187 mv s10, zero 188 mv s11, zero 189 190 mv t0, zero 191 mv t1, zero 192 mv t2, zero 193 mv t3, zero 194 mv t4, zero 195 mv t5, zero 196 mv t6, zero 197 csrw CSR_SEPC, zero 198 csrw CSR_SCAUSE, zero 199 csrw CSR_SSCRATCH, zero 200 201 /* 202 * Switch to physical addressing 203 * This will also trigger a jump to CS 204 * which in this case is the address o 205 * kernel. 206 */ 207 csrw CSR_STVEC, a2 208 csrw CSR_SATP, zero 209 210 SYM_CODE_END(riscv_kexec_norelocate) 211 212 .section ".rodata" 213 SYM_DATA(riscv_kexec_relocate_size, 214 .long riscv_kexec_relocate_end - riscv 215
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.