Commit 5f221c3c authored by Gautham R. Shenoy's avatar Gautham R. Shenoy Committed by Michael Ellerman

powerpc/powernv/idle: Correctly initialize core_idle_state_ptr

The lower 8 bits of core_idle_state_ptr tracks the number of non-idle
threads in the core. This is supposed to be initialized to bit-map
corresponding to the threads_per_core. However, currently it is
initialized to PNV_CORE_IDLE_THREAD_BITS (0xFF). This is correct for
POWER8 which has 8 threads per core, but not for POWER9 which has 4
threads per core.

As a result, on POWER9, core_idle_state_ptr gets initialized to
0xFF. In case when all the threads of the core are idle, the bits
corresponding tracking the idle-threads are non-zero. As a result, the
idle entry/exit code fails to save/restore per-core hypervisor state
since it assumes that there are threads in the cores which are still
active.

Fix this by correctly initializing the lower bits of the
core_idle_state_ptr on the basis of threads_per_core.
Signed-off-by: default avatarGautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 518470fe
...@@ -96,15 +96,24 @@ static void pnv_alloc_idle_core_states(void) ...@@ -96,15 +96,24 @@ static void pnv_alloc_idle_core_states(void)
u32 *core_idle_state; u32 *core_idle_state;
/* /*
* core_idle_state - First 8 bits track the idle state of each thread * core_idle_state - The lower 8 bits track the idle state of
* of the core. The 8th bit is the lock bit. Initially all thread bits * each thread of the core.
* are set. They are cleared when the thread enters deep idle state *
* like sleep and winkle. Initially the lock bit is cleared. * The most significant bit is the lock bit.
* The lock bit has 2 purposes *
* a. While the first thread is restoring core state, it prevents * Initially all the bits corresponding to threads_per_core
* other threads in the core from switching to process context. * are set. They are cleared when the thread enters deep idle
* b. While the last thread in the core is saving the core state, it * state like sleep and winkle/stop.
* prevents a different thread from waking up. *
* Initially the lock bit is cleared. The lock bit has 2
* purposes:
* a. While the first thread in the core waking up from
* idle is restoring core state, it prevents other
* threads in the core from switching to process
* context.
* b. While the last thread in the core is saving the
* core state, it prevents a different thread from
* waking up.
*/ */
for (i = 0; i < nr_cores; i++) { for (i = 0; i < nr_cores; i++) {
int first_cpu = i * threads_per_core; int first_cpu = i * threads_per_core;
...@@ -112,7 +121,7 @@ static void pnv_alloc_idle_core_states(void) ...@@ -112,7 +121,7 @@ static void pnv_alloc_idle_core_states(void)
size_t paca_ptr_array_size; size_t paca_ptr_array_size;
core_idle_state = kmalloc_node(sizeof(u32), GFP_KERNEL, node); core_idle_state = kmalloc_node(sizeof(u32), GFP_KERNEL, node);
*core_idle_state = PNV_CORE_IDLE_THREAD_BITS; *core_idle_state = (1 << threads_per_core) - 1;
paca_ptr_array_size = (threads_per_core * paca_ptr_array_size = (threads_per_core *
sizeof(struct paca_struct *)); sizeof(struct paca_struct *));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment