aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/cpu.c38
-rw-r--r--core/init.c3
-rw-r--r--include/cpu.h1
-rw-r--r--include/opal-api.h9
-rw-r--r--include/processor.h1
5 files changed, 52 insertions, 0 deletions
diff --git a/core/cpu.c b/core/cpu.c
index 31f5c92..75c7008 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -49,10 +49,12 @@ unsigned int cpu_max_pir;
struct cpu_thread *boot_cpu;
static struct lock reinit_lock = LOCK_UNLOCKED;
static bool hile_supported;
+static bool radix_supported;
static unsigned long hid0_hile;
static unsigned long hid0_attn;
static bool pm_enabled;
static bool current_hile_mode;
+static bool current_radix_mode;
unsigned long cpu_secondary_start __force_data = 0;
@@ -700,6 +702,7 @@ void init_boot_cpu(void)
case PVR_TYPE_P9:
proc_gen = proc_gen_p9;
hile_supported = true;
+ radix_supported = true;
hid0_hile = SPR_HID0_POWER9_HILE;
hid0_attn = SPR_HID0_POWER9_ENABLE_ATTN;
break;
@@ -1060,11 +1063,27 @@ static int64_t cpu_change_all_hid0(struct hid0_change_req *req)
return OPAL_SUCCESS;
}
+void cpu_set_radix_mode(void)
+{
+ struct hid0_change_req req;
+
+ if (!radix_supported)
+ return;
+
+ req.clr_bits = 0;
+ req.set_bits = SPR_HID0_POWER9_RADIX;
+ cleanup_global_tlb();
+ current_radix_mode = true;
+ cpu_change_all_hid0(&req);
+}
+
void cpu_fast_reboot_complete(void)
{
/* Fast reboot will have cleared HID0:HILE */
current_hile_mode = false;
+ /* On P9, restore radix mode */
+ cpu_set_radix_mode();
}
static int64_t opal_reinit_cpus(uint64_t flags)
@@ -1129,6 +1148,25 @@ static int64_t opal_reinit_cpus(uint64_t flags)
}
}
+ /* If MMU mode change is supported */
+ if (radix_supported &&
+ (flags & (OPAL_REINIT_CPUS_MMU_HASH |
+ OPAL_REINIT_CPUS_MMU_RADIX))) {
+ bool radix = !!(flags & OPAL_REINIT_CPUS_MMU_RADIX);
+
+ flags &= ~(OPAL_REINIT_CPUS_MMU_HASH |
+ OPAL_REINIT_CPUS_MMU_RADIX);
+ if (radix != current_radix_mode) {
+ if (radix)
+ req.set_bits |= SPR_HID0_POWER9_RADIX;
+ else
+ req.clr_bits |= SPR_HID0_POWER9_RADIX;
+
+ cleanup_global_tlb();
+ current_radix_mode = radix;
+ }
+ }
+
/* Apply HID bits changes if any */
if (req.set_bits || req.clr_bits)
cpu_change_all_hid0(&req);
diff --git a/core/init.c b/core/init.c
index 244a78f..9ffbc72 100644
--- a/core/init.c
+++ b/core/init.c
@@ -1045,6 +1045,9 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
prd_register_reserved_memory();
+ /* On P9, switch to radix mode by default */
+ cpu_set_radix_mode();
+
load_and_boot_kernel(false);
}
diff --git a/include/cpu.h b/include/cpu.h
index 1d19c20..fd3acf7 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -270,6 +270,7 @@ extern unsigned long __attrconst cpu_stack_top(unsigned int pir);
extern void cpu_idle_job(void);
extern void cpu_idle_delay(unsigned long delay, unsigned long min_pm);
+extern void cpu_set_radix_mode(void);
extern void cpu_fast_reboot_complete(void);
#endif /* __CPU_H */
diff --git a/include/opal-api.h b/include/opal-api.h
index 2713490..8ffdd4b 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -1014,6 +1014,15 @@ struct OpalIoPhb4ErrorData {
enum {
OPAL_REINIT_CPUS_HILE_BE = (1 << 0),
OPAL_REINIT_CPUS_HILE_LE = (1 << 1),
+
+ /* These two define the base MMU mode of the host on P9
+ *
+ * On P9 Nimbus DD2.0 and Cumlus (and later), KVM can still
+ * create hash guests in "radix" mode with care (full core
+ * switch only).
+ */
+ OPAL_REINIT_CPUS_MMU_HASH = (1 << 2),
+ OPAL_REINIT_CPUS_MMU_RADIX = (1 << 3),
};
typedef struct oppanel_line {
diff --git a/include/processor.h b/include/processor.h
index 5906b86..af3fd2b 100644
--- a/include/processor.h
+++ b/include/processor.h
@@ -169,6 +169,7 @@
#define SPR_HID0_POWER9_HILE PPC_BIT(4)
#define SPR_HID0_POWER8_ENABLE_ATTN PPC_BIT(31)
#define SPR_HID0_POWER9_ENABLE_ATTN PPC_BIT(3)
+#define SPR_HID0_POWER9_RADIX PPC_BIT(8)
/* PVR bits */
#define SPR_PVR_TYPE 0xffff0000