* [PATCH v2 01/16] Make kvm_cpu_(has|get)_interrupt() work for userspace irqchip too.
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
@ 2009-04-21 14:44 ` Gleb Natapov
2009-04-21 14:44 ` [PATCH v2 02/16] Consolidate userspace and kernel interrupt injection for VMX Gleb Natapov
` (15 subsequent siblings)
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:44 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/kvm/irq.c | 7 +++++++
arch/x86/kvm/svm.c | 11 +++++++----
arch/x86/kvm/vmx.c | 18 +++++++++---------
arch/x86/kvm/x86.c | 4 ++--
4 files changed, 25 insertions(+), 15 deletions(-)
diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
index cf17ed5..11c2757 100644
--- a/arch/x86/kvm/irq.c
+++ b/arch/x86/kvm/irq.c
@@ -24,6 +24,7 @@
#include "irq.h"
#include "i8254.h"
+#include "x86.h"
/*
* check if there are pending timer events
@@ -48,6 +49,9 @@ int kvm_cpu_has_interrupt(struct kvm_vcpu *v)
{
struct kvm_pic *s;
+ if (!irqchip_in_kernel(v->kvm))
+ return v->arch.irq_summary;
+
if (kvm_apic_has_interrupt(v) == -1) { /* LAPIC */
if (kvm_apic_accept_pic_intr(v)) {
s = pic_irqchip(v->kvm); /* PIC */
@@ -67,6 +71,9 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v)
struct kvm_pic *s;
int vector;
+ if (!irqchip_in_kernel(v->kvm))
+ return kvm_pop_irq(v);
+
vector = kvm_get_apic_interrupt(v); /* APIC */
if (vector == -1) {
if (kvm_apic_accept_pic_intr(v)) {
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 3ffb695..7ac57e7 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2082,8 +2082,9 @@ static int interrupt_window_interception(struct vcpu_svm *svm,
* If the user space waits to inject interrupts, exit as soon as
* possible
*/
- if (kvm_run->request_interrupt_window &&
- !svm->vcpu.arch.irq_summary) {
+ if (!irqchip_in_kernel(svm->vcpu.kvm) &&
+ kvm_run->request_interrupt_window &&
+ !kvm_cpu_has_interrupt(&svm->vcpu)) {
++svm->vcpu.stat.irq_window_exits;
kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
return 0;
@@ -2364,7 +2365,8 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu,
(svm->vmcb->save.rflags & X86_EFLAGS_IF) &&
(svm->vcpu.arch.hflags & HF_GIF_MASK));
- if (svm->vcpu.arch.interrupt_window_open && svm->vcpu.arch.irq_summary)
+ if (svm->vcpu.arch.interrupt_window_open &&
+ kvm_cpu_has_interrupt(&svm->vcpu))
/*
* If interrupts enabled, and not blocked by sti or mov ss. Good.
*/
@@ -2374,7 +2376,8 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu,
* Interrupts blocked. Wait for unblock.
*/
if (!svm->vcpu.arch.interrupt_window_open &&
- (svm->vcpu.arch.irq_summary || kvm_run->request_interrupt_window))
+ (kvm_cpu_has_interrupt(&svm->vcpu) ||
+ kvm_run->request_interrupt_window))
svm_set_vintr(svm);
else
svm_clear_vintr(svm);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index c6997c0..b3292c1 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2535,21 +2535,20 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu,
vmx_inject_nmi(vcpu);
if (vcpu->arch.nmi_pending)
enable_nmi_window(vcpu);
- else if (vcpu->arch.irq_summary
- || kvm_run->request_interrupt_window)
+ else if (kvm_cpu_has_interrupt(vcpu) ||
+ kvm_run->request_interrupt_window)
enable_irq_window(vcpu);
return;
}
if (vcpu->arch.interrupt_window_open) {
- if (vcpu->arch.irq_summary && !vcpu->arch.interrupt.pending)
- kvm_queue_interrupt(vcpu, kvm_pop_irq(vcpu));
+ if (kvm_cpu_has_interrupt(vcpu) && !vcpu->arch.interrupt.pending)
+ kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
if (vcpu->arch.interrupt.pending)
vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
- }
- if (!vcpu->arch.interrupt_window_open &&
- (vcpu->arch.irq_summary || kvm_run->request_interrupt_window))
+ } else if(kvm_cpu_has_interrupt(vcpu) ||
+ kvm_run->request_interrupt_window)
enable_irq_window(vcpu);
}
@@ -2976,8 +2975,9 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu,
* If the user space waits to inject interrupts, exit as soon as
* possible
*/
- if (kvm_run->request_interrupt_window &&
- !vcpu->arch.irq_summary) {
+ if (!irqchip_in_kernel(vcpu->kvm) &&
+ kvm_run->request_interrupt_window &&
+ !kvm_cpu_has_interrupt(vcpu)) {
kvm_run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
return 0;
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 0bb4131..7184f55 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3059,7 +3059,7 @@ EXPORT_SYMBOL_GPL(kvm_emulate_cpuid);
static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu,
struct kvm_run *kvm_run)
{
- return (!vcpu->arch.irq_summary &&
+ return (!irqchip_in_kernel(vcpu->kvm) && !kvm_cpu_has_interrupt(vcpu) &&
kvm_run->request_interrupt_window &&
vcpu->arch.interrupt_window_open &&
(kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF));
@@ -3076,7 +3076,7 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu,
else
kvm_run->ready_for_interrupt_injection =
(vcpu->arch.interrupt_window_open &&
- vcpu->arch.irq_summary == 0);
+ !kvm_cpu_has_interrupt(vcpu));
}
static void vapic_enter(struct kvm_vcpu *vcpu)
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 02/16] Consolidate userspace and kernel interrupt injection for VMX.
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
2009-04-21 14:44 ` [PATCH v2 01/16] Make kvm_cpu_(has|get)_interrupt() work for userspace irqchip too Gleb Natapov
@ 2009-04-21 14:44 ` Gleb Natapov
2009-04-21 14:44 ` [PATCH v2 03/16] Cleanup vmx_intr_assist() Gleb Natapov
` (14 subsequent siblings)
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:44 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
Use the same callback to inject irq/nmi events no matter what irqchip is
in use. Only from VMX for now.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/include/asm/kvm_host.h | 2 +-
arch/x86/kvm/svm.c | 2 +-
arch/x86/kvm/vmx.c | 71 +++++++++------------------------------
arch/x86/kvm/x86.c | 2 +-
4 files changed, 19 insertions(+), 58 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 3fc4623..4a9022d 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -520,7 +520,7 @@ struct kvm_x86_ops {
void (*queue_exception)(struct kvm_vcpu *vcpu, unsigned nr,
bool has_error_code, u32 error_code);
bool (*exception_injected)(struct kvm_vcpu *vcpu);
- void (*inject_pending_irq)(struct kvm_vcpu *vcpu);
+ void (*inject_pending_irq)(struct kvm_vcpu *vcpu, struct kvm_run *run);
void (*inject_pending_vectors)(struct kvm_vcpu *vcpu,
struct kvm_run *run);
int (*interrupt_allowed)(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 7ac57e7..52c41aa 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2289,7 +2289,7 @@ static int svm_interrupt_allowed(struct kvm_vcpu *vcpu)
(svm->vcpu.arch.hflags & HF_GIF_MASK);
}
-static void svm_intr_assist(struct kvm_vcpu *vcpu)
+static void svm_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
struct vcpu_svm *svm = to_svm(vcpu);
struct vmcb *vmcb = svm->vmcb;
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index b3292c1..06252f7 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2510,48 +2510,6 @@ static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
return vcpu->arch.interrupt_window_open;
}
-static void do_interrupt_requests(struct kvm_vcpu *vcpu,
- struct kvm_run *kvm_run)
-{
- vmx_update_window_states(vcpu);
-
- if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
- vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
- GUEST_INTR_STATE_STI |
- GUEST_INTR_STATE_MOV_SS);
-
- if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) {
- if (vcpu->arch.interrupt.pending) {
- enable_nmi_window(vcpu);
- } else if (vcpu->arch.nmi_window_open) {
- vcpu->arch.nmi_pending = false;
- vcpu->arch.nmi_injected = true;
- } else {
- enable_nmi_window(vcpu);
- return;
- }
- }
- if (vcpu->arch.nmi_injected) {
- vmx_inject_nmi(vcpu);
- if (vcpu->arch.nmi_pending)
- enable_nmi_window(vcpu);
- else if (kvm_cpu_has_interrupt(vcpu) ||
- kvm_run->request_interrupt_window)
- enable_irq_window(vcpu);
- return;
- }
-
- if (vcpu->arch.interrupt_window_open) {
- if (kvm_cpu_has_interrupt(vcpu) && !vcpu->arch.interrupt.pending)
- kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
-
- if (vcpu->arch.interrupt.pending)
- vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
- } else if(kvm_cpu_has_interrupt(vcpu) ||
- kvm_run->request_interrupt_window)
- enable_irq_window(vcpu);
-}
-
static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
{
int ret;
@@ -3351,8 +3309,11 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
}
}
-static void vmx_intr_assist(struct kvm_vcpu *vcpu)
+static void vmx_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
+ bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
+ kvm_run->request_interrupt_window;
+
update_tpr_threshold(vcpu);
vmx_update_window_states(vcpu);
@@ -3373,25 +3334,25 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
return;
}
}
+
if (vcpu->arch.nmi_injected) {
vmx_inject_nmi(vcpu);
- if (vcpu->arch.nmi_pending)
- enable_nmi_window(vcpu);
- else if (kvm_cpu_has_interrupt(vcpu))
- enable_irq_window(vcpu);
- return;
+ goto out;
}
+
if (!vcpu->arch.interrupt.pending && kvm_cpu_has_interrupt(vcpu)) {
if (vcpu->arch.interrupt_window_open)
kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
- else
- enable_irq_window(vcpu);
}
- if (vcpu->arch.interrupt.pending) {
+
+ if (vcpu->arch.interrupt.pending)
vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
- if (kvm_cpu_has_interrupt(vcpu))
- enable_irq_window(vcpu);
- }
+
+out:
+ if (vcpu->arch.nmi_pending)
+ enable_nmi_window(vcpu);
+ else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
+ enable_irq_window(vcpu);
}
/*
@@ -3733,7 +3694,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
.queue_exception = vmx_queue_exception,
.exception_injected = vmx_exception_injected,
.inject_pending_irq = vmx_intr_assist,
- .inject_pending_vectors = do_interrupt_requests,
+ .inject_pending_vectors = vmx_intr_assist,
.interrupt_allowed = vmx_interrupt_allowed,
.set_tss_addr = vmx_set_tss_addr,
.get_tdp_level = get_ept_level,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 7184f55..dfcf358 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3163,7 +3163,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
if (vcpu->arch.exception.pending)
__queue_exception(vcpu);
else if (irqchip_in_kernel(vcpu->kvm))
- kvm_x86_ops->inject_pending_irq(vcpu);
+ kvm_x86_ops->inject_pending_irq(vcpu, kvm_run);
else
kvm_x86_ops->inject_pending_vectors(vcpu, kvm_run);
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 03/16] Cleanup vmx_intr_assist()
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
2009-04-21 14:44 ` [PATCH v2 01/16] Make kvm_cpu_(has|get)_interrupt() work for userspace irqchip too Gleb Natapov
2009-04-21 14:44 ` [PATCH v2 02/16] Consolidate userspace and kernel interrupt injection for VMX Gleb Natapov
@ 2009-04-21 14:44 ` Gleb Natapov
2009-04-21 14:44 ` [PATCH v2 04/16] Use kvm_arch_interrupt_allowed() instead of checking interrupt_window_open directly Gleb Natapov
` (13 subsequent siblings)
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:44 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/kvm/vmx.c | 55 ++++++++++++++++++++++++++++-----------------------
1 files changed, 30 insertions(+), 25 deletions(-)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 06252f7..9eb518f 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3309,6 +3309,34 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
}
}
+static void vmx_intr_inject(struct kvm_vcpu *vcpu)
+{
+ /* try to reinject previous events if any */
+ if (vcpu->arch.nmi_injected) {
+ vmx_inject_nmi(vcpu);
+ return;
+ }
+
+ if (vcpu->arch.interrupt.pending) {
+ vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
+ return;
+ }
+
+ /* try to inject new event if pending */
+ if (vcpu->arch.nmi_pending) {
+ if (vcpu->arch.nmi_window_open) {
+ vcpu->arch.nmi_pending = false;
+ vcpu->arch.nmi_injected = true;
+ vmx_inject_nmi(vcpu);
+ }
+ } else if (kvm_cpu_has_interrupt(vcpu)) {
+ if (vcpu->arch.interrupt_window_open) {
+ kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
+ vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
+ }
+ }
+}
+
static void vmx_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
@@ -3323,32 +3351,9 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
GUEST_INTR_STATE_STI |
GUEST_INTR_STATE_MOV_SS);
- if (vcpu->arch.nmi_pending && !vcpu->arch.nmi_injected) {
- if (vcpu->arch.interrupt.pending) {
- enable_nmi_window(vcpu);
- } else if (vcpu->arch.nmi_window_open) {
- vcpu->arch.nmi_pending = false;
- vcpu->arch.nmi_injected = true;
- } else {
- enable_nmi_window(vcpu);
- return;
- }
- }
-
- if (vcpu->arch.nmi_injected) {
- vmx_inject_nmi(vcpu);
- goto out;
- }
-
- if (!vcpu->arch.interrupt.pending && kvm_cpu_has_interrupt(vcpu)) {
- if (vcpu->arch.interrupt_window_open)
- kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
- }
-
- if (vcpu->arch.interrupt.pending)
- vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
+ vmx_intr_inject(vcpu);
-out:
+ /* enable NMI/IRQ window open exits if needed */
if (vcpu->arch.nmi_pending)
enable_nmi_window(vcpu);
else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 04/16] Use kvm_arch_interrupt_allowed() instead of checking interrupt_window_open directly
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (2 preceding siblings ...)
2009-04-21 14:44 ` [PATCH v2 03/16] Cleanup vmx_intr_assist() Gleb Natapov
@ 2009-04-21 14:44 ` Gleb Natapov
2009-04-21 14:45 ` [PATCH v2 05/16] Coalesce userspace/kernel irqchip interrupt injection logic Gleb Natapov
` (12 subsequent siblings)
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:44 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
kvm_arch_interrupt_allowed() also checks IF so drop the check.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/kvm/x86.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index dfcf358..f6aaa15 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3061,8 +3061,7 @@ static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu,
{
return (!irqchip_in_kernel(vcpu->kvm) && !kvm_cpu_has_interrupt(vcpu) &&
kvm_run->request_interrupt_window &&
- vcpu->arch.interrupt_window_open &&
- (kvm_x86_ops->get_rflags(vcpu) & X86_EFLAGS_IF));
+ kvm_arch_interrupt_allowed(vcpu));
}
static void post_kvm_run_save(struct kvm_vcpu *vcpu,
@@ -3075,7 +3074,7 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu,
kvm_run->ready_for_interrupt_injection = 1;
else
kvm_run->ready_for_interrupt_injection =
- (vcpu->arch.interrupt_window_open &&
+ (kvm_arch_interrupt_allowed(vcpu) &&
!kvm_cpu_has_interrupt(vcpu));
}
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 05/16] Coalesce userspace/kernel irqchip interrupt injection logic.
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (3 preceding siblings ...)
2009-04-21 14:44 ` [PATCH v2 04/16] Use kvm_arch_interrupt_allowed() instead of checking interrupt_window_open directly Gleb Natapov
@ 2009-04-21 14:45 ` Gleb Natapov
2009-04-23 14:14 ` Gleb Natapov
2009-04-21 14:45 ` [PATCH v2 06/16] Use EVENTINJ to inject interrupts Gleb Natapov
` (11 subsequent siblings)
16 siblings, 1 reply; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:45 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
Start to use interrupt/exception queues like VMX does.
This also fix the bug that if exit was caused by a guest
internal exception access to IDT the exception was not
reinjected.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/kvm/svm.c | 176 ++++++++++++++++++++++------------------------------
1 files changed, 75 insertions(+), 101 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 52c41aa..053370d 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -70,7 +70,6 @@ module_param(npt, int, S_IRUGO);
static int nested = 0;
module_param(nested, int, S_IRUGO);
-static void kvm_reput_irq(struct vcpu_svm *svm);
static void svm_flush_tlb(struct kvm_vcpu *vcpu);
static int nested_svm_exit_handled(struct vcpu_svm *svm, bool kvm_override);
@@ -199,9 +198,7 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
static bool svm_exception_injected(struct kvm_vcpu *vcpu)
{
- struct vcpu_svm *svm = to_svm(vcpu);
-
- return !(svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID);
+ return false;
}
static int is_external_interrupt(u32 info)
@@ -976,12 +973,9 @@ static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
static int svm_get_irq(struct kvm_vcpu *vcpu)
{
- struct vcpu_svm *svm = to_svm(vcpu);
- u32 exit_int_info = svm->vmcb->control.exit_int_info;
-
- if (is_external_interrupt(exit_int_info))
- return exit_int_info & SVM_EVTINJ_VEC_MASK;
- return -1;
+ if (!vcpu->arch.interrupt.pending)
+ return -1;
+ return vcpu->arch.interrupt.nr;
}
static void load_host_msrs(struct kvm_vcpu *vcpu)
@@ -1088,17 +1082,8 @@ static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value,
static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
{
- u32 exit_int_info = svm->vmcb->control.exit_int_info;
- struct kvm *kvm = svm->vcpu.kvm;
u64 fault_address;
u32 error_code;
- bool event_injection = false;
-
- if (!irqchip_in_kernel(kvm) &&
- is_external_interrupt(exit_int_info)) {
- event_injection = true;
- kvm_push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK);
- }
fault_address = svm->vmcb->control.exit_info_2;
error_code = svm->vmcb->control.exit_info_1;
@@ -1118,9 +1103,11 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
*/
if (npt_enabled)
svm_flush_tlb(&svm->vcpu);
-
- if (!npt_enabled && event_injection)
- kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
+ else {
+ if (svm->vcpu.arch.interrupt.pending ||
+ svm->vcpu.arch.exception.pending)
+ kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
+ }
return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code);
}
@@ -2187,7 +2174,6 @@ static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
}
}
- kvm_reput_irq(svm);
if (svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
@@ -2289,98 +2275,47 @@ static int svm_interrupt_allowed(struct kvm_vcpu *vcpu)
(svm->vcpu.arch.hflags & HF_GIF_MASK);
}
-static void svm_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+static void enable_irq_window(struct kvm_vcpu *vcpu)
{
- struct vcpu_svm *svm = to_svm(vcpu);
- struct vmcb *vmcb = svm->vmcb;
- int intr_vector = -1;
-
- if ((vmcb->control.exit_int_info & SVM_EVTINJ_VALID) &&
- ((vmcb->control.exit_int_info & SVM_EVTINJ_TYPE_MASK) == 0)) {
- intr_vector = vmcb->control.exit_int_info &
- SVM_EVTINJ_VEC_MASK;
- vmcb->control.exit_int_info = 0;
- svm_inject_irq(svm, intr_vector);
- goto out;
- }
-
- if (vmcb->control.int_ctl & V_IRQ_MASK)
- goto out;
-
- if (!kvm_cpu_has_interrupt(vcpu))
- goto out;
-
- if (nested_svm_intr(svm))
- goto out;
-
- if (!(svm->vcpu.arch.hflags & HF_GIF_MASK))
- goto out;
-
- if (!(vmcb->save.rflags & X86_EFLAGS_IF) ||
- (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) ||
- (vmcb->control.event_inj & SVM_EVTINJ_VALID)) {
- /* unable to deliver irq, set pending irq */
- svm_set_vintr(svm);
- svm_inject_irq(svm, 0x0);
- goto out;
- }
- /* Okay, we can deliver the interrupt: grab it and update PIC state. */
- intr_vector = kvm_cpu_get_interrupt(vcpu);
- svm_inject_irq(svm, intr_vector);
-out:
- update_cr8_intercept(vcpu);
+ svm_set_vintr(to_svm(vcpu));
+ svm_inject_irq(to_svm(vcpu), 0x0);
}
-static void kvm_reput_irq(struct vcpu_svm *svm)
+static void svm_intr_inject(struct kvm_vcpu *vcpu)
{
- struct vmcb_control_area *control = &svm->vmcb->control;
-
- if ((control->int_ctl & V_IRQ_MASK)
- && !irqchip_in_kernel(svm->vcpu.kvm)) {
- control->int_ctl &= ~V_IRQ_MASK;
- kvm_push_irq(&svm->vcpu, control->int_vector);
+ /* try to reinject previous events if any */
+ if (vcpu->arch.interrupt.pending) {
+ svm_inject_irq(to_svm(vcpu), vcpu->arch.interrupt.nr);
+ return;
}
- svm->vcpu.arch.interrupt_window_open =
- !(control->int_state & SVM_INTERRUPT_SHADOW_MASK) &&
- (svm->vcpu.arch.hflags & HF_GIF_MASK);
-}
-
-static void svm_do_inject_vector(struct vcpu_svm *svm)
-{
- svm_inject_irq(svm, kvm_pop_irq(&svm->vcpu));
+ /* try to inject new event if pending */
+ if (kvm_cpu_has_interrupt(vcpu)) {
+ if (vcpu->arch.interrupt_window_open) {
+ kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
+ svm_inject_irq(to_svm(vcpu), vcpu->arch.interrupt.nr);
+ }
+ }
}
-static void do_interrupt_requests(struct kvm_vcpu *vcpu,
- struct kvm_run *kvm_run)
+static void svm_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
struct vcpu_svm *svm = to_svm(vcpu);
- struct vmcb_control_area *control = &svm->vmcb->control;
+ bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
+ kvm_run->request_interrupt_window;
if (nested_svm_intr(svm))
- return;
+ goto out;
- svm->vcpu.arch.interrupt_window_open =
- (!(control->int_state & SVM_INTERRUPT_SHADOW_MASK) &&
- (svm->vmcb->save.rflags & X86_EFLAGS_IF) &&
- (svm->vcpu.arch.hflags & HF_GIF_MASK));
+ svm->vcpu.arch.interrupt_window_open = svm_interrupt_allowed(vcpu);
- if (svm->vcpu.arch.interrupt_window_open &&
- kvm_cpu_has_interrupt(&svm->vcpu))
- /*
- * If interrupts enabled, and not blocked by sti or mov ss. Good.
- */
- svm_do_inject_vector(svm);
+ svm_intr_inject(vcpu);
- /*
- * Interrupts blocked. Wait for unblock.
- */
- if (!svm->vcpu.arch.interrupt_window_open &&
- (kvm_cpu_has_interrupt(&svm->vcpu) ||
- kvm_run->request_interrupt_window))
- svm_set_vintr(svm);
- else
- svm_clear_vintr(svm);
+ if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
+ enable_irq_window(vcpu);
+
+out:
+ update_cr8_intercept(vcpu);
}
static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr)
@@ -2420,6 +2355,43 @@ static inline void sync_lapic_to_cr8(struct kvm_vcpu *vcpu)
svm->vmcb->control.int_ctl |= cr8 & V_TPR_MASK;
}
+static void svm_complete_interrupts(struct vcpu_svm *svm)
+{
+ u8 vector;
+ int type;
+ u32 exitintinfo = svm->vmcb->control.exit_int_info;
+
+ svm->vcpu.arch.nmi_injected = false;
+ kvm_clear_exception_queue(&svm->vcpu);
+ kvm_clear_interrupt_queue(&svm->vcpu);
+
+ if (!(exitintinfo & SVM_EXITINTINFO_VALID))
+ return;
+
+ vector = exitintinfo & SVM_EXITINTINFO_VEC_MASK;
+ type = exitintinfo & SVM_EXITINTINFO_TYPE_MASK;
+
+ switch (type) {
+ case SVM_EXITINTINFO_TYPE_NMI:
+ svm->vcpu.arch.nmi_injected = true;
+ break;
+ case SVM_EXITINTINFO_TYPE_EXEPT:
+ if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) {
+ u32 err = svm->vmcb->control.exit_int_info_err;
+ kvm_queue_exception_e(&svm->vcpu, vector, err);
+
+ } else
+ kvm_queue_exception(&svm->vcpu, vector);
+ break;
+ case SVM_EXITINTINFO_TYPE_SOFT:
+ case SVM_EXITINTINFO_TYPE_INTR:
+ kvm_queue_interrupt(&svm->vcpu, vector);
+ break;
+ default:
+ break;
+ }
+}
+
#ifdef CONFIG_X86_64
#define R "r"
#else
@@ -2548,6 +2520,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
sync_cr8_to_lapic(vcpu);
svm->next_rip = 0;
+
+ svm_complete_interrupts(svm);
}
#undef R
@@ -2669,7 +2643,7 @@ static struct kvm_x86_ops svm_x86_ops = {
.queue_exception = svm_queue_exception,
.exception_injected = svm_exception_injected,
.inject_pending_irq = svm_intr_assist,
- .inject_pending_vectors = do_interrupt_requests,
+ .inject_pending_vectors = svm_intr_assist,
.interrupt_allowed = svm_interrupt_allowed,
.set_tss_addr = svm_set_tss_addr,
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [PATCH v2 05/16] Coalesce userspace/kernel irqchip interrupt injection logic.
2009-04-21 14:45 ` [PATCH v2 05/16] Coalesce userspace/kernel irqchip interrupt injection logic Gleb Natapov
@ 2009-04-23 14:14 ` Gleb Natapov
0 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-23 14:14 UTC (permalink / raw)
To: avi; +Cc: kvm
Please use this patch instead of previous one. The difference is that in
this one if fault happens during soft interrupt (int) or soft exceptions
(into, int3) the event is not re-injected since instruction will be
re-executed anyway.
Start to use interrupt/exception queues like VMX does.
This also fix the bug that if exit was caused by a guest
internal exception access to IDT the exception was not
reinjected.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 674a249..63c265a 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -70,7 +70,6 @@ module_param(npt, int, S_IRUGO);
static int nested = 0;
module_param(nested, int, S_IRUGO);
-static void kvm_reput_irq(struct vcpu_svm *svm);
static void svm_flush_tlb(struct kvm_vcpu *vcpu);
static int nested_svm_exit_handled(struct vcpu_svm *svm, bool kvm_override);
@@ -199,9 +198,7 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
static bool svm_exception_injected(struct kvm_vcpu *vcpu)
{
- struct vcpu_svm *svm = to_svm(vcpu);
-
- return !(svm->vmcb->control.exit_int_info & SVM_EXITINTINFO_VALID);
+ return false;
}
static int is_external_interrupt(u32 info)
@@ -976,12 +973,9 @@ static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
static int svm_get_irq(struct kvm_vcpu *vcpu)
{
- struct vcpu_svm *svm = to_svm(vcpu);
- u32 exit_int_info = svm->vmcb->control.exit_int_info;
-
- if (is_external_interrupt(exit_int_info))
- return exit_int_info & SVM_EVTINJ_VEC_MASK;
- return -1;
+ if (!vcpu->arch.interrupt.pending)
+ return -1;
+ return vcpu->arch.interrupt.nr;
}
static void load_host_msrs(struct kvm_vcpu *vcpu)
@@ -1088,17 +1082,8 @@ static void svm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long value,
static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
{
- u32 exit_int_info = svm->vmcb->control.exit_int_info;
- struct kvm *kvm = svm->vcpu.kvm;
u64 fault_address;
u32 error_code;
- bool event_injection = false;
-
- if (!irqchip_in_kernel(kvm) &&
- is_external_interrupt(exit_int_info)) {
- event_injection = true;
- kvm_push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK);
- }
fault_address = svm->vmcb->control.exit_info_2;
error_code = svm->vmcb->control.exit_info_1;
@@ -1118,9 +1103,11 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
*/
if (npt_enabled)
svm_flush_tlb(&svm->vcpu);
-
- if (!npt_enabled && event_injection)
- kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
+ else {
+ if (svm->vcpu.arch.interrupt.pending ||
+ svm->vcpu.arch.exception.pending)
+ kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
+ }
return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code);
}
@@ -2194,7 +2181,6 @@ static int handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
}
}
- kvm_reput_irq(svm);
if (svm->vmcb->control.exit_code == SVM_EXIT_ERR) {
kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
@@ -2296,98 +2282,47 @@ static int svm_interrupt_allowed(struct kvm_vcpu *vcpu)
(svm->vcpu.arch.hflags & HF_GIF_MASK);
}
-static void svm_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+static void enable_irq_window(struct kvm_vcpu *vcpu)
{
- struct vcpu_svm *svm = to_svm(vcpu);
- struct vmcb *vmcb = svm->vmcb;
- int intr_vector = -1;
-
- if ((vmcb->control.exit_int_info & SVM_EVTINJ_VALID) &&
- ((vmcb->control.exit_int_info & SVM_EVTINJ_TYPE_MASK) == 0)) {
- intr_vector = vmcb->control.exit_int_info &
- SVM_EVTINJ_VEC_MASK;
- vmcb->control.exit_int_info = 0;
- svm_inject_irq(svm, intr_vector);
- goto out;
- }
-
- if (vmcb->control.int_ctl & V_IRQ_MASK)
- goto out;
-
- if (!kvm_cpu_has_interrupt(vcpu))
- goto out;
-
- if (nested_svm_intr(svm))
- goto out;
-
- if (!(svm->vcpu.arch.hflags & HF_GIF_MASK))
- goto out;
-
- if (!(vmcb->save.rflags & X86_EFLAGS_IF) ||
- (vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) ||
- (vmcb->control.event_inj & SVM_EVTINJ_VALID)) {
- /* unable to deliver irq, set pending irq */
- svm_set_vintr(svm);
- svm_inject_irq(svm, 0x0);
- goto out;
- }
- /* Okay, we can deliver the interrupt: grab it and update PIC state. */
- intr_vector = kvm_cpu_get_interrupt(vcpu);
- svm_inject_irq(svm, intr_vector);
-out:
- update_cr8_intercept(vcpu);
+ svm_set_vintr(to_svm(vcpu));
+ svm_inject_irq(to_svm(vcpu), 0x0);
}
-static void kvm_reput_irq(struct vcpu_svm *svm)
+static void svm_intr_inject(struct kvm_vcpu *vcpu)
{
- struct vmcb_control_area *control = &svm->vmcb->control;
-
- if ((control->int_ctl & V_IRQ_MASK)
- && !irqchip_in_kernel(svm->vcpu.kvm)) {
- control->int_ctl &= ~V_IRQ_MASK;
- kvm_push_irq(&svm->vcpu, control->int_vector);
+ /* try to reinject previous events if any */
+ if (vcpu->arch.interrupt.pending) {
+ svm_inject_irq(to_svm(vcpu), vcpu->arch.interrupt.nr);
+ return;
}
- svm->vcpu.arch.interrupt_window_open =
- !(control->int_state & SVM_INTERRUPT_SHADOW_MASK) &&
- (svm->vcpu.arch.hflags & HF_GIF_MASK);
-}
-
-static void svm_do_inject_vector(struct vcpu_svm *svm)
-{
- svm_inject_irq(svm, kvm_pop_irq(&svm->vcpu));
+ /* try to inject new event if pending */
+ if (kvm_cpu_has_interrupt(vcpu)) {
+ if (vcpu->arch.interrupt_window_open) {
+ kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
+ svm_inject_irq(to_svm(vcpu), vcpu->arch.interrupt.nr);
+ }
+ }
}
-static void do_interrupt_requests(struct kvm_vcpu *vcpu,
- struct kvm_run *kvm_run)
+static void svm_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
struct vcpu_svm *svm = to_svm(vcpu);
- struct vmcb_control_area *control = &svm->vmcb->control;
+ bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
+ kvm_run->request_interrupt_window;
if (nested_svm_intr(svm))
- return;
+ goto out;
- svm->vcpu.arch.interrupt_window_open =
- (!(control->int_state & SVM_INTERRUPT_SHADOW_MASK) &&
- (svm->vmcb->save.rflags & X86_EFLAGS_IF) &&
- (svm->vcpu.arch.hflags & HF_GIF_MASK));
+ svm->vcpu.arch.interrupt_window_open = svm_interrupt_allowed(vcpu);
- if (svm->vcpu.arch.interrupt_window_open &&
- kvm_cpu_has_interrupt(&svm->vcpu))
- /*
- * If interrupts enabled, and not blocked by sti or mov ss. Good.
- */
- svm_do_inject_vector(svm);
+ svm_intr_inject(vcpu);
- /*
- * Interrupts blocked. Wait for unblock.
- */
- if (!svm->vcpu.arch.interrupt_window_open &&
- (kvm_cpu_has_interrupt(&svm->vcpu) ||
- kvm_run->request_interrupt_window))
- svm_set_vintr(svm);
- else
- svm_clear_vintr(svm);
+ if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
+ enable_irq_window(vcpu);
+
+out:
+ update_cr8_intercept(vcpu);
}
static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr)
@@ -2427,6 +2362,46 @@ static inline void sync_lapic_to_cr8(struct kvm_vcpu *vcpu)
svm->vmcb->control.int_ctl |= cr8 & V_TPR_MASK;
}
+static void svm_complete_interrupts(struct vcpu_svm *svm)
+{
+ u8 vector;
+ int type;
+ u32 exitintinfo = svm->vmcb->control.exit_int_info;
+
+ svm->vcpu.arch.nmi_injected = false;
+ kvm_clear_exception_queue(&svm->vcpu);
+ kvm_clear_interrupt_queue(&svm->vcpu);
+
+ if (!(exitintinfo & SVM_EXITINTINFO_VALID))
+ return;
+
+ vector = exitintinfo & SVM_EXITINTINFO_VEC_MASK;
+ type = exitintinfo & SVM_EXITINTINFO_TYPE_MASK;
+
+ switch (type) {
+ case SVM_EXITINTINFO_TYPE_NMI:
+ svm->vcpu.arch.nmi_injected = true;
+ break;
+ case SVM_EXITINTINFO_TYPE_EXEPT:
+ /* In case of software exception do not reinject an exception
+ vector, but re-execute and instruction instead */
+ if (vector == BP_VECTOR || vector == OF_VECTOR)
+ break;
+ if (exitintinfo & SVM_EXITINTINFO_VALID_ERR) {
+ u32 err = svm->vmcb->control.exit_int_info_err;
+ kvm_queue_exception_e(&svm->vcpu, vector, err);
+
+ } else
+ kvm_queue_exception(&svm->vcpu, vector);
+ break;
+ case SVM_EXITINTINFO_TYPE_INTR:
+ kvm_queue_interrupt(&svm->vcpu, vector);
+ break;
+ default:
+ break;
+ }
+}
+
#ifdef CONFIG_X86_64
#define R "r"
#else
@@ -2555,6 +2530,8 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
sync_cr8_to_lapic(vcpu);
svm->next_rip = 0;
+
+ svm_complete_interrupts(svm);
}
#undef R
@@ -2676,7 +2653,7 @@ static struct kvm_x86_ops svm_x86_ops = {
.queue_exception = svm_queue_exception,
.exception_injected = svm_exception_injected,
.inject_pending_irq = svm_intr_assist,
- .inject_pending_vectors = do_interrupt_requests,
+ .inject_pending_vectors = svm_intr_assist,
.interrupt_allowed = svm_interrupt_allowed,
.set_tss_addr = svm_set_tss_addr,
--
Gleb.
^ permalink raw reply related [flat|nested] 26+ messages in thread
* [PATCH v2 06/16] Use EVENTINJ to inject interrupts.
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (4 preceding siblings ...)
2009-04-21 14:45 ` [PATCH v2 05/16] Coalesce userspace/kernel irqchip interrupt injection logic Gleb Natapov
@ 2009-04-21 14:45 ` Gleb Natapov
2009-04-21 14:45 ` [PATCH v2 07/16] Remove exception_injected() callback Gleb Natapov
` (10 subsequent siblings)
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:45 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
Use VINT only for detecting when IRQ windows is open again.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/kvm/svm.c | 12 +++++++++---
1 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 053370d..3b4c00f 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2236,13 +2236,19 @@ static inline void svm_inject_irq(struct vcpu_svm *svm, int irq)
((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT);
}
+static void svm_queue_irq(struct vcpu_svm *svm, unsigned nr)
+{
+ svm->vmcb->control.event_inj = nr |
+ SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR;
+}
+
static void svm_set_irq(struct kvm_vcpu *vcpu, int irq)
{
struct vcpu_svm *svm = to_svm(vcpu);
nested_svm_intr(svm);
- svm_inject_irq(svm, irq);
+ svm_queue_irq(svm, irq);
}
static void update_cr8_intercept(struct kvm_vcpu *vcpu)
@@ -2285,7 +2291,7 @@ static void svm_intr_inject(struct kvm_vcpu *vcpu)
{
/* try to reinject previous events if any */
if (vcpu->arch.interrupt.pending) {
- svm_inject_irq(to_svm(vcpu), vcpu->arch.interrupt.nr);
+ svm_queue_irq(to_svm(vcpu), vcpu->arch.interrupt.nr);
return;
}
@@ -2293,7 +2299,7 @@ static void svm_intr_inject(struct kvm_vcpu *vcpu)
if (kvm_cpu_has_interrupt(vcpu)) {
if (vcpu->arch.interrupt_window_open) {
kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
- svm_inject_irq(to_svm(vcpu), vcpu->arch.interrupt.nr);
+ svm_queue_irq(to_svm(vcpu), vcpu->arch.interrupt.nr);
}
}
}
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 07/16] Remove exception_injected() callback.
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (5 preceding siblings ...)
2009-04-21 14:45 ` [PATCH v2 06/16] Use EVENTINJ to inject interrupts Gleb Natapov
@ 2009-04-21 14:45 ` Gleb Natapov
2009-04-21 14:45 ` [PATCH v2 08/16] Remove inject_pending_vectors() callback Gleb Natapov
` (9 subsequent siblings)
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:45 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
It always return false for VMX/SVM now.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/include/asm/kvm_host.h | 1 -
arch/x86/kvm/svm.c | 6 ------
arch/x86/kvm/vmx.c | 6 ------
arch/x86/kvm/x86.c | 2 --
4 files changed, 0 insertions(+), 15 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 4a9022d..fc29e36 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -519,7 +519,6 @@ struct kvm_x86_ops {
void (*set_irq)(struct kvm_vcpu *vcpu, int vec);
void (*queue_exception)(struct kvm_vcpu *vcpu, unsigned nr,
bool has_error_code, u32 error_code);
- bool (*exception_injected)(struct kvm_vcpu *vcpu);
void (*inject_pending_irq)(struct kvm_vcpu *vcpu, struct kvm_run *run);
void (*inject_pending_vectors)(struct kvm_vcpu *vcpu,
struct kvm_run *run);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 3b4c00f..d6bc56a 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -196,11 +196,6 @@ static void svm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
svm->vmcb->control.event_inj_err = error_code;
}
-static bool svm_exception_injected(struct kvm_vcpu *vcpu)
-{
- return false;
-}
-
static int is_external_interrupt(u32 info)
{
info &= SVM_EVTINJ_TYPE_MASK | SVM_EVTINJ_VALID;
@@ -2647,7 +2642,6 @@ static struct kvm_x86_ops svm_x86_ops = {
.get_irq = svm_get_irq,
.set_irq = svm_set_irq,
.queue_exception = svm_queue_exception,
- .exception_injected = svm_exception_injected,
.inject_pending_irq = svm_intr_assist,
.inject_pending_vectors = svm_intr_assist,
.interrupt_allowed = svm_interrupt_allowed,
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 9eb518f..3186fcf 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -789,11 +789,6 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
}
-static bool vmx_exception_injected(struct kvm_vcpu *vcpu)
-{
- return false;
-}
-
/*
* Swap MSR entry in host/guest MSR entry array.
*/
@@ -3697,7 +3692,6 @@ static struct kvm_x86_ops vmx_x86_ops = {
.get_irq = vmx_get_irq,
.set_irq = vmx_inject_irq,
.queue_exception = vmx_queue_exception,
- .exception_injected = vmx_exception_injected,
.inject_pending_irq = vmx_intr_assist,
.inject_pending_vectors = vmx_intr_assist,
.interrupt_allowed = vmx_interrupt_allowed,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index f6aaa15..a50c8a3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3227,8 +3227,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
profile_hit(KVM_PROFILING, (void *)rip);
}
- if (vcpu->arch.exception.pending && kvm_x86_ops->exception_injected(vcpu))
- vcpu->arch.exception.pending = false;
kvm_lapic_sync_from_vapic(vcpu);
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 08/16] Remove inject_pending_vectors() callback.
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (6 preceding siblings ...)
2009-04-21 14:45 ` [PATCH v2 07/16] Remove exception_injected() callback Gleb Natapov
@ 2009-04-21 14:45 ` Gleb Natapov
2009-04-21 14:45 ` [PATCH v2 09/16] kvm_push_irq() no longer used Gleb Natapov
` (8 subsequent siblings)
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:45 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
It is the same as inject_pending_irq() for VMX/SVM now.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/include/asm/kvm_host.h | 2 --
arch/x86/kvm/svm.c | 1 -
arch/x86/kvm/vmx.c | 1 -
arch/x86/kvm/x86.c | 4 +---
4 files changed, 1 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index fc29e36..663dba8 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -520,8 +520,6 @@ struct kvm_x86_ops {
void (*queue_exception)(struct kvm_vcpu *vcpu, unsigned nr,
bool has_error_code, u32 error_code);
void (*inject_pending_irq)(struct kvm_vcpu *vcpu, struct kvm_run *run);
- void (*inject_pending_vectors)(struct kvm_vcpu *vcpu,
- struct kvm_run *run);
int (*interrupt_allowed)(struct kvm_vcpu *vcpu);
int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
int (*get_tdp_level)(void);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index d6bc56a..f8beddb 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2643,7 +2643,6 @@ static struct kvm_x86_ops svm_x86_ops = {
.set_irq = svm_set_irq,
.queue_exception = svm_queue_exception,
.inject_pending_irq = svm_intr_assist,
- .inject_pending_vectors = svm_intr_assist,
.interrupt_allowed = svm_interrupt_allowed,
.set_tss_addr = svm_set_tss_addr,
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 3186fcf..9162b4c 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3693,7 +3693,6 @@ static struct kvm_x86_ops vmx_x86_ops = {
.set_irq = vmx_inject_irq,
.queue_exception = vmx_queue_exception,
.inject_pending_irq = vmx_intr_assist,
- .inject_pending_vectors = vmx_intr_assist,
.interrupt_allowed = vmx_interrupt_allowed,
.set_tss_addr = vmx_set_tss_addr,
.get_tdp_level = get_ept_level,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index a50c8a3..d94a152 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3161,10 +3161,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
if (vcpu->arch.exception.pending)
__queue_exception(vcpu);
- else if (irqchip_in_kernel(vcpu->kvm))
- kvm_x86_ops->inject_pending_irq(vcpu, kvm_run);
else
- kvm_x86_ops->inject_pending_vectors(vcpu, kvm_run);
+ kvm_x86_ops->inject_pending_irq(vcpu, kvm_run);
kvm_lapic_sync_to_vapic(vcpu);
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 09/16] kvm_push_irq() no longer used.
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (7 preceding siblings ...)
2009-04-21 14:45 ` [PATCH v2 08/16] Remove inject_pending_vectors() callback Gleb Natapov
@ 2009-04-21 14:45 ` Gleb Natapov
2009-04-21 14:45 ` [PATCH v2 10/16] sync_lapic_to_cr8() should always sync cr8 to V_TPR Gleb Natapov
` (7 subsequent siblings)
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:45 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
Remove it.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/kvm/x86.h | 7 -------
1 files changed, 0 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 2ab6791..39350b2 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -30,11 +30,4 @@ static inline u8 kvm_pop_irq(struct kvm_vcpu *vcpu)
clear_bit(word_index, &vcpu->arch.irq_summary);
return irq;
}
-
-static inline void kvm_push_irq(struct kvm_vcpu *vcpu, u8 irq)
-{
- set_bit(irq, vcpu->arch.irq_pending);
- set_bit(irq / BITS_PER_LONG, &vcpu->arch.irq_summary);
-}
-
#endif
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 10/16] sync_lapic_to_cr8() should always sync cr8 to V_TPR.
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (8 preceding siblings ...)
2009-04-21 14:45 ` [PATCH v2 09/16] kvm_push_irq() no longer used Gleb Natapov
@ 2009-04-21 14:45 ` Gleb Natapov
2009-04-21 14:45 ` [PATCH v2 11/16] Do not report TPR write to userspace if new value bigger or equal to a previous one Gleb Natapov
` (6 subsequent siblings)
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:45 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
Even if IRQ chip is in userspace.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/kvm/svm.c | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index f8beddb..52bd999 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2339,7 +2339,7 @@ static inline void sync_cr8_to_lapic(struct kvm_vcpu *vcpu)
if (!(svm->vmcb->control.intercept_cr_write & INTERCEPT_CR8_MASK)) {
int cr8 = svm->vmcb->control.int_ctl & V_TPR_MASK;
- kvm_lapic_set_tpr(vcpu, cr8);
+ kvm_set_cr8(vcpu, cr8);
}
}
@@ -2348,9 +2348,6 @@ static inline void sync_lapic_to_cr8(struct kvm_vcpu *vcpu)
struct vcpu_svm *svm = to_svm(vcpu);
u64 cr8;
- if (!irqchip_in_kernel(vcpu->kvm))
- return;
-
cr8 = kvm_get_cr8(vcpu);
svm->vmcb->control.int_ctl &= ~V_TPR_MASK;
svm->vmcb->control.int_ctl |= cr8 & V_TPR_MASK;
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 11/16] Do not report TPR write to userspace if new value bigger or equal to a previous one.
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (9 preceding siblings ...)
2009-04-21 14:45 ` [PATCH v2 10/16] sync_lapic_to_cr8() should always sync cr8 to V_TPR Gleb Natapov
@ 2009-04-21 14:45 ` Gleb Natapov
2009-04-21 14:45 ` [PATCH v2 12/16] Get rid of arch.interrupt_window_open & arch.nmi_window_open Gleb Natapov
` (5 subsequent siblings)
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:45 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
Saves many exits to userspace in a case of IRQ chip in userspace.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/kvm/svm.c | 4 ++++
arch/x86/kvm/vmx.c | 19 ++++++++++++-------
2 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 52bd999..9a8eb14 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1853,9 +1853,13 @@ static int emulate_on_interception(struct vcpu_svm *svm,
static int cr8_write_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
{
+ u8 cr8_prev = kvm_get_cr8(&svm->vcpu);
+ /* instruction emulation calls kvm_set_cr8() */
emulate_instruction(&svm->vcpu, NULL, 0, 0, 0);
if (irqchip_in_kernel(svm->vcpu.kvm))
return 1;
+ if (cr8_prev <= kvm_get_cr8(&svm->vcpu))
+ return 1;
kvm_run->exit_reason = KVM_EXIT_SET_TPR;
return 0;
}
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 9162b4c..51f804c 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2724,13 +2724,18 @@ static int handle_cr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
kvm_set_cr4(vcpu, kvm_register_read(vcpu, reg));
skip_emulated_instruction(vcpu);
return 1;
- case 8:
- kvm_set_cr8(vcpu, kvm_register_read(vcpu, reg));
- skip_emulated_instruction(vcpu);
- if (irqchip_in_kernel(vcpu->kvm))
- return 1;
- kvm_run->exit_reason = KVM_EXIT_SET_TPR;
- return 0;
+ case 8: {
+ u8 cr8_prev = kvm_get_cr8(vcpu);
+ u8 cr8 = kvm_register_read(vcpu, reg);
+ kvm_set_cr8(vcpu, cr8);
+ skip_emulated_instruction(vcpu);
+ if (irqchip_in_kernel(vcpu->kvm))
+ return 1;
+ if (cr8_prev <= cr8)
+ return 1;
+ kvm_run->exit_reason = KVM_EXIT_SET_TPR;
+ return 0;
+ }
};
break;
case 2: /* clts */
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 12/16] Get rid of arch.interrupt_window_open & arch.nmi_window_open
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (10 preceding siblings ...)
2009-04-21 14:45 ` [PATCH v2 11/16] Do not report TPR write to userspace if new value bigger or equal to a previous one Gleb Natapov
@ 2009-04-21 14:45 ` Gleb Natapov
2009-04-21 14:45 ` [PATCH v2 13/16] Add NMI injection support to SVM Gleb Natapov
` (4 subsequent siblings)
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:45 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
They are recalculated before each use anyway.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/include/asm/kvm_host.h | 2 --
arch/x86/kvm/svm.c | 6 +-----
arch/x86/kvm/vmx.c | 35 +++++++++++------------------------
3 files changed, 12 insertions(+), 31 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 663dba8..8b6f6e9 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -267,7 +267,6 @@ struct kvm_mmu {
struct kvm_vcpu_arch {
u64 host_tsc;
- int interrupt_window_open;
unsigned long irq_summary; /* bit vector: 1 per word in irq_pending */
DECLARE_BITMAP(irq_pending, KVM_NR_INTERRUPTS);
/*
@@ -361,7 +360,6 @@ struct kvm_vcpu_arch {
bool nmi_pending;
bool nmi_injected;
- bool nmi_window_open;
struct mtrr_state_type mtrr_state;
u32 pat;
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 9a8eb14..c605477 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -216,8 +216,6 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
kvm_rip_write(vcpu, svm->next_rip);
svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
-
- vcpu->arch.interrupt_window_open = (svm->vcpu.arch.hflags & HF_GIF_MASK);
}
static int has_svm(void)
@@ -2296,7 +2294,7 @@ static void svm_intr_inject(struct kvm_vcpu *vcpu)
/* try to inject new event if pending */
if (kvm_cpu_has_interrupt(vcpu)) {
- if (vcpu->arch.interrupt_window_open) {
+ if (svm_interrupt_allowed(vcpu)) {
kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
svm_queue_irq(to_svm(vcpu), vcpu->arch.interrupt.nr);
}
@@ -2312,8 +2310,6 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
if (nested_svm_intr(svm))
goto out;
- svm->vcpu.arch.interrupt_window_open = svm_interrupt_allowed(vcpu);
-
svm_intr_inject(vcpu);
if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 51f804c..116eac0 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -753,7 +753,6 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
if (interruptibility & 3)
vmcs_write32(GUEST_INTERRUPTIBILITY_INFO,
interruptibility & ~3);
- vcpu->arch.interrupt_window_open = 1;
}
static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
@@ -2482,27 +2481,21 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);
}
-static void vmx_update_window_states(struct kvm_vcpu *vcpu)
+static int vmx_nmi_allowed(struct kvm_vcpu *vcpu)
{
- u32 guest_intr = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
-
- vcpu->arch.nmi_window_open =
- !(guest_intr & (GUEST_INTR_STATE_STI |
- GUEST_INTR_STATE_MOV_SS |
- GUEST_INTR_STATE_NMI));
if (!cpu_has_virtual_nmis() && to_vmx(vcpu)->soft_vnmi_blocked)
- vcpu->arch.nmi_window_open = 0;
+ return 0;
- vcpu->arch.interrupt_window_open =
- ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
- !(guest_intr & (GUEST_INTR_STATE_STI |
- GUEST_INTR_STATE_MOV_SS)));
+ return !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
+ (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS |
+ GUEST_INTR_STATE_NMI));
}
static int vmx_interrupt_allowed(struct kvm_vcpu *vcpu)
{
- vmx_update_window_states(vcpu);
- return vcpu->arch.interrupt_window_open;
+ return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
+ !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
+ (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS));
}
static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
@@ -3194,9 +3187,8 @@ static int vmx_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
__func__, vectoring_info, exit_reason);
if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked)) {
- if (vcpu->arch.interrupt_window_open) {
+ if (vmx_interrupt_allowed(vcpu)) {
vmx->soft_vnmi_blocked = 0;
- vcpu->arch.nmi_window_open = 1;
} else if (vmx->vnmi_blocked_time > 1000000000LL &&
vcpu->arch.nmi_pending) {
/*
@@ -3209,7 +3201,6 @@ static int vmx_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
"state on VCPU %d after 1 s timeout\n",
__func__, vcpu->vcpu_id);
vmx->soft_vnmi_blocked = 0;
- vmx->vcpu.arch.nmi_window_open = 1;
}
}
@@ -3324,13 +3315,13 @@ static void vmx_intr_inject(struct kvm_vcpu *vcpu)
/* try to inject new event if pending */
if (vcpu->arch.nmi_pending) {
- if (vcpu->arch.nmi_window_open) {
+ if (vmx_nmi_allowed(vcpu)) {
vcpu->arch.nmi_pending = false;
vcpu->arch.nmi_injected = true;
vmx_inject_nmi(vcpu);
}
} else if (kvm_cpu_has_interrupt(vcpu)) {
- if (vcpu->arch.interrupt_window_open) {
+ if (vmx_interrupt_allowed(vcpu)) {
kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
}
@@ -3344,8 +3335,6 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
update_tpr_threshold(vcpu);
- vmx_update_window_states(vcpu);
-
if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
GUEST_INTR_STATE_STI |
@@ -3518,8 +3507,6 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
if (vmx->rmode.irq.pending)
fixup_rmode_irq(vmx);
- vmx_update_window_states(vcpu);
-
asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
vmx->launched = 1;
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 13/16] Add NMI injection support to SVM.
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (11 preceding siblings ...)
2009-04-21 14:45 ` [PATCH v2 12/16] Get rid of arch.interrupt_window_open & arch.nmi_window_open Gleb Natapov
@ 2009-04-21 14:45 ` Gleb Natapov
2009-04-21 14:45 ` [PATCH v2 14/16] Move interrupt injection logic to x86.c Gleb Natapov
` (3 subsequent siblings)
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:45 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/include/asm/kvm_host.h | 1 +
arch/x86/kvm/svm.c | 50 +++++++++++++++++++++++++++++++++++++-
2 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 8b6f6e9..057a612 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -766,6 +766,7 @@ enum {
#define HF_GIF_MASK (1 << 0)
#define HF_HIF_MASK (1 << 1)
#define HF_VINTR_MASK (1 << 2)
+#define HF_NMI_MASK (1 << 3)
/*
* Hardware virtualization extension instructions may fault if a
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index c605477..3452bb4 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1834,6 +1834,14 @@ static int cpuid_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
return 1;
}
+static int iret_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
+{
+ ++svm->vcpu.stat.nmi_window_exits;
+ svm->vmcb->control.intercept &= ~(1UL << INTERCEPT_IRET);
+ svm->vcpu.arch.hflags &= ~HF_NMI_MASK;
+ return 1;
+}
+
static int invlpg_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
{
if (emulate_instruction(&svm->vcpu, kvm_run, 0, 0, 0) != EMULATE_DONE)
@@ -2111,6 +2119,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm,
[SVM_EXIT_VINTR] = interrupt_window_interception,
/* [SVM_EXIT_CR0_SEL_WRITE] = emulate_on_interception, */
[SVM_EXIT_CPUID] = cpuid_interception,
+ [SVM_EXIT_IRET] = iret_interception,
[SVM_EXIT_INVD] = emulate_on_interception,
[SVM_EXIT_HLT] = halt_interception,
[SVM_EXIT_INVLPG] = invlpg_interception,
@@ -2218,6 +2227,13 @@ static void pre_svm_run(struct vcpu_svm *svm)
new_asid(svm, svm_data);
}
+static void svm_inject_nmi(struct vcpu_svm *svm)
+{
+ svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI;
+ vcpu->arch.hflags |= HF_NMI_MASK;
+ svm->vmcb->control.intercept |= (1UL << INTERCEPT_IRET);
+ ++vcpu->stat.nmi_injections;
+}
static inline void svm_inject_irq(struct vcpu_svm *svm, int irq)
{
@@ -2269,6 +2285,14 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu)
vmcb->control.intercept_cr_write |= INTERCEPT_CR8_MASK;
}
+static int svm_nmi_allowed(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+ struct vmcb *vmcb = svm->vmcb;
+ return !(vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK) &&
+ !(svm->vcpu.arch.hflags & HF_NMI_MASK);
+}
+
static int svm_interrupt_allowed(struct kvm_vcpu *vcpu)
{
struct vcpu_svm *svm = to_svm(vcpu);
@@ -2284,16 +2308,35 @@ static void enable_irq_window(struct kvm_vcpu *vcpu)
svm_inject_irq(to_svm(vcpu), 0x0);
}
+static void enable_nmi_window(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+ if (svm->vmcb->control.int_state & SVM_INTERRUPT_SHADOW_MASK)
+ enable_irq_window(vcpu);
+}
+
static void svm_intr_inject(struct kvm_vcpu *vcpu)
{
/* try to reinject previous events if any */
+ if (vcpu->arch.nmi_injected) {
+ svm_inject_nmi(to_svm(vcpu));
+ return;
+ }
+
if (vcpu->arch.interrupt.pending) {
svm_queue_irq(to_svm(vcpu), vcpu->arch.interrupt.nr);
return;
}
/* try to inject new event if pending */
- if (kvm_cpu_has_interrupt(vcpu)) {
+ if (vcpu->arch.nmi_pending) {
+ if (svm_nmi_allowed(vcpu)) {
+ vcpu->arch.nmi_pending = false;
+ vcpu->arch.nmi_injected = true;
+ svm_inject_nmi(vcpu);
+ }
+ } else if (kvm_cpu_has_interrupt(vcpu)) {
if (svm_interrupt_allowed(vcpu)) {
kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
svm_queue_irq(to_svm(vcpu), vcpu->arch.interrupt.nr);
@@ -2312,7 +2355,10 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
svm_intr_inject(vcpu);
- if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
+ /* enable NMI/IRQ window open exits if needed */
+ if (vcpu->arch.nmi_pending)
+ enable_nmi_window(vcpu);
+ else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
enable_irq_window(vcpu);
out:
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 14/16] Move interrupt injection logic to x86.c
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (12 preceding siblings ...)
2009-04-21 14:45 ` [PATCH v2 13/16] Add NMI injection support to SVM Gleb Natapov
@ 2009-04-21 14:45 ` Gleb Natapov
2009-04-21 14:45 ` [PATCH v2 15/16] Fix userspace IRQ chip migration Gleb Natapov
` (2 subsequent siblings)
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:45 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/include/asm/kvm_host.h | 7 +++-
arch/x86/kvm/svm.c | 94 +++++++++++----------------------------
arch/x86/kvm/vmx.c | 79 ++++++++-------------------------
arch/x86/kvm/x86.c | 71 ++++++++++++++++++++++++++++-
4 files changed, 120 insertions(+), 131 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 057a612..f9eb9ac 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -515,10 +515,15 @@ struct kvm_x86_ops {
unsigned char *hypercall_addr);
int (*get_irq)(struct kvm_vcpu *vcpu);
void (*set_irq)(struct kvm_vcpu *vcpu, int vec);
+ void (*set_nmi)(struct kvm_vcpu *vcpu);
void (*queue_exception)(struct kvm_vcpu *vcpu, unsigned nr,
bool has_error_code, u32 error_code);
- void (*inject_pending_irq)(struct kvm_vcpu *vcpu, struct kvm_run *run);
int (*interrupt_allowed)(struct kvm_vcpu *vcpu);
+ int (*nmi_allowed)(struct kvm_vcpu *vcpu);
+ void (*enable_nmi_window)(struct kvm_vcpu *vcpu);
+ void (*enable_irq_window)(struct kvm_vcpu *vcpu);
+ void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr);
+ void (*drop_interrupt_shadow)(struct kvm_vcpu *vcpu);
int (*set_tss_addr)(struct kvm *kvm, unsigned int addr);
int (*get_tdp_level)(void);
int (*get_mt_mask_shift)(void);
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 3452bb4..ca57365 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1862,8 +1862,10 @@ static int cr8_write_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
u8 cr8_prev = kvm_get_cr8(&svm->vcpu);
/* instruction emulation calls kvm_set_cr8() */
emulate_instruction(&svm->vcpu, NULL, 0, 0, 0);
- if (irqchip_in_kernel(svm->vcpu.kvm))
+ if (irqchip_in_kernel(svm->vcpu.kvm)) {
+ svm->vmcb->control.intercept_cr_write &= ~INTERCEPT_CR8_MASK;
return 1;
+ }
if (cr8_prev <= kvm_get_cr8(&svm->vcpu))
return 1;
kvm_run->exit_reason = KVM_EXIT_SET_TPR;
@@ -2227,8 +2229,16 @@ static void pre_svm_run(struct vcpu_svm *svm)
new_asid(svm, svm_data);
}
-static void svm_inject_nmi(struct vcpu_svm *svm)
+static void svm_drop_interrupt_shadow(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_svm *svm = to_svm(vcpu);
+ svm->vmcb->control.int_state &= ~SVM_INTERRUPT_SHADOW_MASK;
+}
+
+static void svm_inject_nmi(struct kvm_vcpu *vcpu)
{
+ struct vcpu_svm *svm = to_svm(vcpu);
+
svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI;
vcpu->arch.hflags |= HF_NMI_MASK;
svm->vmcb->control.intercept |= (1UL << INTERCEPT_IRET);
@@ -2249,8 +2259,10 @@ static inline void svm_inject_irq(struct vcpu_svm *svm, int irq)
((/*control->int_vector >> 4*/ 0xf) << V_INTR_PRIO_SHIFT);
}
-static void svm_queue_irq(struct vcpu_svm *svm, unsigned nr)
+static void svm_queue_irq(struct kvm_vcpu *vcpu, unsigned nr)
{
+ struct vcpu_svm *svm = to_svm(vcpu);
+
svm->vmcb->control.event_inj = nr |
SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_INTR;
}
@@ -2261,28 +2273,18 @@ static void svm_set_irq(struct kvm_vcpu *vcpu, int irq)
nested_svm_intr(svm);
- svm_queue_irq(svm, irq);
+ svm_queue_irq(vcpu, irq);
}
-static void update_cr8_intercept(struct kvm_vcpu *vcpu)
+static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
{
struct vcpu_svm *svm = to_svm(vcpu);
- struct vmcb *vmcb = svm->vmcb;
- int max_irr, tpr;
- if (!irqchip_in_kernel(vcpu->kvm) || vcpu->arch.apic->vapic_addr)
+ if (irr == -1)
return;
- vmcb->control.intercept_cr_write &= ~INTERCEPT_CR8_MASK;
-
- max_irr = kvm_lapic_find_highest_irr(vcpu);
- if (max_irr == -1)
- return;
-
- tpr = kvm_lapic_get_cr8(vcpu) << 4;
-
- if (tpr >= (max_irr & 0xf0))
- vmcb->control.intercept_cr_write |= INTERCEPT_CR8_MASK;
+ if (tpr >= irr)
+ svm->vmcb->control.intercept_cr_write |= INTERCEPT_CR8_MASK;
}
static int svm_nmi_allowed(struct kvm_vcpu *vcpu)
@@ -2316,55 +2318,6 @@ static void enable_nmi_window(struct kvm_vcpu *vcpu)
enable_irq_window(vcpu);
}
-static void svm_intr_inject(struct kvm_vcpu *vcpu)
-{
- /* try to reinject previous events if any */
- if (vcpu->arch.nmi_injected) {
- svm_inject_nmi(to_svm(vcpu));
- return;
- }
-
- if (vcpu->arch.interrupt.pending) {
- svm_queue_irq(to_svm(vcpu), vcpu->arch.interrupt.nr);
- return;
- }
-
- /* try to inject new event if pending */
- if (vcpu->arch.nmi_pending) {
- if (svm_nmi_allowed(vcpu)) {
- vcpu->arch.nmi_pending = false;
- vcpu->arch.nmi_injected = true;
- svm_inject_nmi(vcpu);
- }
- } else if (kvm_cpu_has_interrupt(vcpu)) {
- if (svm_interrupt_allowed(vcpu)) {
- kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
- svm_queue_irq(to_svm(vcpu), vcpu->arch.interrupt.nr);
- }
- }
-}
-
-static void svm_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
-{
- struct vcpu_svm *svm = to_svm(vcpu);
- bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
- kvm_run->request_interrupt_window;
-
- if (nested_svm_intr(svm))
- goto out;
-
- svm_intr_inject(vcpu);
-
- /* enable NMI/IRQ window open exits if needed */
- if (vcpu->arch.nmi_pending)
- enable_nmi_window(vcpu);
- else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
- enable_irq_window(vcpu);
-
-out:
- update_cr8_intercept(vcpu);
-}
-
static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr)
{
return 0;
@@ -2684,9 +2637,14 @@ static struct kvm_x86_ops svm_x86_ops = {
.patch_hypercall = svm_patch_hypercall,
.get_irq = svm_get_irq,
.set_irq = svm_set_irq,
+ .set_nmi = svm_inject_nmi,
.queue_exception = svm_queue_exception,
- .inject_pending_irq = svm_intr_assist,
.interrupt_allowed = svm_interrupt_allowed,
+ .nmi_allowed = svm_nmi_allowed,
+ .enable_nmi_window = enable_nmi_window,
+ .enable_irq_window = enable_irq_window,
+ .update_cr8_intercept = update_cr8_intercept,
+ .drop_interrupt_shadow = svm_drop_interrupt_shadow,
.set_tss_addr = svm_set_tss_addr,
.get_tdp_level = get_npt_level,
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 116eac0..bad2413 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1314,6 +1314,9 @@ static __init int hardware_setup(void)
if (!cpu_has_vmx_flexpriority())
flexpriority_enabled = 0;
+ if (!cpu_has_vmx_tpr_shadow())
+ kvm_x86_ops->update_cr8_intercept = NULL;
+
return alloc_kvm_area();
}
@@ -2404,6 +2407,12 @@ out:
return ret;
}
+void vmx_drop_interrupt_shadow(struct kvm_vcpu *vcpu)
+{
+ vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
+ GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS);
+}
+
static void enable_irq_window(struct kvm_vcpu *vcpu)
{
u32 cpu_based_vm_exec_control;
@@ -3214,21 +3223,14 @@ static int vmx_handle_exit(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
return 0;
}
-static void update_tpr_threshold(struct kvm_vcpu *vcpu)
+static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
{
- int max_irr, tpr;
-
- if (!vm_need_tpr_shadow(vcpu->kvm))
- return;
-
- if (!kvm_lapic_enabled(vcpu) ||
- ((max_irr = kvm_lapic_find_highest_irr(vcpu)) == -1)) {
+ if (irr == -1 || tpr < irr) {
vmcs_write32(TPR_THRESHOLD, 0);
return;
}
- tpr = (kvm_lapic_get_cr8(vcpu) & 0x0f) << 4;
- vmcs_write32(TPR_THRESHOLD, (max_irr > tpr) ? tpr >> 4 : max_irr >> 4);
+ vmcs_write32(TPR_THRESHOLD, irr);
}
static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
@@ -3300,55 +3302,6 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx)
}
}
-static void vmx_intr_inject(struct kvm_vcpu *vcpu)
-{
- /* try to reinject previous events if any */
- if (vcpu->arch.nmi_injected) {
- vmx_inject_nmi(vcpu);
- return;
- }
-
- if (vcpu->arch.interrupt.pending) {
- vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
- return;
- }
-
- /* try to inject new event if pending */
- if (vcpu->arch.nmi_pending) {
- if (vmx_nmi_allowed(vcpu)) {
- vcpu->arch.nmi_pending = false;
- vcpu->arch.nmi_injected = true;
- vmx_inject_nmi(vcpu);
- }
- } else if (kvm_cpu_has_interrupt(vcpu)) {
- if (vmx_interrupt_allowed(vcpu)) {
- kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
- vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
- }
- }
-}
-
-static void vmx_intr_assist(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
-{
- bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
- kvm_run->request_interrupt_window;
-
- update_tpr_threshold(vcpu);
-
- if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
- vmcs_clear_bits(GUEST_INTERRUPTIBILITY_INFO,
- GUEST_INTR_STATE_STI |
- GUEST_INTR_STATE_MOV_SS);
-
- vmx_intr_inject(vcpu);
-
- /* enable NMI/IRQ window open exits if needed */
- if (vcpu->arch.nmi_pending)
- enable_nmi_window(vcpu);
- else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
- enable_irq_window(vcpu);
-}
-
/*
* Failure to inject an interrupt should give us the information
* in IDT_VECTORING_INFO_FIELD. However, if the failure occurs
@@ -3683,9 +3636,15 @@ static struct kvm_x86_ops vmx_x86_ops = {
.patch_hypercall = vmx_patch_hypercall,
.get_irq = vmx_get_irq,
.set_irq = vmx_inject_irq,
+ .set_nmi = vmx_inject_nmi,
.queue_exception = vmx_queue_exception,
- .inject_pending_irq = vmx_intr_assist,
.interrupt_allowed = vmx_interrupt_allowed,
+ .nmi_allowed = vmx_nmi_allowed,
+ .enable_nmi_window = enable_nmi_window,
+ .enable_irq_window = enable_irq_window,
+ .update_cr8_intercept = update_cr8_intercept,
+ .drop_interrupt_shadow = vmx_drop_interrupt_shadow,
+
.set_tss_addr = vmx_set_tss_addr,
.get_tdp_level = get_ept_level,
.get_mt_mask_shift = vmx_get_mt_mask_shift,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d94a152..cae1985 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3104,6 +3104,68 @@ static void vapic_exit(struct kvm_vcpu *vcpu)
up_read(&vcpu->kvm->slots_lock);
}
+static void update_cr8_intercept(struct kvm_vcpu *vcpu)
+{
+ int max_irr, tpr;
+
+ if (!kvm_x86_ops->update_cr8_intercept)
+ return;
+
+ max_irr = kvm_lapic_find_highest_irr(vcpu);
+
+ if (max_irr != -1)
+ max_irr >>= 4;
+
+ tpr = kvm_lapic_get_cr8(vcpu);
+
+ kvm_x86_ops->update_cr8_intercept(vcpu, tpr, max_irr);
+}
+
+static void inject_irq(struct kvm_vcpu *vcpu)
+{
+ /* try to reinject previous events if any */
+ if (vcpu->arch.nmi_injected) {
+ kvm_x86_ops->set_nmi(vcpu);
+ return;
+ }
+
+ if (vcpu->arch.interrupt.pending) {
+ kvm_x86_ops->set_irq(vcpu, vcpu->arch.interrupt.nr);
+ return;
+ }
+
+ /* try to inject new event if pending */
+ if (vcpu->arch.nmi_pending) {
+ if (kvm_x86_ops->nmi_allowed(vcpu)) {
+ vcpu->arch.nmi_pending = false;
+ vcpu->arch.nmi_injected = true;
+ kvm_x86_ops->set_nmi(vcpu);
+ }
+ } else if (kvm_cpu_has_interrupt(vcpu)) {
+ if (kvm_x86_ops->interrupt_allowed(vcpu)) {
+ kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu));
+ kvm_x86_ops->set_irq(vcpu, vcpu->arch.interrupt.nr);
+ }
+ }
+}
+
+static void inject_pending_irq(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+ bool req_int_win = !irqchip_in_kernel(vcpu->kvm) &&
+ kvm_run->request_interrupt_window;
+
+ if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
+ kvm_x86_ops->drop_interrupt_shadow(vcpu);
+
+ inject_irq(vcpu);
+
+ /* enable NMI/IRQ window open exits if needed */
+ if (vcpu->arch.nmi_pending)
+ kvm_x86_ops->enable_nmi_window(vcpu);
+ else if (kvm_cpu_has_interrupt(vcpu) || req_int_win)
+ kvm_x86_ops->enable_irq_window(vcpu);
+}
+
static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
{
int r;
@@ -3162,9 +3224,14 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
if (vcpu->arch.exception.pending)
__queue_exception(vcpu);
else
- kvm_x86_ops->inject_pending_irq(vcpu, kvm_run);
+ inject_pending_irq(vcpu, kvm_run);
- kvm_lapic_sync_to_vapic(vcpu);
+ if (kvm_lapic_enabled(vcpu)) {
+ if (!vcpu->arch.apic->vapic_addr)
+ update_cr8_intercept(vcpu);
+ else
+ kvm_lapic_sync_to_vapic(vcpu);
+ }
up_read(&vcpu->kvm->slots_lock);
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 15/16] Fix userspace IRQ chip migration.
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (13 preceding siblings ...)
2009-04-21 14:45 ` [PATCH v2 14/16] Move interrupt injection logic to x86.c Gleb Natapov
@ 2009-04-21 14:45 ` Gleb Natapov
2009-04-21 14:45 ` [PATCH v2 16/16] Get rid of get_irq() callback Gleb Natapov
2009-04-27 11:19 ` [PATCH v2 00/16] interrupt injection rework Avi Kivity
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:45 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
Re-put pending IRQ vector into interrupt_bitmap before migration.
Otherwise it will be lost if migration happens in the wrong time.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/kvm/x86.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index cae1985..7bea346 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3556,17 +3556,17 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
sregs->efer = vcpu->arch.shadow_efer;
sregs->apic_base = kvm_get_apic_base(vcpu);
- if (irqchip_in_kernel(vcpu->kvm)) {
+ if (irqchip_in_kernel(vcpu->kvm))
memset(sregs->interrupt_bitmap, 0,
sizeof sregs->interrupt_bitmap);
- pending_vec = kvm_x86_ops->get_irq(vcpu);
- if (pending_vec >= 0)
- set_bit(pending_vec,
- (unsigned long *)sregs->interrupt_bitmap);
- } else
+ else
memcpy(sregs->interrupt_bitmap, vcpu->arch.irq_pending,
sizeof sregs->interrupt_bitmap);
+ pending_vec = kvm_x86_ops->get_irq(vcpu);
+ if (pending_vec >= 0)
+ set_bit(pending_vec, (unsigned long *)sregs->interrupt_bitmap);
+
vcpu_put(vcpu);
return 0;
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* [PATCH v2 16/16] Get rid of get_irq() callback.
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (14 preceding siblings ...)
2009-04-21 14:45 ` [PATCH v2 15/16] Fix userspace IRQ chip migration Gleb Natapov
@ 2009-04-21 14:45 ` Gleb Natapov
2009-04-27 11:19 ` [PATCH v2 00/16] interrupt injection rework Avi Kivity
16 siblings, 0 replies; 26+ messages in thread
From: Gleb Natapov @ 2009-04-21 14:45 UTC (permalink / raw)
To: avi; +Cc: kvm, Gleb Natapov
It just returns pending IRQ vector from the queue for VMX/SVM.
Get IRQ directly from the queue before migration and put it back
after.
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
arch/x86/include/asm/kvm_host.h | 1 -
arch/x86/kvm/svm.c | 8 --------
arch/x86/kvm/vmx.c | 8 --------
arch/x86/kvm/x86.c | 12 +++++-------
4 files changed, 5 insertions(+), 24 deletions(-)
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index f9eb9ac..0fa07e7 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -513,7 +513,6 @@ struct kvm_x86_ops {
void (*skip_emulated_instruction)(struct kvm_vcpu *vcpu);
void (*patch_hypercall)(struct kvm_vcpu *vcpu,
unsigned char *hypercall_addr);
- int (*get_irq)(struct kvm_vcpu *vcpu);
void (*set_irq)(struct kvm_vcpu *vcpu, int vec);
void (*set_nmi)(struct kvm_vcpu *vcpu);
void (*queue_exception)(struct kvm_vcpu *vcpu, unsigned nr,
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index ca57365..1ca877a 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -964,13 +964,6 @@ static int svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
return 0;
}
-static int svm_get_irq(struct kvm_vcpu *vcpu)
-{
- if (!vcpu->arch.interrupt.pending)
- return -1;
- return vcpu->arch.interrupt.nr;
-}
-
static void load_host_msrs(struct kvm_vcpu *vcpu)
{
#ifdef CONFIG_X86_64
@@ -2635,7 +2628,6 @@ static struct kvm_x86_ops svm_x86_ops = {
.handle_exit = handle_exit,
.skip_emulated_instruction = skip_emulated_instruction,
.patch_hypercall = svm_patch_hypercall,
- .get_irq = svm_get_irq,
.set_irq = svm_set_irq,
.set_nmi = svm_inject_nmi,
.queue_exception = svm_queue_exception,
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index bad2413..25be53a 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1045,13 +1045,6 @@ static int set_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
return 0;
}
-static int vmx_get_irq(struct kvm_vcpu *vcpu)
-{
- if (!vcpu->arch.interrupt.pending)
- return -1;
- return vcpu->arch.interrupt.nr;
-}
-
static __init int cpu_has_kvm_support(void)
{
return cpu_has_vmx();
@@ -3634,7 +3627,6 @@ static struct kvm_x86_ops vmx_x86_ops = {
.handle_exit = vmx_handle_exit,
.skip_emulated_instruction = skip_emulated_instruction,
.patch_hypercall = vmx_patch_hypercall,
- .get_irq = vmx_get_irq,
.set_irq = vmx_inject_irq,
.set_nmi = vmx_inject_nmi,
.queue_exception = vmx_queue_exception,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 7bea346..1a99a23 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3526,7 +3526,6 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
struct kvm_sregs *sregs)
{
struct descriptor_table dt;
- int pending_vec;
vcpu_load(vcpu);
@@ -3563,9 +3562,9 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
memcpy(sregs->interrupt_bitmap, vcpu->arch.irq_pending,
sizeof sregs->interrupt_bitmap);
- pending_vec = kvm_x86_ops->get_irq(vcpu);
- if (pending_vec >= 0)
- set_bit(pending_vec, (unsigned long *)sregs->interrupt_bitmap);
+ if (vcpu->arch.interrupt.pending)
+ set_bit(vcpu->arch.interrupt.nr,
+ (unsigned long *)sregs->interrupt_bitmap);
vcpu_put(vcpu);
@@ -4081,9 +4080,8 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
max_bits);
/* Only pending external irq is handled here */
if (pending_vec < max_bits) {
- kvm_x86_ops->set_irq(vcpu, pending_vec);
- pr_debug("Set back pending irq %d\n",
- pending_vec);
+ kvm_queue_interrupt(vcpu, pending_vec);
+ pr_debug("Set back pending irq %d\n", pending_vec);
}
kvm_pic_clear_isr_ack(vcpu->kvm);
}
--
1.5.6.5
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [PATCH v2 00/16] interrupt injection rework
2009-04-21 14:44 [PATCH v2 00/16] interrupt injection rework Gleb Natapov
` (15 preceding siblings ...)
2009-04-21 14:45 ` [PATCH v2 16/16] Get rid of get_irq() callback Gleb Natapov
@ 2009-04-27 11:19 ` Avi Kivity
2009-04-29 9:30 ` Jan Kiszka
16 siblings, 1 reply; 26+ messages in thread
From: Avi Kivity @ 2009-04-27 11:19 UTC (permalink / raw)
To: Gleb Natapov; +Cc: kvm
Gleb Natapov wrote:
> Hi,
>
> This patch series aims to consolidate IRQ injection code for in kernel
> IRQ chip and userspace one. Also to move IRQ injection logic from
> SVM/VMX specific code to x86.c.
>
Applied all, thanks for this excellent patchset.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 26+ messages in thread* Re: [PATCH v2 00/16] interrupt injection rework
2009-04-27 11:19 ` [PATCH v2 00/16] interrupt injection rework Avi Kivity
@ 2009-04-29 9:30 ` Jan Kiszka
2009-04-29 10:22 ` Gleb Natapov
2009-04-29 10:40 ` Avi Kivity
0 siblings, 2 replies; 26+ messages in thread
From: Jan Kiszka @ 2009-04-29 9:30 UTC (permalink / raw)
To: Avi Kivity; +Cc: Gleb Natapov, kvm
Avi Kivity wrote:
> Gleb Natapov wrote:
>> Hi,
>>
>> This patch series aims to consolidate IRQ injection code for in kernel
>> IRQ chip and userspace one. Also to move IRQ injection logic from
>> SVM/VMX specific code to x86.c.
>>
>
> Applied all, thanks for this excellent patchset.
>
Hmm, to which branch? Or did you just forget to also push it...
Gleb, what is your current schedule regarding single-step on NMI iret?
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 00/16] interrupt injection rework
2009-04-29 9:30 ` Jan Kiszka
@ 2009-04-29 10:22 ` Gleb Natapov
2009-04-29 10:33 ` Jan Kiszka
2009-04-29 10:40 ` Avi Kivity
1 sibling, 1 reply; 26+ messages in thread
From: Gleb Natapov @ 2009-04-29 10:22 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Avi Kivity, kvm
On Wed, Apr 29, 2009 at 11:30:46AM +0200, Jan Kiszka wrote:
> Avi Kivity wrote:
> > Gleb Natapov wrote:
> >> Hi,
> >>
> >> This patch series aims to consolidate IRQ injection code for in kernel
> >> IRQ chip and userspace one. Also to move IRQ injection logic from
> >> SVM/VMX specific code to x86.c.
> >>
> >
> > Applied all, thanks for this excellent patchset.
> >
>
> Hmm, to which branch? Or did you just forget to also push it...
>
> Gleb, what is your current schedule regarding single-step on NMI iret?
>
I was going to look at it shortly. BTW there are other cases when single
stepping is required. For instance if exception is injected and there is
NMI pending NMI should be injected immediately after exception handler
is started, but currently it happens only after a next exit.
--
Gleb.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 00/16] interrupt injection rework
2009-04-29 10:22 ` Gleb Natapov
@ 2009-04-29 10:33 ` Jan Kiszka
2009-04-29 10:35 ` Gleb Natapov
0 siblings, 1 reply; 26+ messages in thread
From: Jan Kiszka @ 2009-04-29 10:33 UTC (permalink / raw)
To: Gleb Natapov; +Cc: Avi Kivity, kvm
Gleb Natapov wrote:
> On Wed, Apr 29, 2009 at 11:30:46AM +0200, Jan Kiszka wrote:
>> Avi Kivity wrote:
>>> Gleb Natapov wrote:
>>>> Hi,
>>>>
>>>> This patch series aims to consolidate IRQ injection code for in kernel
>>>> IRQ chip and userspace one. Also to move IRQ injection logic from
>>>> SVM/VMX specific code to x86.c.
>>>>
>>> Applied all, thanks for this excellent patchset.
>>>
>> Hmm, to which branch? Or did you just forget to also push it...
>>
>> Gleb, what is your current schedule regarding single-step on NMI iret?
>>
> I was going to look at it shortly. BTW there are other cases when single
> stepping is required. For instance if exception is injected and there is
> NMI pending NMI should be injected immediately after exception handler
> is started, but currently it happens only after a next exit.
So we basically need an NMI windows notification that not only triggers
on iret completion. Sounds OK.
Then I would say: once there is anything to test, even if it's early
stuff, throw it over.
Thanks,
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 00/16] interrupt injection rework
2009-04-29 10:33 ` Jan Kiszka
@ 2009-04-29 10:35 ` Gleb Natapov
2009-04-29 10:46 ` Jan Kiszka
0 siblings, 1 reply; 26+ messages in thread
From: Gleb Natapov @ 2009-04-29 10:35 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Avi Kivity, kvm
On Wed, Apr 29, 2009 at 12:33:09PM +0200, Jan Kiszka wrote:
> Gleb Natapov wrote:
> > On Wed, Apr 29, 2009 at 11:30:46AM +0200, Jan Kiszka wrote:
> >> Avi Kivity wrote:
> >>> Gleb Natapov wrote:
> >>>> Hi,
> >>>>
> >>>> This patch series aims to consolidate IRQ injection code for in kernel
> >>>> IRQ chip and userspace one. Also to move IRQ injection logic from
> >>>> SVM/VMX specific code to x86.c.
> >>>>
> >>> Applied all, thanks for this excellent patchset.
> >>>
> >> Hmm, to which branch? Or did you just forget to also push it...
> >>
> >> Gleb, what is your current schedule regarding single-step on NMI iret?
> >>
> > I was going to look at it shortly. BTW there are other cases when single
> > stepping is required. For instance if exception is injected and there is
> > NMI pending NMI should be injected immediately after exception handler
> > is started, but currently it happens only after a next exit.
>
> So we basically need an NMI windows notification that not only triggers
> on iret completion. Sounds OK.
>
But we don't have one on SVM :(
> Then I would say: once there is anything to test, even if it's early
> stuff, throw it over.
>
OK.
--
Gleb.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 00/16] interrupt injection rework
2009-04-29 10:35 ` Gleb Natapov
@ 2009-04-29 10:46 ` Jan Kiszka
0 siblings, 0 replies; 26+ messages in thread
From: Jan Kiszka @ 2009-04-29 10:46 UTC (permalink / raw)
To: Gleb Natapov; +Cc: Avi Kivity, kvm
Gleb Natapov wrote:
> On Wed, Apr 29, 2009 at 12:33:09PM +0200, Jan Kiszka wrote:
>> Gleb Natapov wrote:
>>> On Wed, Apr 29, 2009 at 11:30:46AM +0200, Jan Kiszka wrote:
>>>> Avi Kivity wrote:
>>>>> Gleb Natapov wrote:
>>>>>> Hi,
>>>>>>
>>>>>> This patch series aims to consolidate IRQ injection code for in kernel
>>>>>> IRQ chip and userspace one. Also to move IRQ injection logic from
>>>>>> SVM/VMX specific code to x86.c.
>>>>>>
>>>>> Applied all, thanks for this excellent patchset.
>>>>>
>>>> Hmm, to which branch? Or did you just forget to also push it...
>>>>
>>>> Gleb, what is your current schedule regarding single-step on NMI iret?
>>>>
>>> I was going to look at it shortly. BTW there are other cases when single
>>> stepping is required. For instance if exception is injected and there is
>>> NMI pending NMI should be injected immediately after exception handler
>>> is started, but currently it happens only after a next exit.
>> So we basically need an NMI windows notification that not only triggers
>> on iret completion. Sounds OK.
>>
> But we don't have one on SVM :(
Yeah - and I was so optimistic that AMD managed to deliver an easily
implementable interface right from the beginning. Intel required two
steps, and the result has still some traps. Now it turns out also AMD
complicated NMI virtualization, IMHO needlessly. Well, but as we all
constantly seek for challenges... ;)
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 00/16] interrupt injection rework
2009-04-29 9:30 ` Jan Kiszka
2009-04-29 10:22 ` Gleb Natapov
@ 2009-04-29 10:40 ` Avi Kivity
2009-04-29 10:47 ` Jan Kiszka
1 sibling, 1 reply; 26+ messages in thread
From: Avi Kivity @ 2009-04-29 10:40 UTC (permalink / raw)
To: Jan Kiszka; +Cc: Gleb Natapov, kvm
Jan Kiszka wrote:
> Hmm, to which branch? Or did you just forget to also push it...
>
>
In general, if I apply and don't push a couple of hours later, it means
there are regressions.
I think these regressions are from the recent qemu merge, not the
interrupt rework.
--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [PATCH v2 00/16] interrupt injection rework
2009-04-29 10:40 ` Avi Kivity
@ 2009-04-29 10:47 ` Jan Kiszka
0 siblings, 0 replies; 26+ messages in thread
From: Jan Kiszka @ 2009-04-29 10:47 UTC (permalink / raw)
To: Avi Kivity; +Cc: Gleb Natapov, kvm
Avi Kivity wrote:
> Jan Kiszka wrote:
>> Hmm, to which branch? Or did you just forget to also push it...
>>
>>
>
> In general, if I apply and don't push a couple of hours later, it means
> there are regressions.
>
> I think these regressions are from the recent qemu merge, not the
> interrupt rework.
I guess so as well, specifically as those changes are kernel-only,
transparent to user space. So excluding them as source for regression
via older kvm-userspace should also be possible.
Jan
--
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 26+ messages in thread