[PATCH] powerpc/32s: fix suspend/resume when IBATs 4-7 are used

From: Christophe Leroy
Date: Mon Jun 17 2019 - 02:15:23 EST


Previously, only IBAT1 and IBAT2 were used to map kernel linear mem.
Since commit 63b2bc619565 ("powerpc/mm/32s: Use BATs for
STRICT_KERNEL_RWX"), we may have all 8 BATs used for mapping
kernel text. But the suspend/restore functions only save/restore
BATs 0 to 3, and clears BATs 4 to 7.

Make suspend and restore functions respectively save and reload
the 8 BATs on CPUs having MMU_FTR_USE_HIGH_BATS feature.

Reported-by: Andreas Schwab <schwab@xxxxxxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Christophe Leroy <christophe.leroy@xxxxxx>
---
arch/powerpc/kernel/swsusp_32.S | 108 +++++++++++++++++++++++++-------
arch/powerpc/platforms/powermac/sleep.S | 104 +++++++++++++++++++++++-------
2 files changed, 166 insertions(+), 46 deletions(-)

diff --git a/arch/powerpc/kernel/swsusp_32.S b/arch/powerpc/kernel/swsusp_32.S
index 7a919e9a3400..4d3068f24ff3 100644
--- a/arch/powerpc/kernel/swsusp_32.S
+++ b/arch/powerpc/kernel/swsusp_32.S
@@ -25,11 +25,19 @@
#define SL_IBAT2 0x48
#define SL_DBAT3 0x50
#define SL_IBAT3 0x58
-#define SL_TB 0x60
-#define SL_R2 0x68
-#define SL_CR 0x6c
-#define SL_LR 0x70
-#define SL_R12 0x74 /* r12 to r31 */
+#define SL_DBAT4 0x60
+#define SL_IBAT4 0x68
+#define SL_DBAT5 0x70
+#define SL_IBAT5 0x78
+#define SL_DBAT6 0x80
+#define SL_IBAT6 0x88
+#define SL_DBAT7 0x90
+#define SL_IBAT7 0x98
+#define SL_TB 0xa0
+#define SL_R2 0xa8
+#define SL_CR 0xac
+#define SL_LR 0xb0
+#define SL_R12 0xb4 /* r12 to r31 */
#define SL_SIZE (SL_R12 + 80)

.section .data
@@ -97,6 +105,24 @@ _GLOBAL(swsusp_arch_suspend)
stw r4,SL_DBAT3(r11)
mfdbatl r4,3
stw r4,SL_DBAT3+4(r11)
+BEGIN_MMU_FTR_SECTION
+ mfdbatu r4,4
+ stw r4,SL_DBAT4(r11)
+ mfdbatl r4,4
+ stw r4,SL_DBAT4+4(r11)
+ mfdbatu r4,5
+ stw r4,SL_DBAT5(r11)
+ mfdbatl r4,5
+ stw r4,SL_DBAT5+4(r11)
+ mfdbatu r4,6
+ stw r4,SL_DBAT6(r11)
+ mfdbatl r4,6
+ stw r4,SL_DBAT6+4(r11)
+ mfdbatu r4,7
+ stw r4,SL_DBAT7(r11)
+ mfdbatl r4,7
+ stw r4,SL_DBAT7+4(r11)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
mfibatu r4,0
stw r4,SL_IBAT0(r11)
mfibatl r4,0
@@ -113,6 +139,24 @@ _GLOBAL(swsusp_arch_suspend)
stw r4,SL_IBAT3(r11)
mfibatl r4,3
stw r4,SL_IBAT3+4(r11)
+BEGIN_MMU_FTR_SECTION
+ mfibatu r4,4
+ stw r4,SL_IBAT4(r11)
+ mfibatl r4,4
+ stw r4,SL_IBAT4+4(r11)
+ mfibatu r4,5
+ stw r4,SL_IBAT5(r11)
+ mfibatl r4,5
+ stw r4,SL_IBAT5+4(r11)
+ mfibatu r4,6
+ stw r4,SL_IBAT6(r11)
+ mfibatl r4,6
+ stw r4,SL_IBAT6+4(r11)
+ mfibatu r4,7
+ stw r4,SL_IBAT7(r11)
+ mfibatl r4,7
+ stw r4,SL_IBAT7+4(r11)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)

