]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
powerpc/powernv/idle: Correctly initialize core_idle_state_ptr
authorGautham R. Shenoy <ego@linux.vnet.ibm.com>
Tue, 16 May 2017 08:49:43 +0000 (14:19 +0530)
committerMichael Ellerman <mpe@ellerman.id.au>
Tue, 30 May 2017 04:59:51 +0000 (14:59 +1000)
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>
arch/powerpc/platforms/powernv/idle.c

index 0c21747ed7e071686321033c869484696e9c2e54..502f3275d8c266f4ba0c7f5fcff21230d4164beb 100644 (file)
@@ -96,15 +96,24 @@ static void pnv_alloc_idle_core_states(void)
        u32 *core_idle_state;
 
        /*
-        * core_idle_state - First 8 bits track the idle state of each thread
-        * of the core. The 8th bit is the lock bit. Initially all thread bits
-        * are set. They are cleared when the thread enters deep idle state
-        * like sleep and winkle. Initially the lock bit is cleared.
-        * The lock bit has 2 purposes
-        * a. While the first thread 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.
+        * core_idle_state - The lower 8 bits track the idle state of
+        * each thread of the core.
+        *
+        * The most significant bit is the lock bit.
+        *
+        * Initially all the bits corresponding to threads_per_core
+        * are set. They are cleared when the thread enters deep idle
+        * state like sleep and winkle/stop.
+        *
+        * 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++) {
                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;
 
                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 *
                                       sizeof(struct paca_struct *));