powerpc/powermac: Fix low_sleep_handler with CONFIG_VMAP_STACK

low_sleep_handler() can't restore the context from standard
stack because the stack can hardly be accessed with MMU OFF.

Store everything in a global storage area instead of storing
a pointer to the stack in that global storage area.

To avoid a complete churn of the function, still use r1 as
the pointer to the storage area during restore.

Fixes: cd08f109e2 ("powerpc/32s: Enable CONFIG_VMAP_STACK")
Reported-by: Giuseppe Sacco <giuseppe@sguazz.it>
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Tested-by: Giuseppe Sacco <giuseppe@sguazz.it>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/e3e0d8042a3ba75cb4a9546c19c408b5b5b28994.1607404931.git.christophe.leroy@csgroup.eu
This commit is contained in:
Christophe Leroy 2020-12-08 05:24:19 +00:00 committed by Michael Ellerman
parent f8a4b277c3
commit db972a3787
2 changed files with 60 additions and 74 deletions

View file

@ -36,7 +36,7 @@ config PPC_BOOK3S_6xx
select PPC_HAVE_PMU_SUPPORT
select PPC_HAVE_KUEP
select PPC_HAVE_KUAP
select HAVE_ARCH_VMAP_STACK if !ADB_PMU
select HAVE_ARCH_VMAP_STACK
config PPC_85xx
bool "Freescale 85xx"

View file

