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