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: Gautham R. Shenoy <ego@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
518470fe96
commit
5f221c3ca1
|
@ -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)
|
||||||
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 *));
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue