aboutsummaryrefslogtreecommitdiff
path: root/core/cpu.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2017-06-24 14:17:27 -0500
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-06-26 14:28:58 +1000
commit24726a1f5e41e416b1035f2486870def72a2ce8a (patch)
tree1b99c47c3759581e19b122401183ba9576856f14 /core/cpu.c
parent42f9a14f9579db6f90e52b158ab859508b14cc02 (diff)
downloadskiboot-24726a1f5e41e416b1035f2486870def72a2ce8a.zip
skiboot-24726a1f5e41e416b1035f2486870def72a2ce8a.tar.gz
skiboot-24726a1f5e41e416b1035f2486870def72a2ce8a.tar.bz2
cpu: Rework HILE change
Create a more generic helper for changing HID0 bits on all processors. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/cpu.c')
-rw-r--r--core/cpu.c71
1 files changed, 43 insertions, 28 deletions
diff --git a/core/cpu.c b/core/cpu.c
index a083ed7..31f5c92 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)