powerpc/47x: Kernel support for KEXEC

This patch adds support for creating 1:1 mapping for the PPC_47x during
a KEXEC. The implementation is similar to that of the PPC440x which is
described here :

	http://patchwork.ozlabs.org/patch/104323/

PPC_47x MMU :

The 47x uses Unified TLB 1024 entries, with 4-way associative mapping
(4 x 256 entries). The index to be used is calculated by the MMU by
hashing the PID, EPN and TS. The software can choose to specify the way
by setting bit 0(enable way select) and the way in bits 1-2 in the TLB
Word 0.

Implementation:

The patch erases all the UTLB entries which includes the tlb covering
the mapping for our code. The shadow TLB caches the mapping for the
running code which helps us to continue the execution until we do
isync/rfi. We then create a tmp mapping for the current code in the
other address space (TS) and switch to it.

Then we create a 1:1 mapping(EPN=RPN) for 0-2GiB in the original
address space and switch to the new mapping.

TODO: Add SMP support.

Signed-off-by: Suzuki K. Poulose <suzuki@in.ibm.com>
Signed-off-by: Josh Boyer <jwboyer@gmail.com>
This commit is contained in:
Suzuki Poulose 2012-04-15 22:27:18 +00:00 committed by Josh Boyer
parent f13bfcc696
commit 6834302003
2 changed files with 190 additions and 7 deletions

View File

@ -353,7 +353,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
config KEXEC
bool "kexec system call (EXPERIMENTAL)"
depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !PPC_47x)) && EXPERIMENTAL
depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP)) && EXPERIMENTAL
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot

View File

