1/* 2 * This is the analog to the kexec "purgatory" code 3 * 4 * The goal here is to call the actual kernel entry point with the arguments it 5 * expects when kexec calls into it with no arguments. The value of the kernel 6 * entry point and arguments r3-r7 are copied into the trampoline text (which 7 * can be executed from any address) at bytes 8-32. kexec begins execution 8 * of APs at 0x60 bytes past the entry point, executing in a copy relocated 9 * to the absolute address 0x60. Here we implement a loop waiting on the release 10 * of a lock by the kernel at 0x40. 11 * 12 * $FreeBSD: stable/11/stand/powerpc/kboot/kerneltramp.S 329183 2018-02-12 20:51:28Z kevans $ 13 */ 14 15#include <machine/asm.h> 16 17 .globl CNAME(kerneltramp),CNAME(szkerneltramp) 18CNAME(kerneltramp): 19 mflr %r9 20 bl 2f 21 .space 24 /* branch address, r3-r7 */ 22 23/* 24 * MUST BE IN SYNC WITH: 25 * struct trampoline_data { 26 * uint32_t kernel_entry; 27 * uint32_t dtb; 28 * uint32_t phys_mem_offset; 29 * uint32_t of_entry; 30 * uint32_t mdp; 31 * uint32_t mdp_size; 32 * }; 33 */ 34 35. = kerneltramp + 0x40 /* AP spinlock */ 36 .long 0 37 38. = kerneltramp + 0x60 /* AP entry point */ 39 li %r3,0x40 401: lwz %r1,0(%r3) 41 cmpwi %r1,0 42 beq 1b 43 44 /* Jump into CPU reset */ 45 li %r0,0x100 46 icbi 0,%r0 47 isync 48 sync 49 ba 0x100 50 512: /* Continuation of kerneltramp */ 52 mflr %r8 53 mtlr %r9 54 55 mfmsr %r10 56 andi. %r10, %r10, 1 /* test MSR_LE */ 57 bne little_endian 58 59/* We're starting in BE */ 60big_endian: 61 lwz %r3,4(%r8) 62 lwz %r4,8(%r8) 63 lwz %r5,12(%r8) 64 lwz %r6,16(%r8) 65 lwz %r7,20(%r8) 66 67 lwz %r10, 0(%r8) 68 mtctr %r10 69 bctr 70 71/* We're starting in LE */ 72little_endian: 73 74 /* Entries are BE, swap them during load. */ 75 li %r10, 4 76 lwbrx %r3, %r8, %r10 77 li %r10, 8 78 lwbrx %r4, %r8, %r10 79 li %r10, 12 80 lwbrx %r5, %r8, %r10 81 li %r10, 16 82 lwbrx %r6, %r8, %r10 83 li %r10, 20 84 lwbrx %r7, %r8, %r10 85 86 /* Clear MSR_LE flag to enter the BE world */ 87 mfmsr %r10 88 clrrdi %r10, %r10, 1 89 mtsrr1 %r10 90 91 /* Entry is at 0(%r8) */ 92 li %r10, 0 93 lwbrx %r10, %r8, %r10 94 mtsrr0 %r10 95 96 rfid 97 98endkerneltramp: 99 100 .data 101CNAME(szkerneltramp): 102 .long endkerneltramp - CNAME(kerneltramp) 103