Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: PPC: Book3S HV: Move virtual mode ICP functions to real-mode

Interrupt-based hypercalls return H_TOO_HARD to inform KVM that it needs
to switch to the host to complete the rest of hypercall function in
virtual mode. This patch ports the virtual mode ICS/ICP reject and resend
functions to be runnable in hypervisor real mode, thus avoiding the need
to switch to the host to execute these functions in virtual mode. However,
the hypercalls continue to return H_TOO_HARD for vcpu_wakeup and notify
events - these events cannot be done in real mode and they will still need
a switch to host virtual mode.

There are sufficient differences between the real mode code and the
virtual mode code for the ICS/ICP resend and reject functions that
for now the code has been duplicated instead of sharing common code.
In the future, we can look at creating common functions.

Signed-off-by: Suresh Warrier <warrier@linux.vnet.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Alexander Graf <agraf@suse.de>

authored by

Suresh Warrier and committed by
Alexander Graf
b0221556 34cb7954

+211 -14
+211 -14
arch/powerpc/kvm/book3s_hv_rm_xics.c
··· 23 23 24 24 #define DEBUG_PASSUP 25 25 26 + static void icp_rm_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp, 27 + u32 new_irq); 28 + 26 29 static inline void rm_writeb(unsigned long paddr, u8 val) 27 30 { 28 31 __asm__ __volatile__("sync; stbcix %0,0,%1" 29 32 : : "r" (val), "r" (paddr) : "memory"); 30 33 } 34 + 35 + /* -- ICS routines -- */ 36 + static void ics_rm_check_resend(struct kvmppc_xics *xics, 37 + struct kvmppc_ics *ics, struct kvmppc_icp *icp) 38 + { 39 + int i; 40 + 41 + arch_spin_lock(&ics->lock); 42 + 43 + for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) { 44 + struct ics_irq_state *state = &ics->irq_state[i]; 45 + 46 + if (!state->resend) 47 + continue; 48 + 49 + arch_spin_unlock(&ics->lock); 50 + icp_rm_deliver_irq(xics, icp, state->number); 51 + arch_spin_lock(&ics->lock); 52 + } 53 + 54 + arch_spin_unlock(&ics->lock); 55 + } 56 + 57 + /* -- ICP routines -- */ 31 58 32 59 static void icp_rm_set_vcpu_irq(struct kvm_vcpu *vcpu, 33 60 struct kvm_vcpu *this_vcpu) ··· 143 116 return (xics->real_mode_dbg || icp->rm_action) ? H_TOO_HARD : H_SUCCESS; 144 117 } 145 118 119 + static void icp_rm_check_resend(struct kvmppc_xics *xics, 120 + struct kvmppc_icp *icp) 121 + { 122 + u32 icsid; 123 + 124 + /* Order this load with the test for need_resend in the caller */ 125 + smp_rmb(); 126 + for_each_set_bit(icsid, icp->resend_map, xics->max_icsid + 1) { 127 + struct kvmppc_ics *ics = xics->ics[icsid]; 128 + 129 + if (!test_and_clear_bit(icsid, icp->resend_map)) 130 + continue; 131 + if (!ics) 132 + continue; 133 + ics_rm_check_resend(xics, ics, icp); 134 + } 135 + } 136 + 137 + static bool icp_rm_try_to_deliver(struct kvmppc_icp *icp, u32 irq, u8 priority, 138 + u32 *reject) 139 + { 140 + union kvmppc_icp_state old_state, new_state; 141 + bool success; 142 + 143 + do { 144 + old_state = new_state = READ_ONCE(icp->state); 145 + 146 + *reject = 0; 147 + 148 + /* See if we can deliver */ 149 + success = new_state.cppr > priority && 150 + new_state.mfrr > priority && 151 + new_state.pending_pri > priority; 152 + 153 + /* 154 + * If we can, check for a rejection and perform the 155 + * delivery 156 + */ 157 + if (success) { 158 + *reject = new_state.xisr; 159 + new_state.xisr = irq; 160 + new_state.pending_pri = priority; 161 + } else { 162 + /* 163 + * If we failed to deliver we set need_resend 164 + * so a subsequent CPPR state change causes us 165 + * to try a new delivery. 166 + */ 167 + new_state.need_resend = true; 168 + } 169 + 170 + } while (!icp_rm_try_update(icp, old_state, new_state)); 171 + 172 + return success; 173 + } 174 + 175 + static void icp_rm_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp, 176 + u32 new_irq) 177 + { 178 + struct ics_irq_state *state; 179 + struct kvmppc_ics *ics; 180 + u32 reject; 181 + u16 src; 182 + 183 + /* 184 + * This is used both for initial delivery of an interrupt and 185 + * for subsequent rejection. 186 + * 187 + * Rejection can be racy vs. resends. We have evaluated the 188 + * rejection in an atomic ICP transaction which is now complete, 189 + * so potentially the ICP can already accept the interrupt again. 190 + * 191 + * So we need to retry the delivery. Essentially the reject path 192 + * boils down to a failed delivery. Always. 193 + * 194 + * Now the interrupt could also have moved to a different target, 195 + * thus we may need to re-do the ICP lookup as well 196 + */ 197 + 198 + again: 199 + /* Get the ICS state and lock it */ 200 + ics = kvmppc_xics_find_ics(xics, new_irq, &src); 201 + if (!ics) { 202 + /* Unsafe increment, but this does not need to be accurate */ 203 + return; 204 + } 205 + state = &ics->irq_state[src]; 206 + 207 + /* Get a lock on the ICS */ 208 + arch_spin_lock(&ics->lock); 209 + 210 + /* Get our server */ 211 + if (!icp || state->server != icp->server_num) { 212 + icp = kvmppc_xics_find_server(xics->kvm, state->server); 213 + if (!icp) { 214 + /* Unsafe increment again*/ 215 + goto out; 216 + } 217 + } 218 + 219 + /* Clear the resend bit of that interrupt */ 220 + state->resend = 0; 221 + 222 + /* 223 + * If masked, bail out 224 + * 225 + * Note: PAPR doesn't mention anything about masked pending 226 + * when doing a resend, only when doing a delivery. 227 + * 228 + * However that would have the effect of losing a masked 229 + * interrupt that was rejected and isn't consistent with 230 + * the whole masked_pending business which is about not 231 + * losing interrupts that occur while masked. 232 + * 233 + * I don't differentiate normal deliveries and resends, this 234 + * implementation will differ from PAPR and not lose such 235 + * interrupts. 236 + */ 237 + if (state->priority == MASKED) { 238 + state->masked_pending = 1; 239 + goto out; 240 + } 241 + 242 + /* 243 + * Try the delivery, this will set the need_resend flag 244 + * in the ICP as part of the atomic transaction if the 245 + * delivery is not possible. 246 + * 247 + * Note that if successful, the new delivery might have itself 248 + * rejected an interrupt that was "delivered" before we took the 249 + * ics spin lock. 250 + * 251 + * In this case we do the whole sequence all over again for the 252 + * new guy. We cannot assume that the rejected interrupt is less 253 + * favored than the new one, and thus doesn't need to be delivered, 254 + * because by the time we exit icp_rm_try_to_deliver() the target 255 + * processor may well have already consumed & completed it, and thus 256 + * the rejected interrupt might actually be already acceptable. 257 + */ 258 + if (icp_rm_try_to_deliver(icp, new_irq, state->priority, &reject)) { 259 + /* 260 + * Delivery was successful, did we reject somebody else ? 261 + */ 262 + if (reject && reject != XICS_IPI) { 263 + arch_spin_unlock(&ics->lock); 264 + new_irq = reject; 265 + goto again; 266 + } 267 + } else { 268 + /* 269 + * We failed to deliver the interrupt we need to set the 270 + * resend map bit and mark the ICS state as needing a resend 271 + */ 272 + set_bit(ics->icsid, icp->resend_map); 273 + state->resend = 1; 274 + 275 + /* 276 + * If the need_resend flag got cleared in the ICP some time 277 + * between icp_rm_try_to_deliver() atomic update and now, then 278 + * we know it might have missed the resend_map bit. So we 279 + * retry 280 + */ 281 + smp_mb(); 282 + if (!icp->state.need_resend) { 283 + arch_spin_unlock(&ics->lock); 284 + goto again; 285 + } 286 + } 287 + out: 288 + arch_spin_unlock(&ics->lock); 289 + } 290 + 146 291 static void icp_rm_down_cppr(struct kvmppc_xics *xics, struct kvmppc_icp *icp, 147 292 u8 new_cppr) 148 293 { ··· 383 184 * separately here as well. 384 185 */ 385 186 if (resend) { 386 - icp->rm_action |= XICS_RM_CHECK_RESEND; 387 - icp->rm_resend_icp = icp; 187 + icp_rm_check_resend(xics, icp); 388 188 } 389 189 } 390 190 ··· 498 300 } 499 301 } while (!icp_rm_try_update(icp, old_state, new_state)); 500 302 501 - /* Pass rejects to virtual mode */ 303 + /* Handle reject in real mode */ 502 304 if (reject && reject != XICS_IPI) { 503 - this_icp->rm_action |= XICS_RM_REJECT; 504 - this_icp->rm_reject = reject; 305 + icp_rm_deliver_irq(xics, icp, reject); 505 306 } 506 307 507 - /* Pass resends to virtual mode */ 308 + /* Handle resends in real mode */ 508 309 if (resend) { 509 - this_icp->rm_action |= XICS_RM_CHECK_RESEND; 510 - this_icp->rm_resend_icp = icp; 310 + icp_rm_check_resend(xics, icp); 511 311 } 512 312 513 313 return check_too_hard(xics, this_icp); ··· 561 365 562 366 } while (!icp_rm_try_update(icp, old_state, new_state)); 563 367 564 - /* Pass rejects to virtual mode */ 368 + /* 369 + * Check for rejects. They are handled by doing a new delivery 370 + * attempt (see comments in icp_rm_deliver_irq). 371 + */ 565 372 if (reject && reject != XICS_IPI) { 566 - icp->rm_action |= XICS_RM_REJECT; 567 - icp->rm_reject = reject; 373 + icp_rm_deliver_irq(xics, icp, reject); 568 374 } 569 375 bail: 570 376 return check_too_hard(xics, icp); ··· 614 416 goto bail; 615 417 state = &ics->irq_state[src]; 616 418 617 - /* Still asserted, resend it, we make it look like a reject */ 419 + /* Still asserted, resend it */ 618 420 if (state->asserted) { 619 - icp->rm_action |= XICS_RM_REJECT; 620 - icp->rm_reject = irq; 421 + icp_rm_deliver_irq(xics, icp, irq); 621 422 } 622 423 623 424 if (!hlist_empty(&vcpu->kvm->irq_ack_notifier_list)) {