aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@ozlabs.org>2016-10-21 05:03:05 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2016-10-24 04:29:36 -0400
commit56c46222af0d09149fadec2a3ce9d4889de01cc6 (patch)
treeeaf5e055eaea82bbb34a947e6c072bca764c9a37
parenta05b82d5149dfeef05254a11c3636a89a854520a (diff)
powerpc/64: Re-fix race condition between going idle and entering guest
Commit 8117ac6a6c2f ("powerpc/powernv: Switch off MMU before entering nap/sleep/rvwinkle mode", 2014-12-10) fixed a race condition where one thread entering a KVM guest could switch the MMU context to the guest while another thread was still in host kernel context with the MMU on. That commit moved the point where a thread entering a power-saving mode set its kvm_hstate.hwthread_state field in its PACA to KVM_HWTHREAD_IN_IDLE from a point where the MMU was on to after the MMU had been switched off. That commit also added a comment explaining that we have to switch to real mode before setting hwthread_state to avoid this race. Nevertheless, commit 4eae2c9ae54a ("powerpc/powernv: Make pnv_powersave_common more generic", 2016-07-08) subsequently moved the setting of hwthread_state back to a point where the MMU is on, thus reintroducing the race, despite the comment saying that this should not be done being included in full in the context lines of the patch that did it. This fixes the race again and adds a bigger and shoutier comment explaining the potential race condition. Fixes: 4eae2c9ae54a ("powerpc/powernv: Make pnv_powersave_common more generic") Cc: stable@vger.kernel.org # v4.8+ Signed-off-by: Paul Mackerras <paulus@ozlabs.org> Reviewed-by: Shreyas B. Prabhu <shreyasbp@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/kernel/idle_book3s.S32
1 files changed, 26 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S
index bd739fed26e3..0d8712a835d2 100644
--- a/arch/powerpc/kernel/idle_book3s.S
+++ b/arch/powerpc/kernel/idle_book3s.S
@@ -163,12 +163,6 @@ _GLOBAL(pnv_powersave_common)
163 std r9,_MSR(r1) 163 std r9,_MSR(r1)
164 std r1,PACAR1(r13) 164 std r1,PACAR1(r13)
165 165
166#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
167 /* Tell KVM we're entering idle */
168 li r4,KVM_HWTHREAD_IN_IDLE
169 stb r4,HSTATE_HWTHREAD_STATE(r13)
170#endif
171
172 /* 166 /*
173 * Go to real mode to do the nap, as required by the architecture. 167 * Go to real mode to do the nap, as required by the architecture.
174 * Also, we need to be in real mode before setting hwthread_state, 168 * Also, we need to be in real mode before setting hwthread_state,
@@ -185,6 +179,26 @@ _GLOBAL(pnv_powersave_common)
185 179
186 .globl pnv_enter_arch207_idle_mode 180 .globl pnv_enter_arch207_idle_mode
187pnv_enter_arch207_idle_mode: 181pnv_enter_arch207_idle_mode:
182#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
183 /* Tell KVM we're entering idle */
184 li r4,KVM_HWTHREAD_IN_IDLE
185 /******************************************************/
186 /* N O T E W E L L ! ! ! N O T E W E L L */
187 /* The following store to HSTATE_HWTHREAD_STATE(r13) */
188 /* MUST occur in real mode, i.e. with the MMU off, */
189 /* and the MMU must stay off until we clear this flag */
190 /* and test HSTATE_HWTHREAD_REQ(r13) in the system */
191 /* reset interrupt vector in exceptions-64s.S. */
192 /* The reason is that another thread can switch the */
193 /* MMU to a guest context whenever this flag is set */
194 /* to KVM_HWTHREAD_IN_IDLE, and if the MMU was on, */
195 /* that would potentially cause this thread to start */
196 /* executing instructions from guest memory in */
197 /* hypervisor mode, leading to a host crash or data */
198 /* corruption, or worse. */
199 /******************************************************/
200 stb r4,HSTATE_HWTHREAD_STATE(r13)
201#endif
188 stb r3,PACA_THREAD_IDLE_STATE(r13) 202 stb r3,PACA_THREAD_IDLE_STATE(r13)
189 cmpwi cr3,r3,PNV_THREAD_SLEEP 203 cmpwi cr3,r3,PNV_THREAD_SLEEP
190 bge cr3,2f 204 bge cr3,2f
@@ -250,6 +264,12 @@ enter_winkle:
250 * r3 - requested stop state 264 * r3 - requested stop state
251 */ 265 */
252power_enter_stop: 266power_enter_stop:
267#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
268 /* Tell KVM we're entering idle */
269 li r4,KVM_HWTHREAD_IN_IDLE
270 /* DO THIS IN REAL MODE! See comment above. */
271 stb r4,HSTATE_HWTHREAD_STATE(r13)
272#endif
253/* 273/*
254 * Check if the requested state is a deep idle state. 274 * Check if the requested state is a deep idle state.
255 */ 275 */