[Skiboot] [PATCH v2 22/23] cpu: Rework HILE change
Michael Neuling
mikey at neuling.org
Sun Jun 25 05:17:27 AEST 2017
From: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Create a more generic helper for changing HID0 bits on all
processors.
Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Signed-off-by: Michael Neuling <mikey at neuling.org>
---
core/cpu.c | 71 +++++++++++++++++++++++++++++++++---------------------
core/fast-reboot.c | 5 ++--
include/cpu.h | 3 ++-
3 files changed, 48 insertions(+), 31 deletions(-)
diff --git a/core/cpu.c b/core/cpu.c
index a083ed7e0d..31f5c928bb 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -52,6 +52,7 @@ static bool hile_supported;
static unsigned long hid0_hile;
static unsigned long hid0_attn;
static bool pm_enabled;
+static bool current_hile_mode;
unsigned long cpu_secondary_start __force_data = 0;
@@ -1024,44 +1025,51 @@ static int64_t opal_return_cpu(void)
}
opal_call(OPAL_RETURN_CPU, opal_return_cpu, 0);
-static void cpu_change_hile(void *hilep)
-{
- bool hile = *(bool *)hilep;
- unsigned long hid0;
-
- hid0 = mfspr(SPR_HID0);
- if (hile)
- hid0 |= hid0_hile;
- else
- hid0 &= ~hid0_hile;
- prlog(PR_DEBUG, "CPU: [%08x] HID0 set to 0x%016lx\n",
- this_cpu()->pir, hid0);
- set_hid0(hid0);
+struct hid0_change_req {
+ uint64_t clr_bits;
+ uint64_t set_bits;
+};
- this_cpu()->current_hile = hile;
+static void cpu_change_hid0(void *__req)
+{
+ struct hid0_change_req *req = __req;
+ unsigned long hid0, new_hid0;
+
+ hid0 = new_hid0 = mfspr(SPR_HID0);
+ new_hid0 &= ~req->clr_bits;
+ new_hid0 |= req->set_bits;
+ prlog(PR_DEBUG, "CPU: [%08x] HID0 change 0x%016lx -> 0x%016lx\n",
+ this_cpu()->pir, hid0, new_hid0);
+ set_hid0(new_hid0);
}
-static int64_t cpu_change_all_hile(bool hile)
+static int64_t cpu_change_all_hid0(struct hid0_change_req *req)
{
struct cpu_thread *cpu;
- prlog(PR_INFO, "CPU: Switching HILE on all CPUs to %d\n", hile);
-
for_each_available_cpu(cpu) {
- if (cpu->current_hile == hile)
+ if (!cpu_is_thread0(cpu))
continue;
if (cpu == this_cpu()) {
- cpu_change_hile(&hile);
+ cpu_change_hid0(req);
continue;
}
- cpu_wait_job(cpu_queue_job(cpu, "cpu_change_hile",
- cpu_change_hile, &hile), true);
+ cpu_wait_job(cpu_queue_job(cpu, "cpu_change_hid0",
+ cpu_change_hid0, req), true);
}
return OPAL_SUCCESS;
}
+void cpu_fast_reboot_complete(void)
+{
+ /* Fast reboot will have cleared HID0:HILE */
+ current_hile_mode = false;
+
+}
+
static int64_t opal_reinit_cpus(uint64_t flags)
{
+ struct hid0_change_req req = { 0, 0 };
struct cpu_thread *cpu;
int64_t rc = OPAL_SUCCESS;
int i;
@@ -1105,19 +1113,26 @@ static int64_t opal_reinit_cpus(uint64_t flags)
this_cpu()->in_reinit = true;
unlock(&reinit_lock);
- /*
- * If the flags affect endianness and we are on P8 DD2 or later, then
- * use the HID bit. We use the PVR (we could use the EC level in
- * the chip but the PVR is more readily available).
- */
+ /* If HILE change via HID0 is supported ... */
if (hile_supported &&
- (flags & (OPAL_REINIT_CPUS_HILE_BE | OPAL_REINIT_CPUS_HILE_LE))) {
+ (flags & (OPAL_REINIT_CPUS_HILE_BE |
+ OPAL_REINIT_CPUS_HILE_LE))) {
bool hile = !!(flags & OPAL_REINIT_CPUS_HILE_LE);
flags &= ~(OPAL_REINIT_CPUS_HILE_BE | OPAL_REINIT_CPUS_HILE_LE);
- rc = cpu_change_all_hile(hile);
+ if (hile != current_hile_mode) {
+ if (hile)
+ req.set_bits |= hid0_hile;
+ else
+ req.clr_bits |= hid0_hile;
+ current_hile_mode = hile;
+ }
}
+ /* Apply HID bits changes if any */
+ if (req.set_bits || req.clr_bits)
+ cpu_change_all_hid0(&req);
+
/* If we have a P7, error out for LE switch, do nothing for BE */
if (proc_gen < proc_gen_p8) {
if (flags & OPAL_REINIT_CPUS_HILE_LE)
diff --git a/core/fast-reboot.c b/core/fast-reboot.c
index 884441df7c..7bfc06dee0 100644
--- a/core/fast-reboot.c
+++ b/core/fast-reboot.c
@@ -370,8 +370,6 @@ static void cleanup_cpu_state(void)
{
struct cpu_thread *cpu = this_cpu();
- cpu->current_hile = false;
-
/* Per core cleanup */
if (cpu_is_thread0(cpu)) {
/* Shared SPRs whacked back to normal */
@@ -562,6 +560,9 @@ void __noreturn fast_reboot_entry(void)
/* Set our state to active */
this_cpu()->state = cpu_state_active;
+ /* Let the CPU layer do some last minute global cleanups */
+ cpu_fast_reboot_complete();
+
/* We can now do NAP mode */
cpu_set_pm_enable(true);
diff --git a/include/cpu.h b/include/cpu.h
index 0cb6389ac0..1d19c200cd 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -48,7 +48,6 @@ struct cpu_thread {
uint32_t server_no;
uint32_t chip_id;
bool is_secondary;
- bool current_hile;
struct cpu_thread *primary;
enum cpu_thread_state state;
struct dt_node *node;
@@ -271,4 +270,6 @@ 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_fast_reboot_complete(void);
+
#endif /* __CPU_H */
--
2.11.0
More information about the Skiboot
mailing list