@ -44,7 +44,8 @@
#define SL_TB 0xa0
#define SL_R2 0xa8
#define SL_CR 0xac
#define SL_R12 0xb0 /* r12 to r31 */
#define SL_LR 0xb0
#define SL_R12 0xb4 /* r12 to r31 */
#define SL_SIZE (SL_R12 + 80)
.section .text
@ -63,105 +64,107 @@ _GLOBAL(low_sleep_handler)
blr
#else
mflr r0
stw r0,4(r1)
stwu r1,-SL_SIZE(r1)
lis r11,sleep_storage@ha
addi r11,r11,sleep_storage@l
stw r0,SL_LR(r11)
mfcr r0
stw r0,SL_CR(r1)
stw r2,SL_R2(r1)
stmw r12,SL_R12(r1)
stw r0,SL_CR(r11)
stw r1,SL_SP(r11)
stw r2,SL_R2(r11)
stmw r12,SL_R12(r11)
/* Save MSR & SDR1 */
mfmsr r4
stw r4,SL_MSR(r1)
stw r4,SL_MSR(r11)
mfsdr1 r4
stw r4,SL_SDR1(r1)
stw r4,SL_SDR1(r11)
/* Get a stable timebase and save it */
1: mftbu r4
stw r4,SL_TB(r1)
stw r4,SL_TB(r11)
mftb r5
stw r5,SL_TB+4(r1)
stw r5,SL_TB+4(r11)
mftbu r3
cmpw r3,r4
bne 1b
/* Save SPRGs */
mfsprg r4,0
stw r4,SL_SPRG0(r1)
stw r4,SL_SPRG0(r11)
mfsprg r4,1
stw r4,SL_SPRG0+4(r1)
stw r4,SL_SPRG0+4(r11)
mfsprg r4,2
stw r4,SL_SPRG0+8(r1)
stw r4,SL_SPRG0+8(r11)
mfsprg r4,3
stw r4,SL_SPRG0+12(r1)
stw r4,SL_SPRG0+12(r11)
/* Save BATs */
mfdbatu r4,0
stw r4,SL_DBAT0(r1)
stw r4,SL_DBAT0(r11)
mfdbatl r4,0
stw r4,SL_DBAT0+4(r1)
stw r4,SL_DBAT0+4(r11)
mfdbatu r4,1
stw r4,SL_DBAT1(r1)
stw r4,SL_DBAT1(r11)
mfdbatl r4,1
stw r4,SL_DBAT1+4(r1)
stw r4,SL_DBAT1+4(r11)
mfdbatu r4,2
stw r4,SL_DBAT2(r1)
stw r4,SL_DBAT2(r11)
mfdbatl r4,2
stw r4,SL_DBAT2+4(r1)
stw r4,SL_DBAT2+4(r11)
mfdbatu r4,3
stw r4,SL_DBAT3(r1)
stw r4,SL_DBAT3(r11)
mfdbatl r4,3
stw r4,SL_DBAT3+4(r1)
stw r4,SL_DBAT3+4(r11)
mfibatu r4,0
stw r4,SL_IBAT0(r1)
stw r4,SL_IBAT0(r11)
mfibatl r4,0
stw r4,SL_IBAT0+4(r1)
stw r4,SL_IBAT0+4(r11)
mfibatu r4,1
stw r4,SL_IBAT1(r1)
stw r4,SL_IBAT1(r11)
mfibatl r4,1
stw r4,SL_IBAT1+4(r1)
stw r4,SL_IBAT1+4(r11)
mfibatu r4,2
stw r4,SL_IBAT2(r1)
stw r4,SL_IBAT2(r11)
mfibatl r4,2
stw r4,SL_IBAT2+4(r1)
stw r4,SL_IBAT2+4(r11)
mfibatu r4,3
stw r4,SL_IBAT3(r1)
stw r4,SL_IBAT3(r11)
mfibatl r4,3
stw r4,SL_IBAT3+4(r1)
stw r4,SL_IBAT3+4(r11)
BEGIN_MMU_FTR_SECTION
mfspr r4,SPRN_DBAT4U
stw r4,SL_DBAT4(r1)
stw r4,SL_DBAT4(r11)
mfspr r4,SPRN_DBAT4L
stw r4,SL_DBAT4+4(r1)
stw r4,SL_DBAT4+4(r11)
mfspr r4,SPRN_DBAT5U
stw r4,SL_DBAT5(r1)
stw r4,SL_DBAT5(r11)
mfspr r4,SPRN_DBAT5L
stw r4,SL_DBAT5+4(r1)
stw r4,SL_DBAT5+4(r11)
mfspr r4,SPRN_DBAT6U
stw r4,SL_DBAT6(r1)
stw r4,SL_DBAT6(r11)
mfspr r4,SPRN_DBAT6L
stw r4,SL_DBAT6+4(r1)
stw r4,SL_DBAT6+4(r11)
mfspr r4,SPRN_DBAT7U
stw r4,SL_DBAT7(r1)
stw r4,SL_DBAT7(r11)
mfspr r4,SPRN_DBAT7L
stw r4,SL_DBAT7+4(r1)
stw r4,SL_DBAT7+4(r11)
mfspr r4,SPRN_IBAT4U
stw r4,SL_IBAT4(r1)
stw r4,SL_IBAT4(r11)
mfspr r4,SPRN_IBAT4L
stw r4,SL_IBAT4+4(r1)
stw r4,SL_IBAT4+4(r11)
mfspr r4,SPRN_IBAT5U
stw r4,SL_IBAT5(r1)
stw r4,SL_IBAT5(r11)
mfspr r4,SPRN_IBAT5L
stw r4,SL_IBAT5+4(r1)
stw r4,SL_IBAT5+4(r11)
mfspr r4,SPRN_IBAT6U
stw r4,SL_IBAT6(r1)
stw r4,SL_IBAT6(r11)
mfspr r4,SPRN_IBAT6L
stw r4,SL_IBAT6+4(r1)
stw r4,SL_IBAT6+4(r11)
mfspr r4,SPRN_IBAT7U
stw r4,SL_IBAT7(r1)
stw r4,SL_IBAT7(r11)
mfspr r4,SPRN_IBAT7L
stw r4,SL_IBAT7+4(r1)
stw r4,SL_IBAT7+4(r11)
END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
/* Backup various CPU config stuffs */
@ -180,9 +183,9 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
lis r5,grackle_wake_up@ha
addi r5,r5,grackle_wake_up@l
tophys(r5,r5)
stw r5,SL_PC(r1)
stw r5,SL_PC(r11)
lis r4,KERNELBASE@h
tophys(r5,r1)
tophys(r5,r11)
addi r5,r5,SL_PC
lis r6,MAGIC@ha
addi r6,r6,MAGIC@l
@ -194,12 +197,6 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
tophys(r3,r3)
stw r3,0x80(r4)
stw r5,0x84(r4)
/* Store a pointer to our backup storage into
* a kernel global
*/
lis r3,sleep_storage@ha
addi r3,r3,sleep_storage@l
stw r5,0(r3)
.globl low_cpu_offline_self
low_cpu_offline_self:
@ -279,7 +276,7 @@ _GLOBAL(core99_wake_up)
lis r3,sleep_storage@ha
addi r3,r3,sleep_storage@l
tophys(r3,r3)
lwz r1,0(r3)
addi r1,r3,SL_PC
/* Pass thru to older resume code ... */
_ASM_NOKPROBE_SYMBOL(core99_wake_up)
@ -399,13 +396,6 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
blt 1b
sync
/* restore the MSR and turn on the MMU */
lwz r3,SL_MSR(r1)
bl turn_on_mmu
/* get back the stack pointer */
tovirt(r1,r1)
/* Restore TB */
li r3,0
mttbl r3
@ -419,28 +409,24 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
mtcr r0
lwz r2,SL_R2(r1)
lmw r12,SL_R12(r1)
addi r1,r1,SL_SIZE
lwz r0,4(r1)
mtlr r0
blr
_ASM_NOKPROBE_SYMBOL(grackle_wake_up)
turn_on_mmu:
mflr r4
tovirt(r4,r4)
/* restore the MSR and SP and turn on the MMU and return */
lwz r3,SL_MSR(r1)
lwz r4,SL_LR(r1)
lwz r1,SL_SP(r1)
mtsrr0 r4
mtsrr1 r3
sync
isync
rfi
_ASM_NOKPROBE_SYMBOL(turn_on_mmu)
_ASM_NOKPROBE_SYMBOL(grackle_wake_up)
#endif /* defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ) */
.section .data
.section .bss
.balign L1_CACHE_BYTES
sleep_storage:
.long 0
.space SL_SIZE
.balign L1_CACHE_BYTES, 0
#endif /* CONFIG_PPC_BOOK3S_32 */