From bf1e56533ef3a7e607d8e1f95f43656bd79c5f16 Mon Sep 17 00:00:00 2001
From: Michal Suchanek <msuchanek@suse.de>
Date: Thu, 11 Jan 2018 14:43:07 +0100
Subject: [PATCH] powerpc/pseries: rfi-flush: Call setup_rfi_flush() after LPM
migration
References: bsc#1068032
Patch-mainline: submitted https://patchwork.ozlabs.org/patch/873534/ https://patchwork.ozlabs.org/patch/873535/
We might have migrated to a machine that uses a different
flush type, or doesn't need flushing at all.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Ram Pai <linuxram@us.ibm.com>
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
---
arch/powerpc/include/asm/setup.h | 2 +-
arch/powerpc/kernel/setup_64.c | 34 +++++++++++++++++++++++++++----
arch/powerpc/platforms/pseries/mobility.c | 3 +++
arch/powerpc/platforms/pseries/pseries.h | 2 ++
arch/powerpc/platforms/pseries/setup.c | 2 +-
5 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
index 6825a67cc3db..3f160cd20107 100644
--- a/arch/powerpc/include/asm/setup.h
+++ b/arch/powerpc/include/asm/setup.h
@@ -48,7 +48,7 @@ enum l1d_flush_type {
L1D_FLUSH_MTTRIG = 0x8,
};
-void __init setup_rfi_flush(enum l1d_flush_type, bool enable);
+void setup_rfi_flush(enum l1d_flush_type, bool enable);
void do_rfi_flush_fixups(enum l1d_flush_type types);
#endif /* !__ASSEMBLY__ */
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index d72d7cd93066..60584d3380a0 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -817,11 +817,24 @@ void rfi_flush_enable(bool enable)
rfi_flush = enable;
}
-static void init_fallback_flush(void)
+static bool init_fallback_flush(void)
{
u64 l1d_size, limit;
int cpu;
+ if (l1d_flush_fallback_area)
+ return true;
+
+ /*
+ * Once the slab allocator is up it's too late to allocate the fallback
+ * flush area, so return an error. This should not really happen
+ * because we call the init_fallback_flush() early. Doing the
+ * allocation later might fail due to memory fragmentation so we want
+ * to avoid that.
+ */
+ if (slab_is_available())
+ return false;
+
l1d_size = ppc64_caches.l1d.size;
limit = min(safe_stack_limit(), ppc64_rma_size);
@@ -837,13 +850,26 @@ static void init_fallback_flush(void)
paca[cpu].rfi_flush_fallback_area = l1d_flush_fallback_area;
paca[cpu].l1d_flush_size = l1d_size;
}
+
+ return true;
}
-void __init setup_rfi_flush(enum l1d_flush_type types, bool enable)
+void setup_rfi_flush(enum l1d_flush_type types, bool enable)
{
- if (types & L1D_FLUSH_FALLBACK) {
- pr_info("rfi-flush: Using fallback displacement flush\n");
+ /*
+ * Allocate the fallback area early during boot even if the detected
+ * flush type doe not need it - it might change due to migration.
+ */
+ if (!no_rfi_flush)
init_fallback_flush();
+
+ if (types & L1D_FLUSH_FALLBACK) {
+ if (init_fallback_flush())
+ pr_info("rfi-flush: Using fallback displacement flush\n");
+ else {
+ pr_crit("rfi-flush: Error unable to use fallback displacement flush!\n");
+ types &= ~L1D_FLUSH_FALLBACK;
+ }
}
if (types & L1D_FLUSH_ORI)
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c
index 74efac61aae9..ac98e83a5eb2 100644
--- a/arch/powerpc/platforms/pseries/mobility.c
+++ b/arch/powerpc/platforms/pseries/mobility.c
@@ -348,6 +348,9 @@ void post_mobility_fixup(void)
printk(KERN_ERR "Post-mobility device tree update "
"failed: %d\n", rc);
+ /* Possibly switch to a new RFI flush type */
+ pseries_setup_rfi_flush();
+
return;
}
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index 72610bf58c9f..f46132c434f6 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -79,6 +79,8 @@ extern struct pci_controller_ops pseries_pci_controller_ops;
unsigned long pseries_memory_block_size(void);
+void pseries_setup_rfi_flush(void);
+
extern int CMO_PrPSP;
extern int CMO_SecPSP;
extern unsigned long CMO_PageSize;
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index ae4f596273b5..6ce54c17ca17 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -459,7 +459,7 @@ static void __init find_and_init_phbs(void)
of_pci_check_probe_only();
}
-static void pseries_setup_rfi_flush(void)
+void pseries_setup_rfi_flush(void)
{
struct h_cpu_char_result result;
enum l1d_flush_type types;
--
2.13.6