Commit 04140b41 authored by Liran Alon's avatar Liran Alon Committed by Radim Krčmář

KVM: x86: Rename interrupt.pending to interrupt.injected

For exceptions & NMIs events, KVM code use the following
coding convention:
*) "pending" represents an event that should be injected to guest at
some point but it's side-effects have not yet occurred.
*) "injected" represents an event that it's side-effects have already
occurred.

However, interrupts don't conform to this coding convention.
All current code flows mark interrupt.pending when it's side-effects
have already taken place (For example, bit moved from LAPIC IRR to
ISR). Therefore, it makes sense to just rename
interrupt.pending to interrupt.injected.

This change follows logic of previous commit 664f8e26 ("KVM: X86:
Fix loss of exception which has not yet been injected") which changed
exception to follow this coding convention as well.

It is important to note that in case !lapic_in_kernel(vcpu),
interrupt.pending usage was and still incorrect.
In this case, interrrupt.pending can only be set using one of the
following ioctls: KVM_INTERRUPT, KVM_SET_VCPU_EVENTS and
KVM_SET_SREGS. Looking at how QEMU uses these ioctls, one can see that
QEMU uses them either to re-set an "interrupt.pending" state it has
received from KVM (via KVM_GET_VCPU_EVENTS interrupt.pending or
via KVM_GET_SREGS interrupt_bitmap) or by dispatching a new interrupt
from QEMU's emulated LAPIC which reset bit in IRR and set bit in ISR
before sending ioctl to KVM. So it seems that indeed "interrupt.pending"
in this case is also suppose to represent "interrupt.injected".
However, kvm_cpu_has_interrupt() & kvm_cpu_has_injectable_intr()
is misusing (now named) interrupt.injected in order to return if
there is a pending interrupt.
This leads to nVMX/nSVM not be able to distinguish if it should exit
from L2 to L1 on EXTERNAL_INTERRUPT on pending interrupt or should
re-inject an injected interrupt.
Therefore, add a FIXME at these functions for handling this issue.

This patch introduce no semantics change.
Signed-off-by: default avatarLiran Alon <liran.alon@oracle.com>
Reviewed-by: default avatarNikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: default avatarJim Mattson <jmattson@google.com>
Signed-off-by: default avatarKrish Sadhukhan <krish.sadhukhan@oracle.com>
Signed-off-by: default avatarRadim Krčmář <rkrcmar@redhat.com>
parent 7c5a6a59
...@@ -574,7 +574,7 @@ struct kvm_vcpu_arch { ...@@ -574,7 +574,7 @@ struct kvm_vcpu_arch {
} exception; } exception;
struct kvm_queued_interrupt { struct kvm_queued_interrupt {
bool pending; bool injected;
bool soft; bool soft;
u8 nr; u8 nr;
} interrupt; } interrupt;
......
...@@ -73,8 +73,19 @@ static int kvm_cpu_has_extint(struct kvm_vcpu *v) ...@@ -73,8 +73,19 @@ static int kvm_cpu_has_extint(struct kvm_vcpu *v)
*/ */
int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v)
{ {
/*
* FIXME: interrupt.injected represents an interrupt that it's
* side-effects have already been applied (e.g. bit from IRR
* already moved to ISR). Therefore, it is incorrect to rely
* on interrupt.injected to know if there is a pending
* interrupt in the user-mode LAPIC.
* This leads to nVMX/nSVM not be able to distinguish
* if it should exit from L2 to L1 on EXTERNAL_INTERRUPT on
* pending interrupt or should re-inject an injected
* interrupt.
*/
if (!lapic_in_kernel(v)) if (!lapic_in_kernel(v))
return v->arch.interrupt.pending; return v->arch.interrupt.injected;
if (kvm_cpu_has_extint(v)) if (kvm_cpu_has_extint(v))
return 1; return 1;
...@@ -91,8 +102,19 @@ int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) ...@@ -91,8 +102,19 @@ int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v)
*/ */
int kvm_cpu_has_interrupt(struct kvm_vcpu *v) int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
{ {
/*
* FIXME: interrupt.injected represents an interrupt that it's
* side-effects have already been applied (e.g. bit from IRR
* already moved to ISR). Therefore, it is incorrect to rely
* on interrupt.injected to know if there is a pending
* interrupt in the user-mode LAPIC.
* This leads to nVMX/nSVM not be able to distinguish
* if it should exit from L2 to L1 on EXTERNAL_INTERRUPT on
* pending interrupt or should re-inject an injected
* interrupt.
*/
if (!lapic_in_kernel(v)) if (!lapic_in_kernel(v))
return v->arch.interrupt.pending; return v->arch.interrupt.injected;
if (kvm_cpu_has_extint(v)) if (kvm_cpu_has_extint(v))
return 1; return 1;
......
...@@ -11629,7 +11629,7 @@ static void vmcs12_save_pending_event(struct kvm_vcpu *vcpu, ...@@ -11629,7 +11629,7 @@ static void vmcs12_save_pending_event(struct kvm_vcpu *vcpu,
} else if (vcpu->arch.nmi_injected) { } else if (vcpu->arch.nmi_injected) {
vmcs12->idt_vectoring_info_field = vmcs12->idt_vectoring_info_field =
INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR; INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR;
} else if (vcpu->arch.interrupt.pending) { } else if (vcpu->arch.interrupt.injected) {
nr = vcpu->arch.interrupt.nr; nr = vcpu->arch.interrupt.nr;
idt_vectoring = nr | VECTORING_INFO_VALID_MASK; idt_vectoring = nr | VECTORING_INFO_VALID_MASK;
......
...@@ -3312,7 +3312,7 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu, ...@@ -3312,7 +3312,7 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,
events->exception.error_code = vcpu->arch.exception.error_code; events->exception.error_code = vcpu->arch.exception.error_code;
events->interrupt.injected = events->interrupt.injected =
vcpu->arch.interrupt.pending && !vcpu->arch.interrupt.soft; vcpu->arch.interrupt.injected && !vcpu->arch.interrupt.soft;
events->interrupt.nr = vcpu->arch.interrupt.nr; events->interrupt.nr = vcpu->arch.interrupt.nr;
events->interrupt.soft = 0; events->interrupt.soft = 0;
events->interrupt.shadow = kvm_x86_ops->get_interrupt_shadow(vcpu); events->interrupt.shadow = kvm_x86_ops->get_interrupt_shadow(vcpu);
...@@ -3365,7 +3365,7 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu, ...@@ -3365,7 +3365,7 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
vcpu->arch.exception.has_error_code = events->exception.has_error_code; vcpu->arch.exception.has_error_code = events->exception.has_error_code;
vcpu->arch.exception.error_code = events->exception.error_code; vcpu->arch.exception.error_code = events->exception.error_code;
vcpu->arch.interrupt.pending = events->interrupt.injected; vcpu->arch.interrupt.injected = events->interrupt.injected;
vcpu->arch.interrupt.nr = events->interrupt.nr; vcpu->arch.interrupt.nr = events->interrupt.nr;
vcpu->arch.interrupt.soft = events->interrupt.soft; vcpu->arch.interrupt.soft = events->interrupt.soft;
if (events->flags & KVM_VCPUEVENT_VALID_SHADOW) if (events->flags & KVM_VCPUEVENT_VALID_SHADOW)
...@@ -6767,7 +6767,7 @@ static int inject_pending_event(struct kvm_vcpu *vcpu, bool req_int_win) ...@@ -6767,7 +6767,7 @@ static int inject_pending_event(struct kvm_vcpu *vcpu, bool req_int_win)
return 0; return 0;
} }
if (vcpu->arch.interrupt.pending) { if (vcpu->arch.interrupt.injected) {
kvm_x86_ops->set_irq(vcpu); kvm_x86_ops->set_irq(vcpu);
return 0; return 0;
} }
...@@ -7818,7 +7818,7 @@ static void __get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) ...@@ -7818,7 +7818,7 @@ static void __get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
memset(sregs->interrupt_bitmap, 0, sizeof sregs->interrupt_bitmap); memset(sregs->interrupt_bitmap, 0, sizeof sregs->interrupt_bitmap);
if (vcpu->arch.interrupt.pending && !vcpu->arch.interrupt.soft) if (vcpu->arch.interrupt.injected && !vcpu->arch.interrupt.soft)
set_bit(vcpu->arch.interrupt.nr, set_bit(vcpu->arch.interrupt.nr,
(unsigned long *)sregs->interrupt_bitmap); (unsigned long *)sregs->interrupt_bitmap);
} }
......
...@@ -55,19 +55,19 @@ static inline void kvm_clear_exception_queue(struct kvm_vcpu *vcpu) ...@@ -55,19 +55,19 @@ static inline void kvm_clear_exception_queue(struct kvm_vcpu *vcpu)
static inline void kvm_queue_interrupt(struct kvm_vcpu *vcpu, u8 vector, static inline void kvm_queue_interrupt(struct kvm_vcpu *vcpu, u8 vector,
bool soft) bool soft)
{ {
vcpu->arch.interrupt.pending = true; vcpu->arch.interrupt.injected = true;
vcpu->arch.interrupt.soft = soft; vcpu->arch.interrupt.soft = soft;
vcpu->arch.interrupt.nr = vector; vcpu->arch.interrupt.nr = vector;
} }
static inline void kvm_clear_interrupt_queue(struct kvm_vcpu *vcpu) static inline void kvm_clear_interrupt_queue(struct kvm_vcpu *vcpu)
{ {
vcpu->arch.interrupt.pending = false; vcpu->arch.interrupt.injected = false;
} }
static inline bool kvm_event_needs_reinjection(struct kvm_vcpu *vcpu) static inline bool kvm_event_needs_reinjection(struct kvm_vcpu *vcpu)
{ {
return vcpu->arch.exception.injected || vcpu->arch.interrupt.pending || return vcpu->arch.exception.injected || vcpu->arch.interrupt.injected ||
vcpu->arch.nmi_injected; vcpu->arch.nmi_injected;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment