aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2012-07-25 13:41:39 +0100
committerPeter Maydell <peter.maydell@linaro.org>2012-07-25 13:41:39 +0100
commit461825c0686e72155f80ce0618130742908522d1 (patch)
treed998cc90bad01340aa7f342a185b8c161cd28ca3
parentb0b0d174ec52402fdcb40599e4a6f5b0915cc5c8 (diff)
kvm: Decouple 'interrupt injection is async' from 'kernel irqchip'
On x86 interrupt injection is asynchronous (and therefore VCPU idle management is done in the kernel) if and only if there is an in-kernel irqchip. On other architectures this isn't necessarily true (they may always do asynchronous injection), so define a new kvm_async_interrupt_injection() function instead of misusing kvm_irqchip_in_kernel(). Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--cpus.c3
-rw-r--r--kvm-all.c7
-rw-r--r--kvm-stub.c1
-rw-r--r--kvm.h11
4 files changed, 20 insertions, 2 deletions
diff --git a/cpus.c b/cpus.c
index 756e6245fd..584b298084 100644
--- a/cpus.c
+++ b/cpus.c
@@ -69,7 +69,8 @@ static bool cpu_thread_is_idle(CPUArchState *env)
if (env->stopped || !runstate_is_running()) {
return true;
}
- if (!env->halted || qemu_cpu_has_work(env) || kvm_irqchip_in_kernel()) {
+ if (!env->halted || qemu_cpu_has_work(env) ||
+ kvm_async_interrupt_injection()) {
return false;
}
return true;
diff --git a/kvm-all.c b/kvm-all.c
index 2148b20bdb..3354c6f0b2 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -100,6 +100,7 @@ struct KVMState
KVMState *kvm_state;
bool kvm_kernel_irqchip;
+bool kvm_async_interrupt_injection;
static const KVMCapabilityInfo kvm_required_capabilites[] = {
KVM_CAP_INFO(USER_MEMORY),
@@ -857,7 +858,7 @@ int kvm_irqchip_set_irq(KVMState *s, int irq, int level)
struct kvm_irq_level event;
int ret;
- assert(kvm_irqchip_in_kernel());
+ assert(kvm_async_interrupt_injection());
event.level = level;
event.irq = irq;
@@ -1201,6 +1202,10 @@ static int kvm_irqchip_create(KVMState *s)
s->irqchip_inject_ioctl = KVM_IRQ_LINE_STATUS;
}
kvm_kernel_irqchip = true;
+ /* If we have an in-kernel IRQ chip then we must have asynchronous
+ * interrupt injection (though the reverse is not necessarily true)
+ */
+ kvm_async_interrupt_injection = true;
kvm_init_irq_routing(s);
diff --git a/kvm-stub.c b/kvm-stub.c
index d23b11c020..b4023d181f 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -19,6 +19,7 @@
KVMState *kvm_state;
bool kvm_kernel_irqchip;
+bool kvm_async_interrupt_injection;
int kvm_init_vcpu(CPUArchState *env)
{
diff --git a/kvm.h b/kvm.h
index a47acefad0..01c636db6c 100644
--- a/kvm.h
+++ b/kvm.h
@@ -24,13 +24,24 @@
extern int kvm_allowed;
extern bool kvm_kernel_irqchip;
+extern bool kvm_async_interrupt_injection;
#if defined CONFIG_KVM || !defined NEED_CPU_H
#define kvm_enabled() (kvm_allowed)
#define kvm_irqchip_in_kernel() (kvm_kernel_irqchip)
+/**
+ * kvm_async_interrupt_injection:
+ *
+ * Returns: true if we can inject interrupts into a KVM CPU
+ * asynchronously (ie by ioctl from any thread at any time)
+ * rather than having to do interrupt delivery synchronously
+ * (where the vcpu must be stopped at a suitable point first).
+ */
+#define kvm_async_interrupt_injection() (kvm_async_interrupt_injection)
#else
#define kvm_enabled() (0)
#define kvm_irqchip_in_kernel() (false)
+#define kvm_async_interrupt_injection() (false)
#endif
struct kvm_run;