Skip to contentSkip to conversation

Patch queue, part VI (interrupt disentangling)

PATCH In review Jan Kiszka 2 participants 5 messages Mar 18, 2011 – Mar 29, 2011 KVM

lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

cover Patch queue, part VI (interrupt disentangling)

Repost of the remaining three patches from part V. No functional changes, I just updated the commit log for reflect their complete rationale.

CC Riku Voipio <[email protected]>

Jan Kiszka (3):
Break up user and system cpu_interrupt implementations Redirect cpu_interrupt to callback handler
kvm: Install specialized interrupt handler

 cpu-all.h |   14 +++++++++++++-
 exec.c    |   18 +++++++++++++-----
 kvm-all.c |   11 +++++++++++
 3 files changed, 37 insertions(+), 6 deletions(-)
author
#1 lore raw

PATCH 1/3 Break up user and system cpu_interrupt implementations

From: Jan Kiszka <[email protected]>

Both have only two lines in common, and we will convert the system service into a callback which is of no use for user mode operation.

---
 exec.c |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)
exec.c +10 -4
index 964ce31..4721f04 100644
@@ -1630,6 +1630,7 @@ static void cpu_unlink_tb(CPUState *env)
     spin_unlock(&interrupt_lock);
 }
 
+#ifndef CONFIG_USER_ONLY
 /* mask must never be zero, except for A20 change call */
 void cpu_interrupt(CPUState *env, int mask)
 {
@@ -1638,7 +1639,6 @@ void cpu_interrupt(CPUState *env, int mask)
     old_mask = env->interrupt_request;
     env->interrupt_request |= mask;
 
-#ifndef CONFIG_USER_ONLY
     /*
      * If called from iothread context, wake the target cpu in
      * case its halted.
@@ -1647,21 +1647,27 @@ void cpu_interrupt(CPUState *env, int mask)
         qemu_cpu_kick(env);
         return;
     }
-#endif
 
     if (use_icount) {
         env->icount_decr.u16.high = 0xffff;
-#ifndef CONFIG_USER_ONLY
         if (!can_do_io(env)
             && (mask & ~old_mask) != 0) {
             cpu_abort(env, "Raised interrupt while not in I/O function");
         }
-#endif
     } else {
         cpu_unlink_tb(env);
     }
 }
 
+#else /* CONFIG_USER_ONLY */
+
+void cpu_interrupt(CPUState *env, int mask)
+{
+    env->interrupt_request |= mask;
+    cpu_unlink_tb(env);
+}
+#endif /* CONFIG_USER_ONLY */
+
 void cpu_reset_interrupt(CPUState *env, int mask)
 {
     env->interrupt_request &= ~mask;
Signature · 1 line
1.7.1
author
#2 lore raw

PATCH 2/3 Redirect cpu_interrupt to callback handler

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

This allows to override the interrupt handling of QEMU in system mode. KVM will make use of it to set a specialized handler.

---
 cpu-all.h |   14 +++++++++++++-
 exec.c    |    4 +++-
 2 files changed, 16 insertions(+), 2 deletions(-)
cpu-all.h +13 -1
index 4f4631d..5835cfa 100644
@@ -790,7 +790,19 @@ extern CPUState *cpu_single_env;
 #define CPU_INTERRUPT_SIPI   0x800 /* SIPI pending. */
 #define CPU_INTERRUPT_MCE    0x1000 /* (x86 only) MCE pending. */
 
-void cpu_interrupt(CPUState *s, int mask);
+#ifndef CONFIG_USER_ONLY
+typedef void (*CPUInterruptHandler)(CPUState *, int);
+
+extern CPUInterruptHandler cpu_interrupt_handler;
+
+static inline void cpu_interrupt(CPUState *s, int mask)
+{
+    cpu_interrupt_handler(s, mask);
+}
+#else /* USER_ONLY */
+void cpu_interrupt(CPUState *env, int mask);
+#endif /* USER_ONLY */
+
 void cpu_reset_interrupt(CPUState *env, int mask);
 
 void cpu_exit(CPUState *s);
exec.c +3 -1
index 4721f04..0c80f84 100644
@@ -1632,7 +1632,7 @@ static void cpu_unlink_tb(CPUState *env)
 
 #ifndef CONFIG_USER_ONLY
 /* mask must never be zero, except for A20 change call */
-void cpu_interrupt(CPUState *env, int mask)
+static void tcg_handle_interrupt(CPUState *env, int mask)
 {
     int old_mask;
 
@@ -1659,6 +1659,8 @@ void cpu_interrupt(CPUState *env, int mask)
     }
 }
 
+CPUInterruptHandler cpu_interrupt_handler = tcg_handle_interrupt;
+
 #else /* CONFIG_USER_ONLY */
 
 void cpu_interrupt(CPUState *env, int mask)
Signature · 1 line
1.7.1
#3 lore raw

Re: [PATCH 2/3] Redirect cpu_interrupt to callback handler

Quoted 60 lines · Jan Kiszka

From: Jan Kiszka <[email protected]>

This allows to override the interrupt handling of QEMU in system mode. KVM will make use of it to set a specialized handler.

---
 cpu-all.h |   14 +++++++++++++-
 exec.c    |    4 +++-
 2 files changed, 16 insertions(+), 2 deletions(-)
cpu-all.h +13 -1
index 4f4631d..5835cfa 100644
@@ -790,7 +790,19 @@ extern CPUState *cpu_single_env;
 #define CPU_INTERRUPT_SIPI   0x800 /* SIPI pending. */
 #define CPU_INTERRUPT_MCE    0x1000 /* (x86 only) MCE pending. */
 
-void cpu_interrupt(CPUState *s, int mask);
+#ifndef CONFIG_USER_ONLY
+typedef void (*CPUInterruptHandler)(CPUState *, int);
+
+extern CPUInterruptHandler cpu_interrupt_handler;
+
+static inline void cpu_interrupt(CPUState *s, int mask)
+{
+    cpu_interrupt_handler(s, mask);
+}
+#else /* USER_ONLY */
+void cpu_interrupt(CPUState *env, int mask);
+#endif /* USER_ONLY */
+
 void cpu_reset_interrupt(CPUState *env, int mask);
 
 void cpu_exit(CPUState *s);
exec.c +3 -1
index 4721f04..0c80f84 100644
@@ -1632,7 +1632,7 @@ static void cpu_unlink_tb(CPUState *env)
 
 #ifndef CONFIG_USER_ONLY
 /* mask must never be zero, except for A20 change call */
-void cpu_interrupt(CPUState *env, int mask)
+static void tcg_handle_interrupt(CPUState *env, int mask)
 {
     int old_mask;
 
@@ -1659,6 +1659,8 @@ void cpu_interrupt(CPUState *env, int mask)
     }
 }
 
