Skip to contentSkip to conversation

QEMU/KVM: dedicated IO thread

RFC In review Marcelo Tosatti 3 participants 6 messages Mar 25, 2008 – Mar 26, 2008 KVM

lore
Share & tools
lore
#0 lore raw

RFC 1/1 QEMU/KVM: dedicated IO thread

Avi was concerned that this would cause problems with migration. I haven't specifically tested it yet, but it seems there will be no problems introduced by this change: the IO thread will stop all vcpu's in the same way the vcpu0 thread did before.

QEMU/KVM: separate thread for IO handling

Move IO processing from vcpu0 to a dedicated thread.

This removes load on vcpu0 by allowing better cache locality and also improves latency.

We can now block signal handling for IO events, so sigtimedwait won't race with handlers:

- Currently the SIGALRM handler fails to set CPU_INTERRUPT_EXIT because the "next_cpu" variable is not initialized in the KVM path, meaning that processing of timer expiration might be delayed until the next vcpu0 exit.

- Processing of IO events will not be unnecessarily interrupted.

libkvm/libkvm.c +0 -3
Index: kvm-userspace.io/libkvm/libkvm.c
===================================================================
@@ -388,9 +388,6 @@ int kvm_create(kvm_context_t kvm, unsign
 	if (r < 0)
 	        return r;
 	kvm_create_irqchip(kvm);
-	r = kvm_create_vcpu(kvm, 0);
-	if (r < 0)
-		return r;
 
 	return 0;
 }
qemu/qemu-kvm.c +77 -48

253 lines not on this page · raw message

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

#1 lore raw
Quoted 5 lines · Marcelo Tosatti

Avi was concerned that this would cause problems with migration. I haven't specifically tested it yet, but it seems there will be no problems introduced by this change: the IO thread will stop all vcpu's in the same way the vcpu0 thread did before.

I believe this is broken for smp_cpus > 1, and will with this change will be broken even for non smp. The pause/resume logic is rotten.

Quoted 7 lines

QEMU/KVM: separate thread for IO handling

Move IO processing from vcpu0 to a dedicated thread.

This removes load on vcpu0 by allowing better cache locality and also improves latency.

Quoted 7 lines

We can now block signal handling for IO events, so sigtimedwait won't race with handlers:

- Currently the SIGALRM handler fails to set CPU_INTERRUPT_EXIT because the "next_cpu" variable is not initialized in the KVM path, meaning that processing of timer expiration might be delayed until the next vcpu0 exit.

I think we call main_loop_wait() is called unconditionally after every signal.

Quoted 9 lines

- Processing of IO events will not be unnecessarily interrupted.

Index: kvm-userspace.io/libkvm/libkvm.c
===================================================================