@ -738,8 +738,23 @@ relocate_new_kernel:
mr r5, r31
li r0, 0
#elif defined(CONFIG_44x) && !defined(CONFIG_PPC_47x)
#elif defined(CONFIG_44x)
/* Save our parameters */
mr r29, r3
mr r30, r4
mr r31, r5
#ifdef CONFIG_PPC_47x
/* Check for 47x cores */
mfspr r3,SPRN_PVR
srwi r3,r3,16
cmplwi cr0,r3,PVR_476@h
beq setup_map_47x
cmplwi cr0,r3,PVR_476_ISS@h
beq setup_map_47x
#endif /* CONFIG_PPC_47x */
/*
* Code for setting up 1:1 mapping for PPC440x for KEXEC
*
@ -753,13 +768,8 @@ relocate_new_kernel:
* 5) Invalidate the tmp mapping.
*
* - Based on the kexec support code for FSL BookE
* - Doesn't support 47x yet.
*
*/
/* Save our parameters */
mr r29, r3
mr r30, r4
mr r31, r5
/*
* Load the PID with kernel PID (0).
@ -904,6 +914,179 @@ next_tlb:
li r3, 0
tlbwe r3, r24, PPC44x_TLB_PAGEID
sync
b ppc44x_map_done
#ifdef CONFIG_PPC_47x
/* 1:1 mapping for 47x */
setup_map_47x:
/*
* Load the kernel pid (0) to PID and also to MMUCR[TID].
* Also set the MSR IS->MMUCR STS
*/
li r3, 0
mtspr SPRN_PID, r3 /* Set PID */
mfmsr r4 /* Get MSR */
andi. r4, r4, MSR_IS@l /* TS=1? */
beq 1f /* If not, leave STS=0 */
oris r3, r3, PPC47x_MMUCR_STS@h /* Set STS=1 */
1: mtspr SPRN_MMUCR, r3 /* Put MMUCR */
sync
/* Find the entry we are running from */
bl 2f
2: mflr r23
tlbsx r23, 0, r23
tlbre r24, r23, 0 /* TLB Word 0 */
tlbre r25, r23, 1 /* TLB Word 1 */
tlbre r26, r23, 2 /* TLB Word 2 */
/*
* Invalidates all the tlb entries by writing to 256 RPNs(r4)
* of 4k page size in all 4 ways (0-3 in r3).
* This would invalidate the entire UTLB including the one we are
* running from. However the shadow TLB entries would help us
* to continue the execution, until we flush them (rfi/isync).
*/
addis r3, 0, 0x8000 /* specify the way */
addi r4, 0, 0 /* TLB Word0 = (EPN=0, VALID = 0) */
addi r5, 0, 0
b clear_utlb_entry
/* Align the loop to speed things up. from head_44x.S */
.align 6
clear_utlb_entry:
tlbwe r4, r3, 0
tlbwe r5, r3, 1
tlbwe r5, r3, 2
addis r3, r3, 0x2000 /* Increment the way */
cmpwi r3, 0
bne clear_utlb_entry
addis r3, 0, 0x8000
addis r4, r4, 0x100 /* Increment the EPN */
cmpwi r4, 0
bne clear_utlb_entry
/* Create the entries in the other address space */
mfmsr r5
rlwinm r7, r5, 27, 31, 31 /* Get the TS (Bit 26) from MSR */
xori r7, r7, 1 /* r7 = !TS */
insrwi r24, r7, 1, 21 /* Change the TS in the saved TLB word 0 */
/*
* write out the TLB entries for the tmp mapping
* Use way '0' so that we could easily invalidate it later.
*/
lis r3, 0x8000 /* Way '0' */
tlbwe r24, r3, 0
tlbwe r25, r3, 1
tlbwe r26, r3, 2
/* Update the msr to the new TS */
insrwi r5, r7, 1, 26
bl 1f
1: mflr r6
addi r6, r6, (2f-1b)
mtspr SPRN_SRR0, r6
mtspr SPRN_SRR1, r5
rfi
/*
* Now we are in the tmp address space.
* Create a 1:1 mapping for 0-2GiB in the original TS.
*/
2:
li r3, 0
li r4, 0 /* TLB Word 0 */
li r5, 0 /* TLB Word 1 */
li r6, 0
ori r6, r6, PPC47x_TLB2_S_RWX /* TLB word 2 */
li r8, 0 /* PageIndex */
xori r7, r7, 1 /* revert back to original TS */
write_utlb:
rotlwi r5, r8, 28 /* RPN = PageIndex * 256M */
/* ERPN = 0 as we don't use memory above 2G */
mr r4, r5 /* EPN = RPN */
ori r4, r4, (PPC47x_TLB0_VALID | PPC47x_TLB0_256M)
insrwi r4, r7, 1, 21 /* Insert the TS to Word 0 */
tlbwe r4, r3, 0 /* Write out the entries */
tlbwe r5, r3, 1
tlbwe r6, r3, 2
addi r8, r8, 1
cmpwi r8, 8 /* Have we completed ? */
bne write_utlb
/* make sure we complete the TLB write up */
isync
/*
* Prepare to jump to the 1:1 mapping.
* 1) Extract page size of the tmp mapping
* DSIZ = TLB_Word0[22:27]
* 2) Calculate the physical address of the address
* to jump to.
*/
rlwinm r10, r24, 0, 22, 27
cmpwi r10, PPC47x_TLB0_4K
bne 0f
li r10, 0x1000 /* r10 = 4k */
bl 1f
0:
/* Defaults to 256M */
lis r10, 0x1000
bl 1f
1: mflr r4
addi r4, r4, (2f-1b) /* virtual address of 2f */
subi r11, r10, 1 /* offsetmask = Pagesize - 1 */
not r10, r11 /* Pagemask = ~(offsetmask) */
and r5, r25, r10 /* Physical page */
and r6, r4, r11 /* offset within the current page */
or r5, r5, r6 /* Physical address for 2f */
/* Switch the TS in MSR to the original one */
mfmsr r8
insrwi r8, r7, 1, 26
mtspr SPRN_SRR1, r8
mtspr SPRN_SRR0, r5
rfi
2:
/* Invalidate the tmp mapping */
lis r3, 0x8000 /* Way '0' */
clrrwi r24, r24, 12 /* Clear the valid bit */
tlbwe r24, r3, 0
tlbwe r25, r3, 1
tlbwe r26, r3, 2
/* Make sure we complete the TLB write and flush the shadow TLB */
isync
#endif
ppc44x_map_done:
/* Restore the parameters */
mr r3, r29