#if 0
/* Backup various CPU config stuffs */
@@ -263,6 +307,24 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
mtdbatu 3,r4
lwz r4,SL_DBAT3+4(r11)
mtdbatl 3,r4
+BEGIN_MMU_FTR_SECTION
+ lwz r4,SL_DBAT4(r11)
+ mtdbatu 4,r4
+ lwz r4,SL_DBAT4+4(r11)
+ mtdbatl 4,r4
+ lwz r4,SL_DBAT5(r11)
+ mtdbatu 5,r4
+ lwz r4,SL_DBAT5+4(r11)
+ mtdbatl 5,r4
+ lwz r4,SL_DBAT6(r11)
+ mtdbatu 6,r4
+ lwz r4,SL_DBAT6+4(r11)
+ mtdbatl 6,r4
+ lwz r4,SL_DBAT7(r11)
+ mtdbatu 7,r4
+ lwz r4,SL_DBAT7+4(r11)
+ mtdbatl 7,r4
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
lwz r4,SL_IBAT0(r11)
mtibatu 0,r4
lwz r4,SL_IBAT0+4(r11)
@@ -279,27 +341,25 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
mtibatu 3,r4
lwz r4,SL_IBAT3+4(r11)
mtibatl 3,r4
-#endif
-
BEGIN_MMU_FTR_SECTION
- li r4,0
- mtspr SPRN_DBAT4U,r4
- mtspr SPRN_DBAT4L,r4
- mtspr SPRN_DBAT5U,r4
- mtspr SPRN_DBAT5L,r4
- mtspr SPRN_DBAT6U,r4
- mtspr SPRN_DBAT6L,r4
- mtspr SPRN_DBAT7U,r4
- mtspr SPRN_DBAT7L,r4
- mtspr SPRN_IBAT4U,r4
- mtspr SPRN_IBAT4L,r4
- mtspr SPRN_IBAT5U,r4
- mtspr SPRN_IBAT5L,r4
- mtspr SPRN_IBAT6U,r4
- mtspr SPRN_IBAT6L,r4
- mtspr SPRN_IBAT7U,r4
- mtspr SPRN_IBAT7L,r4
+ lwz r4,SL_IBAT4(r11)
+ mtibatu 4,r4
+ lwz r4,SL_IBAT4+4(r11)
+ mtibatl 4,r4
+ lwz r4,SL_IBAT5(r11)
+ mtibatu 5,r4
+ lwz r4,SL_IBAT5+4(r11)
+ mtibatl 5,r4
+ lwz r4,SL_IBAT6(r11)
+ mtibatu 6,r4
+ lwz r4,SL_IBAT6+4(r11)
+ mtibatl 6,r4
+ lwz r4,SL_IBAT7(r11)
+ mtibatu 7,r4
+ lwz r4,SL_IBAT7+4(r11)
+ mtibatl 7,r4
END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
+#endif

/* Flush all TLBs */
lis r4,0x1000
diff --git a/arch/powerpc/platforms/powermac/sleep.S b/arch/powerpc/platforms/powermac/sleep.S
index 6bbcbec97712..2d7b035bee09 100644
--- a/arch/powerpc/platforms/powermac/sleep.S
+++ b/arch/powerpc/platforms/powermac/sleep.S
@@ -33,10 +33,18 @@
#define SL_IBAT2 0x48
#define SL_DBAT3 0x50
#define SL_IBAT3 0x58
-#define SL_TB 0x60
-#define SL_R2 0x68
-#define SL_CR 0x6c
-#define SL_R12 0x70 /* r12 to r31 */
+#define SL_DBAT4 0x60
+#define SL_IBAT4 0x68
+#define SL_DBAT5 0x70
+#define SL_IBAT5 0x78
+#define SL_DBAT6 0x80
+#define SL_IBAT6 0x88
+#define SL_DBAT7 0x90
+#define SL_IBAT7 0x98
+#define SL_TB 0xa0
+#define SL_R2 0xa8
+#define SL_CR 0xac
+#define SL_R12 0xb0 /* r12 to r31 */
#define SL_SIZE (SL_R12 + 80)