+CPUInterruptHandler cpu_interrupt_handler = tcg_handle_interrupt;
+
 #else /* CONFIG_USER_ONLY */
 
 void cpu_interrupt(CPUState *env, int mask)
Signature · 1 line
1.7.1

Perhaps a function would be a better interface, but can be changed later.

author
#4 lore raw

PATCH 3/3 kvm: Install specialized interrupt handler

In reply to Jan Kiszka

From: Jan Kiszka <[email protected]>

KVM only requires to set the raised IRQ in CPUState and to kick the receiving vcpu if it is remote. Installing a specialized handler allows potential future changes to the TCG code path without risking KVM side effects.

---
 kvm-all.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)
kvm-all.c +11 -0
index 1d7e8ea..fd1fbfe 100644
@@ -651,6 +651,15 @@ static CPUPhysMemoryClient kvm_cpu_phys_memory_client = {
     .log_stop = kvm_log_stop,
 };
 
+static void kvm_handle_interrupt(CPUState *env, int mask)
+{
+    env->interrupt_request |= mask;
+
+    if (!qemu_cpu_is_self(env)) {
+        qemu_cpu_kick(env);
+    }
+}
+
 int kvm_init(void)
 {
     static const char upgrade_note[] =
@@ -759,6 +768,8 @@ int kvm_init(void)
 
     s->many_ioeventfds = kvm_check_many_ioeventfds();
 
+    cpu_interrupt_handler = kvm_handle_interrupt;
+
     return 0;
 
 err:
Signature · 1 line
1.7.1