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