Skip to content

Commit

Permalink
cpu: Rework HILE change
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
ozbenh authored and stewartsmith committed Jun 26, 2017
1 parent 42f9a14 commit 24726a1
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 31 deletions.
71 changes: 43 additions & 28 deletions core/cpu.c
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
5 changes: 3 additions & 2 deletions core/fast-reboot.c
Expand Up @@ -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 */
Expand Down Expand Up @@ -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);

Expand Down
3 changes: 2 additions & 1 deletion include/cpu.h
Expand Up @@ -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;
Expand Down Expand Up @@ -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 */

0 comments on commit 24726a1

Please sign in to comment.