kerneltramp.S revision 329183
1276413Snwhitehorn/* 2276413Snwhitehorn * This is the analog to the kexec "purgatory" code 3276413Snwhitehorn * 4276413Snwhitehorn * The goal here is to call the actual kernel entry point with the arguments it 5276413Snwhitehorn * expects when kexec calls into it with no arguments. The value of the kernel 6276687Snwhitehorn * entry point and arguments r3-r7 are copied into the trampoline text (which 7276687Snwhitehorn * can be executed from any address) at bytes 8-32. kexec begins execution 8276687Snwhitehorn * of APs at 0x60 bytes past the entry point, executing in a copy relocated 9276687Snwhitehorn * to the absolute address 0x60. Here we implement a loop waiting on the release 10276687Snwhitehorn * of a lock by the kernel at 0x40. 11276413Snwhitehorn * 12277997Snwhitehorn * $FreeBSD: stable/11/stand/powerpc/kboot/kerneltramp.S 329183 2018-02-12 20:51:28Z kevans $ 13276413Snwhitehorn */ 14276413Snwhitehorn 15276413Snwhitehorn#include <machine/asm.h> 16276413Snwhitehorn 17276413Snwhitehorn .globl CNAME(kerneltramp),CNAME(szkerneltramp) 18276413SnwhitehornCNAME(kerneltramp): 19276413Snwhitehorn mflr %r9 20276687Snwhitehorn bl 2f 21276413Snwhitehorn .space 24 /* branch address, r3-r7 */ 22276687Snwhitehorn 23329183Skevans/* 24329183Skevans * MUST BE IN SYNC WITH: 25329183Skevans * struct trampoline_data { 26329183Skevans * uint32_t kernel_entry; 27329183Skevans * uint32_t dtb; 28329183Skevans * uint32_t phys_mem_offset; 29329183Skevans * uint32_t of_entry; 30329183Skevans * uint32_t mdp; 31329183Skevans * uint32_t mdp_size; 32329183Skevans * }; 33329183Skevans */ 34329183Skevans 35276687Snwhitehorn. = kerneltramp + 0x40 /* AP spinlock */ 36276687Snwhitehorn .long 0 37276687Snwhitehorn 38276687Snwhitehorn. = kerneltramp + 0x60 /* AP entry point */ 39276687Snwhitehorn li %r3,0x40 40276687Snwhitehorn1: lwz %r1,0(%r3) 41276687Snwhitehorn cmpwi %r1,0 42276687Snwhitehorn beq 1b 43276687Snwhitehorn 44276687Snwhitehorn /* Jump into CPU reset */ 45276687Snwhitehorn li %r0,0x100 46276687Snwhitehorn icbi 0,%r0 47276687Snwhitehorn isync 48276687Snwhitehorn sync 49276687Snwhitehorn ba 0x100 50276687Snwhitehorn 51329183Skevans2: /* Continuation of kerneltramp */ 52276413Snwhitehorn mflr %r8 53276413Snwhitehorn mtlr %r9 54329183Skevans 55329183Skevans mfmsr %r10 56329183Skevans andi. %r10, %r10, 1 /* test MSR_LE */ 57329183Skevans bne little_endian 58329183Skevans 59329183Skevans/* We're starting in BE */ 60329183Skevansbig_endian: 61276413Snwhitehorn lwz %r3,4(%r8) 62276413Snwhitehorn lwz %r4,8(%r8) 63276413Snwhitehorn lwz %r5,12(%r8) 64276413Snwhitehorn lwz %r6,16(%r8) 65276413Snwhitehorn lwz %r7,20(%r8) 66329183Skevans 67329183Skevans lwz %r10, 0(%r8) 68329183Skevans mtctr %r10 69276413Snwhitehorn bctr 70329183Skevans 71329183Skevans/* We're starting in LE */ 72329183Skevanslittle_endian: 73329183Skevans 74329183Skevans /* Entries are BE, swap them during load. */ 75329183Skevans li %r10, 4 76329183Skevans lwbrx %r3, %r8, %r10 77329183Skevans li %r10, 8 78329183Skevans lwbrx %r4, %r8, %r10 79329183Skevans li %r10, 12 80329183Skevans lwbrx %r5, %r8, %r10 81329183Skevans li %r10, 16 82329183Skevans lwbrx %r6, %r8, %r10 83329183Skevans li %r10, 20 84329183Skevans lwbrx %r7, %r8, %r10 85329183Skevans 86329183Skevans /* Clear MSR_LE flag to enter the BE world */ 87329183Skevans mfmsr %r10 88329183Skevans clrrdi %r10, %r10, 1 89329183Skevans mtsrr1 %r10 90329183Skevans 91329183Skevans /* Entry is at 0(%r8) */ 92329183Skevans li %r10, 0 93329183Skevans lwbrx %r10, %r8, %r10 94329183Skevans mtsrr0 %r10 95329183Skevans 96329183Skevans rfid 97329183Skevans 98276413Snwhitehornendkerneltramp: 99276413Snwhitehorn 100276413Snwhitehorn .data 101276413SnwhitehornCNAME(szkerneltramp): 102276413Snwhitehorn .long endkerneltramp - CNAME(kerneltramp) 103