aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/book3s_hv_rm_xics.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm/book3s_hv_rm_xics.c')
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_xics.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c
index 3ee38e6e884f..7b066f6b02ad 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_xics.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c
@@ -183,8 +183,10 @@ static void icp_rm_down_cppr(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
183 * state update in HW (ie bus transactions) so we can handle them 183 * state update in HW (ie bus transactions) so we can handle them
184 * separately here as well. 184 * separately here as well.
185 */ 185 */
186 if (resend) 186 if (resend) {
187 icp->rm_action |= XICS_RM_CHECK_RESEND; 187 icp->rm_action |= XICS_RM_CHECK_RESEND;
188 icp->rm_resend_icp = icp;
189 }
188} 190}
189 191
190 192
@@ -254,10 +256,25 @@ int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
254 * nothing needs to be done as there can be no XISR to 256 * nothing needs to be done as there can be no XISR to
255 * reject. 257 * reject.
256 * 258 *
259 * ICP state: Check_IPI
260 *
257 * If the CPPR is less favored, then we might be replacing 261 * If the CPPR is less favored, then we might be replacing
258 * an interrupt, and thus need to possibly reject it as in 262 * an interrupt, and thus need to possibly reject it.
259 * 263 *
260 * ICP state: Check_IPI 264 * ICP State: IPI
265 *
266 * Besides rejecting any pending interrupts, we also
267 * update XISR and pending_pri to mark IPI as pending.
268 *
269 * PAPR does not describe this state, but if the MFRR is being
270 * made less favored than its earlier value, there might be
271 * a previously-rejected interrupt needing to be resent.
272 * Ideally, we would want to resend only if
273 * prio(pending_interrupt) < mfrr &&
274 * prio(pending_interrupt) < cppr
275 * where pending interrupt is the one that was rejected. But
276 * we don't have that state, so we simply trigger a resend
277 * whenever the MFRR is made less favored.
261 */ 278 */
262 do { 279 do {
263 old_state = new_state = ACCESS_ONCE(icp->state); 280 old_state = new_state = ACCESS_ONCE(icp->state);
@@ -270,13 +287,14 @@ int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
270 resend = false; 287 resend = false;
271 if (mfrr < new_state.cppr) { 288 if (mfrr < new_state.cppr) {
272 /* Reject a pending interrupt if not an IPI */ 289 /* Reject a pending interrupt if not an IPI */
273 if (mfrr <= new_state.pending_pri) 290 if (mfrr <= new_state.pending_pri) {
274 reject = new_state.xisr; 291 reject = new_state.xisr;
275 new_state.pending_pri = mfrr; 292 new_state.pending_pri = mfrr;
276 new_state.xisr = XICS_IPI; 293 new_state.xisr = XICS_IPI;
294 }
277 } 295 }
278 296
279 if (mfrr > old_state.mfrr && mfrr > new_state.cppr) { 297 if (mfrr > old_state.mfrr) {
280 resend = new_state.need_resend; 298 resend = new_state.need_resend;
281 new_state.need_resend = 0; 299 new_state.need_resend = 0;
282 } 300 }
@@ -289,8 +307,10 @@ int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
289 } 307 }
290 308
291 /* Pass resends to virtual mode */ 309 /* Pass resends to virtual mode */
292 if (resend) 310 if (resend) {
293 this_icp->rm_action |= XICS_RM_CHECK_RESEND; 311 this_icp->rm_action |= XICS_RM_CHECK_RESEND;
312 this_icp->rm_resend_icp = icp;
313 }
294 314
295 return check_too_hard(xics, this_icp); 315 return check_too_hard(xics, this_icp);
296} 316}