|
@@ -150,7 +150,6 @@ static int kvmppc_book3s_vec2irqprio(unsigned int vec)
|
|
|
case 0x400: prio = BOOK3S_IRQPRIO_INST_STORAGE; break;
|
|
|
case 0x480: prio = BOOK3S_IRQPRIO_INST_SEGMENT; break;
|
|
|
case 0x500: prio = BOOK3S_IRQPRIO_EXTERNAL; break;
|
|
|
- case 0x501: prio = BOOK3S_IRQPRIO_EXTERNAL_LEVEL; break;
|
|
|
case 0x600: prio = BOOK3S_IRQPRIO_ALIGNMENT; break;
|
|
|
case 0x700: prio = BOOK3S_IRQPRIO_PROGRAM; break;
|
|
|
case 0x800: prio = BOOK3S_IRQPRIO_FP_UNAVAIL; break;
|
|
@@ -236,18 +235,35 @@ EXPORT_SYMBOL_GPL(kvmppc_core_dequeue_dec);
|
|
|
void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
|
|
|
struct kvm_interrupt *irq)
|
|
|
{
|
|
|
- unsigned int vec = BOOK3S_INTERRUPT_EXTERNAL;
|
|
|
-
|
|
|
- if (irq->irq == KVM_INTERRUPT_SET_LEVEL)
|
|
|
- vec = BOOK3S_INTERRUPT_EXTERNAL_LEVEL;
|
|
|
+ /*
|
|
|
+ * This case (KVM_INTERRUPT_SET) should never actually arise for
|
|
|
+ * a pseries guest (because pseries guests expect their interrupt
|
|
|
+ * controllers to continue asserting an external interrupt request
|
|
|
+ * until it is acknowledged at the interrupt controller), but is
|
|
|
+ * included to avoid ABI breakage and potentially for other
|
|
|
+ * sorts of guest.
|
|
|
+ *
|
|
|
+ * There is a subtlety here: HV KVM does not test the
|
|
|
+ * external_oneshot flag in the code that synthesizes
|
|
|
+ * external interrupts for the guest just before entering
|
|
|
+ * the guest. That is OK even if userspace did do a
|
|
|
+ * KVM_INTERRUPT_SET on a pseries guest vcpu, because the
|
|
|
+ * caller (kvm_vcpu_ioctl_interrupt) does a kvm_vcpu_kick()
|
|
|
+ * which ends up doing a smp_send_reschedule(), which will
|
|
|
+ * pull the guest all the way out to the host, meaning that
|
|
|
+ * we will call kvmppc_core_prepare_to_enter() before entering
|
|
|
+ * the guest again, and that will handle the external_oneshot
|
|
|
+ * flag correctly.
|
|
|
+ */
|
|
|
+ if (irq->irq == KVM_INTERRUPT_SET)
|
|
|
+ vcpu->arch.external_oneshot = 1;
|
|
|
|
|
|
- kvmppc_book3s_queue_irqprio(vcpu, vec);
|
|
|
+ kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL);
|
|
|
}
|
|
|
|
|
|
void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu)
|
|
|
{
|
|
|
kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL);
|
|
|
- kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL_LEVEL);
|
|
|
}
|
|
|
|
|
|
void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu, ulong dar,
|
|
@@ -278,7 +294,6 @@ static int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu,
|
|
|
vec = BOOK3S_INTERRUPT_DECREMENTER;
|
|
|
break;
|
|
|
case BOOK3S_IRQPRIO_EXTERNAL:
|
|
|
- case BOOK3S_IRQPRIO_EXTERNAL_LEVEL:
|
|
|
deliver = (kvmppc_get_msr(vcpu) & MSR_EE) && !crit;
|
|
|
vec = BOOK3S_INTERRUPT_EXTERNAL;
|
|
|
break;
|
|
@@ -352,8 +367,16 @@ static bool clear_irqprio(struct kvm_vcpu *vcpu, unsigned int priority)
|
|
|
case BOOK3S_IRQPRIO_DECREMENTER:
|
|
|
/* DEC interrupts get cleared by mtdec */
|
|
|
return false;
|
|
|
- case BOOK3S_IRQPRIO_EXTERNAL_LEVEL:
|
|
|
- /* External interrupts get cleared by userspace */
|
|
|
+ case BOOK3S_IRQPRIO_EXTERNAL:
|
|
|
+ /*
|
|
|
+ * External interrupts get cleared by userspace
|
|
|
+ * except when set by the KVM_INTERRUPT ioctl with
|
|
|
+ * KVM_INTERRUPT_SET (not KVM_INTERRUPT_SET_LEVEL).
|
|
|
+ */
|
|
|
+ if (vcpu->arch.external_oneshot) {
|
|
|
+ vcpu->arch.external_oneshot = 0;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
return false;
|
|
|
}
|
|
|
|