.section .text
@@ -104,6 +112,24 @@ _GLOBAL(low_sleep_handler)
stw r4,SL_DBAT3(r1)
mfdbatl r4,3
stw r4,SL_DBAT3+4(r1)
+BEGIN_MMU_FTR_SECTION
+ mfdbatu r4,4
+ stw r4,SL_DBAT4(r1)
+ mfdbatl r4,4
+ stw r4,SL_DBAT4+4(r1)
+ mfdbatu r4,5
+ stw r4,SL_DBAT5(r1)
+ mfdbatl r4,5
+ stw r4,SL_DBAT5+4(r1)
+ mfdbatu r4,6
+ stw r4,SL_DBAT6(r1)
+ mfdbatl r4,6
+ stw r4,SL_DBAT6+4(r1)
+ mfdbatu r4,7
+ stw r4,SL_DBAT7(r1)
+ mfdbatl r4,7
+ stw r4,SL_DBAT7+4(r1)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
mfibatu r4,0
stw r4,SL_IBAT0(r1)
mfibatl r4,0
@@ -120,6 +146,24 @@ _GLOBAL(low_sleep_handler)
stw r4,SL_IBAT3(r1)
mfibatl r4,3
stw r4,SL_IBAT3+4(r1)
+BEGIN_MMU_FTR_SECTION
+ mfibatu r4,4
+ stw r4,SL_IBAT4(r1)
+ mfibatl r4,4
+ stw r4,SL_IBAT4+4(r1)
+ mfibatu r4,5
+ stw r4,SL_IBAT5(r1)
+ mfibatl r4,5
+ stw r4,SL_IBAT5+4(r1)
+ mfibatu r4,6
+ stw r4,SL_IBAT6(r1)
+ mfibatl r4,6
+ stw r4,SL_IBAT6+4(r1)
+ mfibatu r4,7
+ stw r4,SL_IBAT7(r1)
+ mfibatl r4,7
+ stw r4,SL_IBAT7+4(r1)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)

/* Backup various CPU config stuffs */
bl __save_cpu_setup
@@ -303,6 +347,24 @@ grackle_wake_up:
mtdbatu 3,r4
lwz r4,SL_DBAT3+4(r1)
mtdbatl 3,r4
+BEGIN_MMU_FTR_SECTION
+ lwz r4,SL_DBAT4(r1)
+ mtdbatu 4,r4
+ lwz r4,SL_DBAT4+4(r1)
+ mtdbatl 4,r4
+ lwz r4,SL_DBAT5(r1)
+ mtdbatu 5,r4
+ lwz r4,SL_DBAT5+4(r1)
+ mtdbatl 5,r4
+ lwz r4,SL_DBAT6(r1)
+ mtdbatu 6,r4
+ lwz r4,SL_DBAT6+4(r1)
+ mtdbatl 6,r4
+ lwz r4,SL_DBAT7(r1)
+ mtdbatu 7,r4
+ lwz r4,SL_DBAT7+4(r1)
+ mtdbatl 7,r4
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
lwz r4,SL_IBAT0(r1)
mtibatu 0,r4
lwz r4,SL_IBAT0+4(r1)
@@ -319,25 +381,23 @@ grackle_wake_up:
mtibatu 3,r4
lwz r4,SL_IBAT3+4(r1)
mtibatl 3,r4
-
BEGIN_MMU_FTR_SECTION
- li r4,0
- mtspr SPRN_DBAT4U,r4
- mtspr SPRN_DBAT4L,r4
- mtspr SPRN_DBAT5U,r4
- mtspr SPRN_DBAT5L,r4
- mtspr SPRN_DBAT6U,r4
- mtspr SPRN_DBAT6L,r4
- mtspr SPRN_DBAT7U,r4
- mtspr SPRN_DBAT7L,r4
- mtspr SPRN_IBAT4U,r4
- mtspr SPRN_IBAT4L,r4
- mtspr SPRN_IBAT5U,r4
- mtspr SPRN_IBAT5L,r4
- mtspr SPRN_IBAT6U,r4
- mtspr SPRN_IBAT6L,r4
- mtspr SPRN_IBAT7U,r4
- mtspr SPRN_IBAT7L,r4
+ lwz r4,SL_IBAT4(r1)
+ mtibatu 4,r4
+ lwz r4,SL_IBAT4+4(r1)
+ mtibatl 4,r4
+ lwz r4,SL_IBAT5(r1)
+ mtibatu 5,r4
+ lwz r4,SL_IBAT5+4(r1)
+ mtibatl 5,r4
+ lwz r4,SL_IBAT6(r1)
+ mtibatu 6,r4
+ lwz r4,SL_IBAT6+4(r1)
+ mtibatl 6,r4
+ lwz r4,SL_IBAT7(r1)
+ mtibatu 7,r4
+ lwz r4,SL_IBAT7+4(r1)
+ mtibatl 7,r4
END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)

/* Flush all TLBs */
--
2.13.3