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 */ 13 14#include <machine/asm.h> 15 16 .globl CNAME(kerneltramp),CNAME(szkerneltramp) 17CNAME(kerneltramp): 18 mflr %r9 19 bl 2f 20 .space 24 /* branch address, r3-r7 */ 21 22/* 23 * MUST BE IN SYNC WITH: 24 * struct trampoline_data { 25 * uint32_t kernel_entry; 26 * uint32_t dtb; 27 * uint32_t phys_mem_offset; 28 * uint32_t of_entry; 29 * uint32_t mdp; 30 * uint32_t mdp_size; 31 * }; 32 */ 33 34. = kerneltramp + 0x40 /* AP spinlock */ 35 .long 0 36 37. = kerneltramp + 0x60 /* AP entry point */ 38 li %r3,0x40 391: lwz %r1,0(%r3) 40 cmpwi %r1,0 41 beq 1b 42 43 /* Jump into CPU reset */ 44 li %r0,0x100 45 icbi 0,%r0 46 isync 47 sync 48 ba 0x100 49 502: /* Continuation of kerneltramp */ 51 mflr %r8 52 mtlr %r9 53 54 mfmsr %r10 55 andi. %r10, %r10, 1 /* test MSR_LE */ 56 bne little_endian 57 58/* We're starting in BE */ 59big_endian: 60 lwz %r3,4(%r8) 61 lwz %r4,8(%r8) 62 lwz %r5,12(%r8) 63 lwz %r6,16(%r8) 64 lwz %r7,20(%r8) 65 66 lwz %r10, 0(%r8) 67 mtctr %r10 68 bctr 69 70/* We're starting in LE */ 71little_endian: 72 73 /* Entries are BE, swap them during load. */ 74 li %r10, 4 75 lwbrx %r3, %r8, %r10 76 li %r10, 8 77 lwbrx %r4, %r8, %r10 78 li %r10, 12 79 lwbrx %r5, %r8, %r10 80 li %r10, 16 81 lwbrx %r6, %r8, %r10 82 li %r10, 20 83 lwbrx %r7, %r8, %r10 84 85 /* Clear MSR_LE flag to enter the BE world */ 86 mfmsr %r10 87 clrrdi %r10, %r10, 1 88 mtsrr1 %r10 89 90 /* Entry is at 0(%r8) */ 91 li %r10, 0 92 lwbrx %r10, %r8, %r10 93 mtsrr0 %r10 94 95 rfid 96 97endkerneltramp: 98 99 .data 100CNAME(szkerneltramp): 101 .long endkerneltramp - CNAME(kerneltramp) 102