libkvm/libkvm.c int kvm_create(kvm_context_t kvm, unsign · line 393

Quoted 9 lines
libkvm/libkvm.c +0 -3
@@ -388,9 +388,6 @@ int kvm_create(kvm_context_t kvm, unsign
 	if (r < 0)
 	        return r;
 	kvm_create_irqchip(kvm);
-	r = kvm_create_vcpu(kvm, 0);
-	if (r < 0)
-		return r;
 
 	return 0;
 }

Please put this and the corresponding qemu change in a separate patch.

[...lots more...]

Looks good.

Signature · 7 lines
error compiling committee.c: too many arguments to function


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
#2 lore raw
Quoted 9 lines · Avi Kivity
Quoted 5 lines · Marcelo Tosatti

Avi was concerned that this would cause problems with migration. I haven't specifically tested it yet, but it seems there will be no problems introduced by this change: the IO thread will stop all vcpu's in the same way the vcpu0 thread did before.

I believe this is broken for smp_cpus > 1, and will with this change will be broken even for non smp. The pause/resume logic is rotten.

Ok, I'll look into it in more detail.

Quoted 10 lines
Quoted 10 lines

QEMU/KVM: separate thread for IO handling

Move IO processing from vcpu0 to a dedicated thread.

This removes load on vcpu0 by allowing better cache locality and also improves latency.

We can now block signal handling for IO events, so sigtimedwait won't race with handlers:

Quoted 7 lines
Quoted 4 lines

- Currently the SIGALRM handler fails to set CPU_INTERRUPT_EXIT because the "next_cpu" variable is not initialized in the KVM path, meaning that processing of timer expiration might be delayed until the next vcpu0 exit.

I think we call main_loop_wait() is called unconditionally after every signal.

We exit the kvm_run() loop if CPU_INTERRUPT_EXIT is detected by pre_kvm_run().

But the SIGALRM handler won't set it:

static void host_alarm_handler(int host_signum)
{
...

        CPUState *env = next_cpu;

        alarm_timer->flags |= ALARM_FLAG_EXPIRED;

        if (env) {
            /* stop the currently executing cpu because a timer occured */
            cpu_interrupt(env, CPU_INTERRUPT_EXIT);
#ifdef USE_KQEMU
            if (env->kqemu_enabled) {
                kqemu_cpu_interrupt(env);
            }

#endif

Because the KVM path does not initialize "next_cpu":

static int main_loop(void)

{
    int ret, timeout;
#ifdef CONFIG_PROFILER
    int64_t ti;
#endif
    CPUState *env;


    if (kvm_enabled()) {
        kvm_main_loop();
        cpu_disable_ticks();
        return 0;
    }

    cur_cpu = first_cpu;
    next_cpu = cur_cpu->next_cpu ?: first_cpu;
Quoted 22 lines
Quoted 10 lines

- Processing of IO events will not be unnecessarily interrupted.

Index: kvm-userspace.io/libkvm/libkvm.c
===================================================================

libkvm/libkvm.c int kvm_create(kvm_context_t kvm, unsign · line 393

Quoted 9 lines
libkvm/libkvm.c +0 -3
@@ -388,9 +388,6 @@ int kvm_create(kvm_context_t kvm, unsign
 	if (r < 0)
 	        return r;
 	kvm_create_irqchip(kvm);
-	r = kvm_create_vcpu(kvm, 0);
-	if (r < 0)
-		return r;
 
 	return 0;
 }

Please put this and the corresponding qemu change in a separate patch.

Quoted 3 lines

[...lots more...]

Looks good.

Will do.

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

#3 lore raw
Quoted 16 lines · Marcelo Tosatti
Quoted 16 lines
Quoted 16 lines

QEMU/KVM: separate thread for IO handling

Move IO processing from vcpu0 to a dedicated thread.

This removes load on vcpu0 by allowing better cache locality and also improves latency.

We can now block signal handling for IO events, so sigtimedwait won't race with handlers:

- Currently the SIGALRM handler fails to set CPU_INTERRUPT_EXIT because the "next_cpu" variable is not initialized in the KVM path, meaning that processing of timer expiration might be delayed until the next vcpu0 exit.

Quoted 7 lines
Quoted 3 lines

I think we call main_loop_wait() is called unconditionally after every signal.

We exit the kvm_run() loop if CPU_INTERRUPT_EXIT is detected by pre_kvm_run().

But why do we need to exit the kvm_run() loop? As I understand it, the I/O thread wakes up when the signal is queued and calls main_loop_wait() to process any events (through qemu_run_timers()). If a timer needs to wake up a vcpu, it will raise an interrupt line which will wake the vcpu up, either in the kernel or in userspace depending on -no-kvm-irqchip.

Signature · 8 lines
error compiling committee.c: too many arguments to function


-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
#4 lore raw
Quoted 25 lines · Avi Kivity
Quoted 16 lines · Marcelo Tosatti
Quoted 16 lines
Quoted 16 lines

QEMU/KVM: separate thread for IO handling

Move IO processing from vcpu0 to a dedicated thread.

This removes load on vcpu0 by allowing better cache locality and also improves latency.

We can now block signal handling for IO events, so sigtimedwait won't race with handlers:

- Currently the SIGALRM handler fails to set CPU_INTERRUPT_EXIT because the "next_cpu" variable is not initialized in the KVM path, meaning that processing of timer expiration might be delayed until the next vcpu0 exit.

Quoted 7 lines
Quoted 3 lines

I think we call main_loop_wait() is called unconditionally after every signal.

We exit the kvm_run() loop if CPU_INTERRUPT_EXIT is detected by pre_kvm_run().

Quoted 5 lines

But why do we need to exit the kvm_run() loop? As I understand it, the I/O thread wakes up when the signal is queued and calls main_loop_wait() to process any events (through qemu_run_timers()). If a timer needs to wake up a vcpu, it will raise an interrupt line which will wake the vcpu up, either in the kernel or in userspace depending on -no-kvm-irqchip.

In the current state of vcpu0 thread handling IO, kvm_run() loop must bail out for main_loop_wait->qemu_run_timers() to run.

If using an userspace timer such as RTC (brought to attention by Dor's patches), the following will happen:

- signal wakes up vcpu0 thread, goes back to userspace.
- host_alarm_handler runs but fails to set CPU_INTERRUPT_EXIT because "next_cpu" is not initialized.
- pre_kvm_run() checks for CPU_INTERRUPT_EXIT and determines its not necessary to exit kvm_run(), so vcpu0 thread goes back into kernel to enter guest mode.

No interrupt was raised even though SIGALRM handler has executed.

AFAICS next_cpu is only initialized here:

static int main_loop(void)
{
...

    if (kvm_enabled()) {
        kvm_main_loop();
        cpu_disable_ticks();
        return 0;
    }

    cur_cpu = first_cpu;
    next_cpu = cur_cpu->next_cpu ?: first_cpu;
    for(;;) {

See ? I pointed this out as it appears to be another factor in unreliable userspace timers.

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace

#5 lore raw
Quoted 38 lines · Marcelo Tosatti
Quoted 25 lines · Avi Kivity
Quoted 16 lines · Marcelo Tosatti
Quoted 16 lines
Quoted 16 lines

QEMU/KVM: separate thread for IO handling

Move IO processing from vcpu0 to a dedicated thread.

This removes load on vcpu0 by allowing better cache locality and also improves latency.

We can now block signal handling for IO events, so sigtimedwait won't race with handlers:

- Currently the SIGALRM handler fails to set CPU_INTERRUPT_EXIT because the "next_cpu" variable is not initialized in the KVM path, meaning that processing of timer expiration might be delayed until the next vcpu0 exit.

Quoted 7 lines
Quoted 3 lines

I think we call main_loop_wait() is called unconditionally after every signal.

We exit the kvm_run() loop if CPU_INTERRUPT_EXIT is detected by pre_kvm_run().

Quoted 5 lines

But why do we need to exit the kvm_run() loop? As I understand it, the I/O thread wakes up when the signal is queued and calls main_loop_wait() to process any events (through qemu_run_timers()). If a timer needs to wake up a vcpu, it will raise an interrupt line which will wake the vcpu up, either in the kernel or in userspace depending on -no-kvm-irqchip.

In the current state of vcpu0 thread handling IO, kvm_run() loop must bail out for main_loop_wait->qemu_run_timers() to run.

If using an userspace timer such as RTC (brought to attention by Dor's patches), the following will happen:

Quoted 9 lines

- signal wakes up vcpu0 thread, goes back to userspace.
- host_alarm_handler runs but fails to set CPU_INTERRUPT_EXIT because "next_cpu" is not initialized.
- pre_kvm_run() checks for CPU_INTERRUPT_EXIT and determines its not necessary to exit kvm_run(), so vcpu0 thread goes back into kernel to enter guest mode.

No interrupt was raised even though SIGALRM handler has executed.

But what if the host_alarm_handler to wake up the sleeping IO thread, then it will run the timers and the irq will be triggered using ioctl. You're right that if the designated vcpu was in userspace at that time it might go back into the kernel but the time to do is decreases + the following:

Every vcpu reads it's irq vector every time before vcpu_run so the guest will receive the irq the next vmenter.
The lapic code sends kvm_vcpu_kick to the destination vcpu in order to cause a vmexit so interrupt would be injected next time.

Quoted 15 lines

AFAICS next_cpu is only initialized here:

static int main_loop(void)
{
...

    if (kvm_enabled()) {
        kvm_main_loop();
        cpu_disable_ticks();
        return 0;
    }

    cur_cpu = first_cpu;
    next_cpu = cur_cpu->next_cpu ?: first_cpu;
    for(;;) {
Quoted 3 lines

See ? I pointed this out as it appears to be another factor in unreliable userspace timers.

-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace