xref: /openbmc/linux/arch/powerpc/kexec/relocate_32.S (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1793b08e2SChristophe Leroy/* SPDX-License-Identifier: GPL-2.0-or-later */
2793b08e2SChristophe Leroy/*
3793b08e2SChristophe Leroy * This file contains kexec low-level functions.
4793b08e2SChristophe Leroy *
5793b08e2SChristophe Leroy * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
6793b08e2SChristophe Leroy * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
7793b08e2SChristophe Leroy * PPC44x port. Copyright (C) 2011,  IBM Corporation
8793b08e2SChristophe Leroy * 		Author: Suzuki Poulose <suzuki@in.ibm.com>
9793b08e2SChristophe Leroy */
10793b08e2SChristophe Leroy
11793b08e2SChristophe Leroy#include <asm/reg.h>
12793b08e2SChristophe Leroy#include <asm/page.h>
13793b08e2SChristophe Leroy#include <asm/mmu.h>
14793b08e2SChristophe Leroy#include <asm/ppc_asm.h>
15793b08e2SChristophe Leroy#include <asm/kexec.h>
16793b08e2SChristophe Leroy
17793b08e2SChristophe Leroy	.text
18793b08e2SChristophe Leroy
19793b08e2SChristophe Leroy	/*
20793b08e2SChristophe Leroy	 * Must be relocatable PIC code callable as a C function.
21793b08e2SChristophe Leroy	 */
22793b08e2SChristophe Leroy	.globl relocate_new_kernel
23793b08e2SChristophe Leroyrelocate_new_kernel:
24793b08e2SChristophe Leroy	/* r3 = page_list   */
25793b08e2SChristophe Leroy	/* r4 = reboot_code_buffer */
26793b08e2SChristophe Leroy	/* r5 = start_address      */
27793b08e2SChristophe Leroy
28*dfc3095cSChristophe Leroy#ifdef CONFIG_PPC_85xx
29793b08e2SChristophe Leroy
30793b08e2SChristophe Leroy	mr	r29, r3
31793b08e2SChristophe Leroy	mr	r30, r4
32793b08e2SChristophe Leroy	mr	r31, r5
33793b08e2SChristophe Leroy
34793b08e2SChristophe Leroy#define ENTRY_MAPPING_KEXEC_SETUP
35*dfc3095cSChristophe Leroy#include <kernel/85xx_entry_mapping.S>
36793b08e2SChristophe Leroy#undef ENTRY_MAPPING_KEXEC_SETUP
37793b08e2SChristophe Leroy
38793b08e2SChristophe Leroy	mr      r3, r29
39793b08e2SChristophe Leroy	mr      r4, r30
40793b08e2SChristophe Leroy	mr      r5, r31
41793b08e2SChristophe Leroy
42793b08e2SChristophe Leroy	li	r0, 0
43793b08e2SChristophe Leroy#elif defined(CONFIG_44x)
44793b08e2SChristophe Leroy
45793b08e2SChristophe Leroy	/* Save our parameters */
46793b08e2SChristophe Leroy	mr	r29, r3
47793b08e2SChristophe Leroy	mr	r30, r4
48793b08e2SChristophe Leroy	mr	r31, r5
49793b08e2SChristophe Leroy
50793b08e2SChristophe Leroy#ifdef CONFIG_PPC_47x
51793b08e2SChristophe Leroy	/* Check for 47x cores */
52793b08e2SChristophe Leroy	mfspr	r3,SPRN_PVR
53793b08e2SChristophe Leroy	srwi	r3,r3,16
54793b08e2SChristophe Leroy	cmplwi	cr0,r3,PVR_476FPE@h
55793b08e2SChristophe Leroy	beq	setup_map_47x
56793b08e2SChristophe Leroy	cmplwi	cr0,r3,PVR_476@h
57793b08e2SChristophe Leroy	beq	setup_map_47x
58793b08e2SChristophe Leroy	cmplwi	cr0,r3,PVR_476_ISS@h
59793b08e2SChristophe Leroy	beq	setup_map_47x
60793b08e2SChristophe Leroy#endif /* CONFIG_PPC_47x */
61793b08e2SChristophe Leroy
62793b08e2SChristophe Leroy/*
63793b08e2SChristophe Leroy * Code for setting up 1:1 mapping for PPC440x for KEXEC
64793b08e2SChristophe Leroy *
65793b08e2SChristophe Leroy * We cannot switch off the MMU on PPC44x.
66793b08e2SChristophe Leroy * So we:
67793b08e2SChristophe Leroy * 1) Invalidate all the mappings except the one we are running from.
68793b08e2SChristophe Leroy * 2) Create a tmp mapping for our code in the other address space(TS) and
69793b08e2SChristophe Leroy *    jump to it. Invalidate the entry we started in.
70793b08e2SChristophe Leroy * 3) Create a 1:1 mapping for 0-2GiB in chunks of 256M in original TS.
71793b08e2SChristophe Leroy * 4) Jump to the 1:1 mapping in original TS.
72793b08e2SChristophe Leroy * 5) Invalidate the tmp mapping.
73793b08e2SChristophe Leroy *
74793b08e2SChristophe Leroy * - Based on the kexec support code for FSL BookE
75793b08e2SChristophe Leroy *
76793b08e2SChristophe Leroy */
77793b08e2SChristophe Leroy
78793b08e2SChristophe Leroy	/*
79793b08e2SChristophe Leroy	 * Load the PID with kernel PID (0).
80793b08e2SChristophe Leroy	 * Also load our MSR_IS and TID to MMUCR for TLB search.
81793b08e2SChristophe Leroy	 */
82793b08e2SChristophe Leroy	li	r3, 0
83793b08e2SChristophe Leroy	mtspr	SPRN_PID, r3
84793b08e2SChristophe Leroy	mfmsr	r4
85793b08e2SChristophe Leroy	andi.	r4,r4,MSR_IS@l
86793b08e2SChristophe Leroy	beq	wmmucr
87793b08e2SChristophe Leroy	oris	r3,r3,PPC44x_MMUCR_STS@h
88793b08e2SChristophe Leroywmmucr:
89793b08e2SChristophe Leroy	mtspr	SPRN_MMUCR,r3
90793b08e2SChristophe Leroy	sync
91793b08e2SChristophe Leroy
92793b08e2SChristophe Leroy	/*
93793b08e2SChristophe Leroy	 * Invalidate all the TLB entries except the current entry
94793b08e2SChristophe Leroy	 * where we are running from
95793b08e2SChristophe Leroy	 */
9633e14024SChristophe Leroy	bcl	20,31,$+4			/* Find our address */
97793b08e2SChristophe Leroy0:	mflr	r5				/* Make it accessible */
98793b08e2SChristophe Leroy	tlbsx	r23,0,r5			/* Find entry we are in */
99793b08e2SChristophe Leroy	li	r4,0				/* Start at TLB entry 0 */
100793b08e2SChristophe Leroy	li	r3,0				/* Set PAGEID inval value */
101793b08e2SChristophe Leroy1:	cmpw	r23,r4				/* Is this our entry? */
102793b08e2SChristophe Leroy	beq	skip				/* If so, skip the inval */
103793b08e2SChristophe Leroy	tlbwe	r3,r4,PPC44x_TLB_PAGEID		/* If not, inval the entry */
104793b08e2SChristophe Leroyskip:
105793b08e2SChristophe Leroy	addi	r4,r4,1				/* Increment */
106793b08e2SChristophe Leroy	cmpwi	r4,64				/* Are we done?	*/
107793b08e2SChristophe Leroy	bne	1b				/* If not, repeat */
108793b08e2SChristophe Leroy	isync
109793b08e2SChristophe Leroy
110793b08e2SChristophe Leroy	/* Create a temp mapping and jump to it */
111793b08e2SChristophe Leroy	andi.	r6, r23, 1		/* Find the index to use */
112793b08e2SChristophe Leroy	addi	r24, r6, 1		/* r24 will contain 1 or 2 */
113793b08e2SChristophe Leroy
114793b08e2SChristophe Leroy	mfmsr	r9			/* get the MSR */
115793b08e2SChristophe Leroy	rlwinm	r5, r9, 27, 31, 31	/* Extract the MSR[IS] */
116793b08e2SChristophe Leroy	xori	r7, r5, 1		/* Use the other address space */
117793b08e2SChristophe Leroy
118793b08e2SChristophe Leroy	/* Read the current mapping entries */
119793b08e2SChristophe Leroy	tlbre	r3, r23, PPC44x_TLB_PAGEID
120793b08e2SChristophe Leroy	tlbre	r4, r23, PPC44x_TLB_XLAT
121793b08e2SChristophe Leroy	tlbre	r5, r23, PPC44x_TLB_ATTRIB
122793b08e2SChristophe Leroy
123793b08e2SChristophe Leroy	/* Save our current XLAT entry */
124793b08e2SChristophe Leroy	mr	r25, r4
125793b08e2SChristophe Leroy
126793b08e2SChristophe Leroy	/* Extract the TLB PageSize */
127793b08e2SChristophe Leroy	li	r10, 1 			/* r10 will hold PageSize */
128793b08e2SChristophe Leroy	rlwinm	r11, r3, 0, 24, 27	/* bits 24-27 */
129793b08e2SChristophe Leroy
130793b08e2SChristophe Leroy	/* XXX: As of now we use 256M, 4K pages */
131793b08e2SChristophe Leroy	cmpwi	r11, PPC44x_TLB_256M
132793b08e2SChristophe Leroy	bne	tlb_4k
133793b08e2SChristophe Leroy	rotlwi	r10, r10, 28		/* r10 = 256M */
134793b08e2SChristophe Leroy	b	write_out
135793b08e2SChristophe Leroytlb_4k:
136793b08e2SChristophe Leroy	cmpwi	r11, PPC44x_TLB_4K
137793b08e2SChristophe Leroy	bne	default
138793b08e2SChristophe Leroy	rotlwi	r10, r10, 12		/* r10 = 4K */
139793b08e2SChristophe Leroy	b	write_out
140793b08e2SChristophe Leroydefault:
141793b08e2SChristophe Leroy	rotlwi	r10, r10, 10		/* r10 = 1K */
142793b08e2SChristophe Leroy
143793b08e2SChristophe Leroywrite_out:
144793b08e2SChristophe Leroy	/*
145793b08e2SChristophe Leroy	 * Write out the tmp 1:1 mapping for this code in other address space
146793b08e2SChristophe Leroy	 * Fixup  EPN = RPN , TS=other address space
147793b08e2SChristophe Leroy	 */
148793b08e2SChristophe Leroy	insrwi	r3, r7, 1, 23		/* Bit 23 is TS for PAGEID field */
149793b08e2SChristophe Leroy
150793b08e2SChristophe Leroy	/* Write out the tmp mapping entries */
151793b08e2SChristophe Leroy	tlbwe	r3, r24, PPC44x_TLB_PAGEID
152793b08e2SChristophe Leroy	tlbwe	r4, r24, PPC44x_TLB_XLAT
153793b08e2SChristophe Leroy	tlbwe	r5, r24, PPC44x_TLB_ATTRIB
154793b08e2SChristophe Leroy
155793b08e2SChristophe Leroy	subi	r11, r10, 1		/* PageOffset Mask = PageSize - 1 */
156793b08e2SChristophe Leroy	not	r10, r11		/* Mask for PageNum */
157793b08e2SChristophe Leroy
158793b08e2SChristophe Leroy	/* Switch to other address space in MSR */
159793b08e2SChristophe Leroy	insrwi	r9, r7, 1, 26		/* Set MSR[IS] = r7 */
160793b08e2SChristophe Leroy
16133e14024SChristophe Leroy	bcl	20,31,$+4
162793b08e2SChristophe Leroy1:	mflr	r8
163793b08e2SChristophe Leroy	addi	r8, r8, (2f-1b)		/* Find the target offset */
164793b08e2SChristophe Leroy
165793b08e2SChristophe Leroy	/* Jump to the tmp mapping */
166793b08e2SChristophe Leroy	mtspr	SPRN_SRR0, r8
167793b08e2SChristophe Leroy	mtspr	SPRN_SRR1, r9
168793b08e2SChristophe Leroy	rfi
169793b08e2SChristophe Leroy
170793b08e2SChristophe Leroy2:
171793b08e2SChristophe Leroy	/* Invalidate the entry we were executing from */
172793b08e2SChristophe Leroy	li	r3, 0
173793b08e2SChristophe Leroy	tlbwe	r3, r23, PPC44x_TLB_PAGEID
174793b08e2SChristophe Leroy
175793b08e2SChristophe Leroy	/* attribute fields. rwx for SUPERVISOR mode */
176793b08e2SChristophe Leroy	li	r5, 0
177793b08e2SChristophe Leroy	ori	r5, r5, (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G)
178793b08e2SChristophe Leroy
179793b08e2SChristophe Leroy	/* Create 1:1 mapping in 256M pages */
180793b08e2SChristophe Leroy	xori	r7, r7, 1			/* Revert back to Original TS */
181793b08e2SChristophe Leroy
182793b08e2SChristophe Leroy	li	r8, 0				/* PageNumber */
183793b08e2SChristophe Leroy	li	r6, 3				/* TLB Index, start at 3  */
184793b08e2SChristophe Leroy
185793b08e2SChristophe Leroynext_tlb:
186793b08e2SChristophe Leroy	rotlwi	r3, r8, 28			/* Create EPN (bits 0-3) */
187793b08e2SChristophe Leroy	mr	r4, r3				/* RPN = EPN  */
188793b08e2SChristophe Leroy	ori	r3, r3, (PPC44x_TLB_VALID | PPC44x_TLB_256M) /* SIZE = 256M, Valid */
189793b08e2SChristophe Leroy	insrwi	r3, r7, 1, 23			/* Set TS from r7 */
190793b08e2SChristophe Leroy
191793b08e2SChristophe Leroy	tlbwe	r3, r6, PPC44x_TLB_PAGEID	/* PageID field : EPN, V, SIZE */
192793b08e2SChristophe Leroy	tlbwe	r4, r6, PPC44x_TLB_XLAT		/* Address translation : RPN   */
193793b08e2SChristophe Leroy	tlbwe	r5, r6, PPC44x_TLB_ATTRIB	/* Attributes */
194793b08e2SChristophe Leroy
195793b08e2SChristophe Leroy	addi	r8, r8, 1			/* Increment PN */
196793b08e2SChristophe Leroy	addi	r6, r6, 1			/* Increment TLB Index */
197793b08e2SChristophe Leroy	cmpwi	r8, 8				/* Are we done ? */
198793b08e2SChristophe Leroy	bne	next_tlb
199793b08e2SChristophe Leroy	isync
200793b08e2SChristophe Leroy
201793b08e2SChristophe Leroy	/* Jump to the new mapping 1:1 */
202793b08e2SChristophe Leroy	li	r9,0
203793b08e2SChristophe Leroy	insrwi	r9, r7, 1, 26			/* Set MSR[IS] = r7 */
204793b08e2SChristophe Leroy
20533e14024SChristophe Leroy	bcl	20,31,$+4
206793b08e2SChristophe Leroy1:	mflr	r8
207793b08e2SChristophe Leroy	and	r8, r8, r11			/* Get our offset within page */
208793b08e2SChristophe Leroy	addi	r8, r8, (2f-1b)
209793b08e2SChristophe Leroy
210793b08e2SChristophe Leroy	and	r5, r25, r10			/* Get our target PageNum */
211793b08e2SChristophe Leroy	or	r8, r8, r5			/* Target jump address */
212793b08e2SChristophe Leroy
213793b08e2SChristophe Leroy	mtspr	SPRN_SRR0, r8
214793b08e2SChristophe Leroy	mtspr	SPRN_SRR1, r9
215793b08e2SChristophe Leroy	rfi
216793b08e2SChristophe Leroy2:
217793b08e2SChristophe Leroy	/* Invalidate the tmp entry we used */
218793b08e2SChristophe Leroy	li	r3, 0
219793b08e2SChristophe Leroy	tlbwe	r3, r24, PPC44x_TLB_PAGEID
220793b08e2SChristophe Leroy	sync
221793b08e2SChristophe Leroy	b	ppc44x_map_done
222793b08e2SChristophe Leroy
223793b08e2SChristophe Leroy#ifdef CONFIG_PPC_47x
224793b08e2SChristophe Leroy
225793b08e2SChristophe Leroy	/* 1:1 mapping for 47x */
226793b08e2SChristophe Leroy
227793b08e2SChristophe Leroysetup_map_47x:
228793b08e2SChristophe Leroy
229793b08e2SChristophe Leroy	/*
230793b08e2SChristophe Leroy	 * Load the kernel pid (0) to PID and also to MMUCR[TID].
231793b08e2SChristophe Leroy	 * Also set the MSR IS->MMUCR STS
232793b08e2SChristophe Leroy	 */
233793b08e2SChristophe Leroy	li	r3, 0
234793b08e2SChristophe Leroy	mtspr	SPRN_PID, r3			/* Set PID */
235793b08e2SChristophe Leroy	mfmsr	r4				/* Get MSR */
236793b08e2SChristophe Leroy	andi.	r4, r4, MSR_IS@l		/* TS=1? */
237793b08e2SChristophe Leroy	beq	1f				/* If not, leave STS=0 */
238793b08e2SChristophe Leroy	oris	r3, r3, PPC47x_MMUCR_STS@h	/* Set STS=1 */
239793b08e2SChristophe Leroy1:	mtspr	SPRN_MMUCR, r3			/* Put MMUCR */
240793b08e2SChristophe Leroy	sync
241793b08e2SChristophe Leroy
242793b08e2SChristophe Leroy	/* Find the entry we are running from */
24333e14024SChristophe Leroy	bcl	20,31,$+4
244793b08e2SChristophe Leroy2:	mflr	r23
245793b08e2SChristophe Leroy	tlbsx	r23, 0, r23
246793b08e2SChristophe Leroy	tlbre	r24, r23, 0			/* TLB Word 0 */
247793b08e2SChristophe Leroy	tlbre	r25, r23, 1			/* TLB Word 1 */
248793b08e2SChristophe Leroy	tlbre	r26, r23, 2			/* TLB Word 2 */
249793b08e2SChristophe Leroy
250793b08e2SChristophe Leroy
251793b08e2SChristophe Leroy	/*
252793b08e2SChristophe Leroy	 * Invalidates all the tlb entries by writing to 256 RPNs(r4)
253793b08e2SChristophe Leroy	 * of 4k page size in all  4 ways (0-3 in r3).
254793b08e2SChristophe Leroy	 * This would invalidate the entire UTLB including the one we are
255793b08e2SChristophe Leroy	 * running from. However the shadow TLB entries would help us
256793b08e2SChristophe Leroy	 * to continue the execution, until we flush them (rfi/isync).
257793b08e2SChristophe Leroy	 */
258793b08e2SChristophe Leroy	addis	r3, 0, 0x8000			/* specify the way */
259793b08e2SChristophe Leroy	addi	r4, 0, 0			/* TLB Word0 = (EPN=0, VALID = 0) */
260793b08e2SChristophe Leroy	addi	r5, 0, 0
261793b08e2SChristophe Leroy	b	clear_utlb_entry
262793b08e2SChristophe Leroy
263793b08e2SChristophe Leroy	/* Align the loop to speed things up. from head_44x.S */
264793b08e2SChristophe Leroy	.align	6
265793b08e2SChristophe Leroy
266793b08e2SChristophe Leroyclear_utlb_entry:
267793b08e2SChristophe Leroy
268793b08e2SChristophe Leroy	tlbwe	r4, r3, 0
269793b08e2SChristophe Leroy	tlbwe	r5, r3, 1
270793b08e2SChristophe Leroy	tlbwe	r5, r3, 2
271793b08e2SChristophe Leroy	addis	r3, r3, 0x2000			/* Increment the way */
272793b08e2SChristophe Leroy	cmpwi	r3, 0
273793b08e2SChristophe Leroy	bne	clear_utlb_entry
274793b08e2SChristophe Leroy	addis	r3, 0, 0x8000
275793b08e2SChristophe Leroy	addis	r4, r4, 0x100			/* Increment the EPN */
276793b08e2SChristophe Leroy	cmpwi	r4, 0
277793b08e2SChristophe Leroy	bne	clear_utlb_entry
278793b08e2SChristophe Leroy
279793b08e2SChristophe Leroy	/* Create the entries in the other address space */
280793b08e2SChristophe Leroy	mfmsr	r5
281793b08e2SChristophe Leroy	rlwinm	r7, r5, 27, 31, 31		/* Get the TS (Bit 26) from MSR */
282793b08e2SChristophe Leroy	xori	r7, r7, 1			/* r7 = !TS */
283793b08e2SChristophe Leroy
284793b08e2SChristophe Leroy	insrwi	r24, r7, 1, 21			/* Change the TS in the saved TLB word 0 */
285793b08e2SChristophe Leroy
286793b08e2SChristophe Leroy	/*
287793b08e2SChristophe Leroy	 * write out the TLB entries for the tmp mapping
288793b08e2SChristophe Leroy	 * Use way '0' so that we could easily invalidate it later.
289793b08e2SChristophe Leroy	 */
290793b08e2SChristophe Leroy	lis	r3, 0x8000			/* Way '0' */
291793b08e2SChristophe Leroy
292793b08e2SChristophe Leroy	tlbwe	r24, r3, 0
293793b08e2SChristophe Leroy	tlbwe	r25, r3, 1
294793b08e2SChristophe Leroy	tlbwe	r26, r3, 2
295793b08e2SChristophe Leroy
296793b08e2SChristophe Leroy	/* Update the msr to the new TS */
297793b08e2SChristophe Leroy	insrwi	r5, r7, 1, 26
298793b08e2SChristophe Leroy
29933e14024SChristophe Leroy	bcl	20,31,$+4
300793b08e2SChristophe Leroy1:	mflr	r6
301793b08e2SChristophe Leroy	addi	r6, r6, (2f-1b)
302793b08e2SChristophe Leroy
303793b08e2SChristophe Leroy	mtspr	SPRN_SRR0, r6
304793b08e2SChristophe Leroy	mtspr	SPRN_SRR1, r5
305793b08e2SChristophe Leroy	rfi
306793b08e2SChristophe Leroy
307793b08e2SChristophe Leroy	/*
308793b08e2SChristophe Leroy	 * Now we are in the tmp address space.
309793b08e2SChristophe Leroy	 * Create a 1:1 mapping for 0-2GiB in the original TS.
310793b08e2SChristophe Leroy	 */
311793b08e2SChristophe Leroy2:
312793b08e2SChristophe Leroy	li	r3, 0
313793b08e2SChristophe Leroy	li	r4, 0				/* TLB Word 0 */
314793b08e2SChristophe Leroy	li	r5, 0				/* TLB Word 1 */
315793b08e2SChristophe Leroy	li	r6, 0
316793b08e2SChristophe Leroy	ori	r6, r6, PPC47x_TLB2_S_RWX	/* TLB word 2 */
317793b08e2SChristophe Leroy
318793b08e2SChristophe Leroy	li	r8, 0				/* PageIndex */
319793b08e2SChristophe Leroy
320793b08e2SChristophe Leroy	xori	r7, r7, 1			/* revert back to original TS */
321793b08e2SChristophe Leroy
322793b08e2SChristophe Leroywrite_utlb:
323793b08e2SChristophe Leroy	rotlwi	r5, r8, 28			/* RPN = PageIndex * 256M */
324793b08e2SChristophe Leroy						/* ERPN = 0 as we don't use memory above 2G */
325793b08e2SChristophe Leroy
326793b08e2SChristophe Leroy	mr	r4, r5				/* EPN = RPN */
327793b08e2SChristophe Leroy	ori	r4, r4, (PPC47x_TLB0_VALID | PPC47x_TLB0_256M)
328793b08e2SChristophe Leroy	insrwi	r4, r7, 1, 21			/* Insert the TS to Word 0 */
329793b08e2SChristophe Leroy
330793b08e2SChristophe Leroy	tlbwe	r4, r3, 0			/* Write out the entries */
331793b08e2SChristophe Leroy	tlbwe	r5, r3, 1
332793b08e2SChristophe Leroy	tlbwe	r6, r3, 2
333793b08e2SChristophe Leroy	addi	r8, r8, 1
334793b08e2SChristophe Leroy	cmpwi	r8, 8				/* Have we completed ? */
335793b08e2SChristophe Leroy	bne	write_utlb
336793b08e2SChristophe Leroy
337793b08e2SChristophe Leroy	/* make sure we complete the TLB write up */
338793b08e2SChristophe Leroy	isync
339793b08e2SChristophe Leroy
340793b08e2SChristophe Leroy	/*
341793b08e2SChristophe Leroy	 * Prepare to jump to the 1:1 mapping.
342793b08e2SChristophe Leroy	 * 1) Extract page size of the tmp mapping
343793b08e2SChristophe Leroy	 *    DSIZ = TLB_Word0[22:27]
344793b08e2SChristophe Leroy	 * 2) Calculate the physical address of the address
345793b08e2SChristophe Leroy	 *    to jump to.
346793b08e2SChristophe Leroy	 */
347793b08e2SChristophe Leroy	rlwinm	r10, r24, 0, 22, 27
348793b08e2SChristophe Leroy
349793b08e2SChristophe Leroy	cmpwi	r10, PPC47x_TLB0_4K
350793b08e2SChristophe Leroy	bne	0f
351793b08e2SChristophe Leroy	li	r10, 0x1000			/* r10 = 4k */
352793b08e2SChristophe Leroy	bl	1f
353793b08e2SChristophe Leroy
354793b08e2SChristophe Leroy0:
355793b08e2SChristophe Leroy	/* Defaults to 256M */
356793b08e2SChristophe Leroy	lis	r10, 0x1000
357793b08e2SChristophe Leroy
35833e14024SChristophe Leroy	bcl	20,31,$+4
359793b08e2SChristophe Leroy1:	mflr	r4
360793b08e2SChristophe Leroy	addi	r4, r4, (2f-1b)			/* virtual address  of 2f */
361793b08e2SChristophe Leroy
362793b08e2SChristophe Leroy	subi	r11, r10, 1			/* offsetmask = Pagesize - 1 */
363793b08e2SChristophe Leroy	not	r10, r11			/* Pagemask = ~(offsetmask) */
364793b08e2SChristophe Leroy
365793b08e2SChristophe Leroy	and	r5, r25, r10			/* Physical page */
366793b08e2SChristophe Leroy	and	r6, r4, r11			/* offset within the current page */
367793b08e2SChristophe Leroy
368793b08e2SChristophe Leroy	or	r5, r5, r6			/* Physical address for 2f */
369793b08e2SChristophe Leroy
370793b08e2SChristophe Leroy	/* Switch the TS in MSR to the original one */
371793b08e2SChristophe Leroy	mfmsr	r8
372793b08e2SChristophe Leroy	insrwi	r8, r7, 1, 26
373793b08e2SChristophe Leroy
374793b08e2SChristophe Leroy	mtspr	SPRN_SRR1, r8
375793b08e2SChristophe Leroy	mtspr	SPRN_SRR0, r5
376793b08e2SChristophe Leroy	rfi
377793b08e2SChristophe Leroy
378793b08e2SChristophe Leroy2:
379793b08e2SChristophe Leroy	/* Invalidate the tmp mapping */
380793b08e2SChristophe Leroy	lis	r3, 0x8000			/* Way '0' */
381793b08e2SChristophe Leroy
382793b08e2SChristophe Leroy	clrrwi	r24, r24, 12			/* Clear the valid bit */
383793b08e2SChristophe Leroy	tlbwe	r24, r3, 0
384793b08e2SChristophe Leroy	tlbwe	r25, r3, 1
385793b08e2SChristophe Leroy	tlbwe	r26, r3, 2
386793b08e2SChristophe Leroy
387793b08e2SChristophe Leroy	/* Make sure we complete the TLB write and flush the shadow TLB */
388793b08e2SChristophe Leroy	isync
389793b08e2SChristophe Leroy
390793b08e2SChristophe Leroy#endif
391793b08e2SChristophe Leroy
392793b08e2SChristophe Leroyppc44x_map_done:
393793b08e2SChristophe Leroy
394793b08e2SChristophe Leroy
395793b08e2SChristophe Leroy	/* Restore the parameters */
396793b08e2SChristophe Leroy	mr	r3, r29
397793b08e2SChristophe Leroy	mr	r4, r30
398793b08e2SChristophe Leroy	mr	r5, r31
399793b08e2SChristophe Leroy
400793b08e2SChristophe Leroy	li	r0, 0
401793b08e2SChristophe Leroy#else
402793b08e2SChristophe Leroy	li	r0, 0
403793b08e2SChristophe Leroy
404793b08e2SChristophe Leroy	/*
405793b08e2SChristophe Leroy	 * Set Machine Status Register to a known status,
406793b08e2SChristophe Leroy	 * switch the MMU off and jump to 1: in a single step.
407793b08e2SChristophe Leroy	 */
408793b08e2SChristophe Leroy
409793b08e2SChristophe Leroy	mr	r8, r0
410793b08e2SChristophe Leroy	ori     r8, r8, MSR_RI|MSR_ME
411793b08e2SChristophe Leroy	mtspr	SPRN_SRR1, r8
412793b08e2SChristophe Leroy	addi	r8, r4, 1f - relocate_new_kernel
413793b08e2SChristophe Leroy	mtspr	SPRN_SRR0, r8
414793b08e2SChristophe Leroy	sync
415793b08e2SChristophe Leroy	rfi
416793b08e2SChristophe Leroy
417793b08e2SChristophe Leroy1:
418793b08e2SChristophe Leroy#endif
419793b08e2SChristophe Leroy	/* from this point address translation is turned off */
420793b08e2SChristophe Leroy	/* and interrupts are disabled */
421793b08e2SChristophe Leroy
422793b08e2SChristophe Leroy	/* set a new stack at the bottom of our page... */
423793b08e2SChristophe Leroy	/* (not really needed now) */
424793b08e2SChristophe Leroy	addi	r1, r4, KEXEC_CONTROL_PAGE_SIZE - 8 /* for LR Save+Back Chain */
425793b08e2SChristophe Leroy	stw	r0, 0(r1)
426793b08e2SChristophe Leroy
427793b08e2SChristophe Leroy	/* Do the copies */
428793b08e2SChristophe Leroy	li	r6, 0 /* checksum */
429793b08e2SChristophe Leroy	mr	r0, r3
430793b08e2SChristophe Leroy	b	1f
431793b08e2SChristophe Leroy
432793b08e2SChristophe Leroy0:	/* top, read another word for the indirection page */
433793b08e2SChristophe Leroy	lwzu	r0, 4(r3)
434793b08e2SChristophe Leroy
435793b08e2SChristophe Leroy1:
436793b08e2SChristophe Leroy	/* is it a destination page? (r8) */
437793b08e2SChristophe Leroy	rlwinm.	r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */
438793b08e2SChristophe Leroy	beq	2f
439793b08e2SChristophe Leroy
440793b08e2SChristophe Leroy	rlwinm	r8, r0, 0, 0, 19 /* clear kexec flags, page align */
441793b08e2SChristophe Leroy	b	0b
442793b08e2SChristophe Leroy
443793b08e2SChristophe Leroy2:	/* is it an indirection page? (r3) */
444793b08e2SChristophe Leroy	rlwinm.	r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */
445793b08e2SChristophe Leroy	beq	2f
446793b08e2SChristophe Leroy
447793b08e2SChristophe Leroy	rlwinm	r3, r0, 0, 0, 19 /* clear kexec flags, page align */
448793b08e2SChristophe Leroy	subi	r3, r3, 4
449793b08e2SChristophe Leroy	b	0b
450793b08e2SChristophe Leroy
451793b08e2SChristophe Leroy2:	/* are we done? */
452793b08e2SChristophe Leroy	rlwinm.	r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */
453793b08e2SChristophe Leroy	beq	2f
454793b08e2SChristophe Leroy	b	3f
455793b08e2SChristophe Leroy
456793b08e2SChristophe Leroy2:	/* is it a source page? (r9) */
457793b08e2SChristophe Leroy	rlwinm.	r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */
458793b08e2SChristophe Leroy	beq	0b
459793b08e2SChristophe Leroy
460793b08e2SChristophe Leroy	rlwinm	r9, r0, 0, 0, 19 /* clear kexec flags, page align */
461793b08e2SChristophe Leroy
462793b08e2SChristophe Leroy	li	r7, PAGE_SIZE / 4
463793b08e2SChristophe Leroy	mtctr   r7
464793b08e2SChristophe Leroy	subi    r9, r9, 4
465793b08e2SChristophe Leroy	subi    r8, r8, 4
466793b08e2SChristophe Leroy9:
467793b08e2SChristophe Leroy	lwzu    r0, 4(r9)  /* do the copy */
468793b08e2SChristophe Leroy	xor	r6, r6, r0
469793b08e2SChristophe Leroy	stwu    r0, 4(r8)
470793b08e2SChristophe Leroy	dcbst	0, r8
471793b08e2SChristophe Leroy	sync
472793b08e2SChristophe Leroy	icbi	0, r8
473793b08e2SChristophe Leroy	bdnz    9b
474793b08e2SChristophe Leroy
475793b08e2SChristophe Leroy	addi    r9, r9, 4
476793b08e2SChristophe Leroy	addi    r8, r8, 4
477793b08e2SChristophe Leroy	b	0b
478793b08e2SChristophe Leroy
479793b08e2SChristophe Leroy3:
480793b08e2SChristophe Leroy
481793b08e2SChristophe Leroy	/* To be certain of avoiding problems with self-modifying code
482793b08e2SChristophe Leroy	 * execute a serializing instruction here.
483793b08e2SChristophe Leroy	 */
484793b08e2SChristophe Leroy	isync
485793b08e2SChristophe Leroy	sync
486793b08e2SChristophe Leroy
487793b08e2SChristophe Leroy	mfspr	r3, SPRN_PIR /* current core we are running on */
488793b08e2SChristophe Leroy	mr	r4, r5 /* load physical address of chunk called */
489793b08e2SChristophe Leroy
490793b08e2SChristophe Leroy	/* jump to the entry point, usually the setup routine */
491793b08e2SChristophe Leroy	mtlr	r5
492793b08e2SChristophe Leroy	blrl
493793b08e2SChristophe Leroy
494793b08e2SChristophe Leroy1:	b	1b
495793b08e2SChristophe Leroy
496793b08e2SChristophe Leroyrelocate_new_kernel_end:
497793b08e2SChristophe Leroy
498793b08e2SChristophe Leroy	.globl relocate_new_kernel_size
499793b08e2SChristophe Leroyrelocate_new_kernel_size:
500793b08e2SChristophe Leroy	.long relocate_new_kernel_end - relocate_new_kernel
501