Patch queue, part VI (interrupt disentangling)
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.
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(-)
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
@@ -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
PATCH 2/3 Redirect cpu_interrupt to callback handler
In reply to Jan KiszkaFrom: 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
@@ -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
@@ -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
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.
Signed-off-by Jan Kiszka <[email protected]>--- cpu-all.h | 14 +++++++++++++- exec.c | 4 +++- 2 files changed, 16 insertions(+), 2 deletions(-)cpu-all.h +13
-1@@ -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@@ -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.
PATCH 3/3 kvm: Install specialized interrupt handler
In reply to Jan KiszkaFrom: 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
@@ -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