[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 22/23] apic: Defer interrupt updates to VCPU thread
From: |
Michael Roth |
Subject: |
[Qemu-devel] [PATCH 22/23] apic: Defer interrupt updates to VCPU thread |
Date: |
Tue, 21 Aug 2012 12:05:56 -0500 |
From: Jan Kiszka <address@hidden>
KVM performs TPR raising asynchronously to QEMU, specifically outside
QEMU's global lock. When an interrupt is injected into the APIC and TPR
is checked to decide if this can be delivered, a stale TPR value may be
used, causing spurious interrupts in the end.
Fix this by deferring apic_update_irq to the context of the target VCPU.
We introduce a new interrupt flag for this, CPU_INTERRUPT_POLL. When it
is set, the VCPU calls apic_poll_irq before checking for further pending
interrupts. To avoid special-casing KVM, we also implement this logic
for TCG mode.
Signed-off-by: Jan Kiszka <address@hidden>
Signed-off-by: Avi Kivity <address@hidden>
(cherry picked from commit 5d62c43a17edaa7f6a88821c9086e6c8e0e5327d)
Signed-off-by: Michael Roth <address@hidden>
---
cpu-exec.c | 6 ++++++
hw/apic.c | 5 ++++-
hw/apic.h | 1 +
hw/apic_internal.h | 1 -
target-i386/cpu.h | 4 +++-
target-i386/kvm.c | 4 ++++
6 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/cpu-exec.c b/cpu-exec.c
index 0344cd5..6db32cd 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -285,6 +285,12 @@ int cpu_exec(CPUArchState *env)
}
#endif
#if defined(TARGET_I386)
+#if !defined(CONFIG_USER_ONLY)
+ if (interrupt_request & CPU_INTERRUPT_POLL) {
+ env->interrupt_request &= ~CPU_INTERRUPT_POLL;
+ apic_poll_irq(env->apic_state);
+ }
+#endif
if (interrupt_request & CPU_INTERRUPT_INIT) {
svm_check_intercept(env, SVM_EXIT_INIT);
do_cpu_init(env);
diff --git a/hw/apic.c b/hw/apic.c
index e96402d..b2c6373 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -16,6 +16,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>
*/
+#include "qemu-thread.h"
#include "apic_internal.h"
#include "apic.h"
#include "ioapic.h"
@@ -369,7 +370,9 @@ static void apic_update_irq(APICCommonState *s)
if (!(s->spurious_vec & APIC_SV_ENABLE)) {
return;
}
- if (apic_irq_pending(s) > 0) {
+ if (!qemu_cpu_is_self(s->cpu_env)) {
+ cpu_interrupt(s->cpu_env, CPU_INTERRUPT_POLL);
+ } else if (apic_irq_pending(s) > 0) {
cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
}
}
diff --git a/hw/apic.h b/hw/apic.h
index 62179ce..a89542b 100644
--- a/hw/apic.h
+++ b/hw/apic.h
@@ -20,6 +20,7 @@ void apic_init_reset(DeviceState *s);
void apic_sipi(DeviceState *s);
void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
TPRAccess access);
+void apic_poll_irq(DeviceState *d);
/* pc.c */
int cpu_is_bsp(CPUX86State *env);
diff --git a/hw/apic_internal.h b/hw/apic_internal.h
index 60a6a8b..4d8ff49 100644
--- a/hw/apic_internal.h
+++ b/hw/apic_internal.h
@@ -141,7 +141,6 @@ void apic_report_irq_delivered(int delivered);
bool apic_next_timer(APICCommonState *s, int64_t current_time);
void apic_enable_tpr_access_reporting(DeviceState *d, bool enable);
void apic_enable_vapic(DeviceState *d, target_phys_addr_t paddr);
-void apic_poll_irq(DeviceState *d);
void vapic_report_tpr_access(DeviceState *dev, void *cpu, target_ulong ip,
TPRAccess access);
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 2460f63..8ff3f30 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -477,6 +477,7 @@
for syscall instruction */
/* i386-specific interrupt pending bits. */
+#define CPU_INTERRUPT_POLL CPU_INTERRUPT_TGT_EXT_1
#define CPU_INTERRUPT_SMI CPU_INTERRUPT_TGT_EXT_2
#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
#define CPU_INTERRUPT_MCE CPU_INTERRUPT_TGT_EXT_4
@@ -1029,7 +1030,8 @@ static inline void cpu_clone_regs(CPUX86State *env,
target_ulong newsp)
static inline bool cpu_has_work(CPUX86State *env)
{
- return ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
+ return ((env->interrupt_request & (CPU_INTERRUPT_HARD |
+ CPU_INTERRUPT_POLL)) &&
(env->eflags & IF_MASK)) ||
(env->interrupt_request & (CPU_INTERRUPT_NMI |
CPU_INTERRUPT_INIT |
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index e74a9e4..d8bbe4f 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1725,6 +1725,10 @@ int kvm_arch_process_async_events(CPUX86State *env)
return 0;
}
+ if (env->interrupt_request & CPU_INTERRUPT_POLL) {
+ env->interrupt_request &= ~CPU_INTERRUPT_POLL;
+ apic_poll_irq(env->apic_state);
+ }
if (((env->interrupt_request & CPU_INTERRUPT_HARD) &&
(env->eflags & IF_MASK)) ||
(env->interrupt_request & CPU_INTERRUPT_NMI)) {
--
1.7.9.5
- [Qemu-devel] [PATCH 11/23] usb: restore USBDevice->attached on vmload, (continued)
- [Qemu-devel] [PATCH 11/23] usb: restore USBDevice->attached on vmload, Michael Roth, 2012/08/21
- [Qemu-devel] [PATCH 10/23] uhci: fix uhci_async_cancel_all, Michael Roth, 2012/08/21
- [Qemu-devel] [PATCH 14/23] qlist: add qlist_size(), Michael Roth, 2012/08/21
- [Qemu-devel] [PATCH 09/23] ehci: don't flush cache on doorbell rings., Michael Roth, 2012/08/21
- [Qemu-devel] [PATCH 12/23] usb-redir: Correctly handle the usb_redir_babble usbredir status, Michael Roth, 2012/08/21
- [Qemu-devel] [PATCH 16/23] check-qjson: add test for large JSON objects, Michael Roth, 2012/08/21
- [Qemu-devel] [PATCH 17/23] slirp: Enforce host-side user of smb share, Michael Roth, 2012/08/21
- [Qemu-devel] [PATCH 15/23] json-parser: don't replicate tokens at each level of recursion, Michael Roth, 2012/08/21
- [Qemu-devel] [PATCH 19/23] slirp: Improve error reporting of inaccessible smb directories, Michael Roth, 2012/08/21
- [Qemu-devel] [PATCH 23/23] update VERSION for 1.1.2, Michael Roth, 2012/08/21
- [Qemu-devel] [PATCH 22/23] apic: Defer interrupt updates to VCPU thread,
Michael Roth <=
- [Qemu-devel] [PATCH 20/23] apic: Resolve potential endless loop around apic_update_irq, Michael Roth, 2012/08/21
- [Qemu-devel] [PATCH 18/23] slirp: Ensure smbd and shared directory exist when enable smb, Michael Roth, 2012/08/21
- [Qemu-devel] [PATCH 21/23] apic: Reevaluate pending interrupts on LVT_LINT0 changes, Michael Roth, 2012/08/21