I mixed up files, this patch misses: /* See if the guest is running */ if (!kvm_cpus[i] || kvm_cpus[i]->thread == 0) return; In the beginning of kvm__pause() and kvm__continue(). I'll send an updated patch. On Sun, 2011-05-29 at 20:32 +0300, Sasha Levin wrote: > Allow pausing and unpausing guests running on the host. > Pausing a guest means that none of the VCPU threads are running > KVM_RUN until they are unpaused. > > Signed-off-by: Sasha Levin <levinsasha928@xxxxxxxxx> > --- > tools/kvm/include/kvm/kvm-cpu.h | 1 + > tools/kvm/include/kvm/kvm.h | 4 +++ > tools/kvm/kvm-cpu.c | 18 +++++++++++---- > tools/kvm/kvm-run.c | 4 +- > tools/kvm/kvm.c | 45 +++++++++++++++++++++++++++++++++++++++ > 5 files changed, 65 insertions(+), 7 deletions(-) > > diff --git a/tools/kvm/include/kvm/kvm-cpu.h b/tools/kvm/include/kvm/kvm-cpu.h > index b2b6fce..4d99246 100644 > --- a/tools/kvm/include/kvm/kvm-cpu.h > +++ b/tools/kvm/include/kvm/kvm-cpu.h > @@ -23,6 +23,7 @@ struct kvm_cpu { > struct kvm_msrs *msrs; /* dynamically allocated */ > > u8 is_running; > + u8 paused; > }; > > struct kvm_cpu *kvm_cpu__init(struct kvm *kvm, unsigned long cpu_id); > diff --git a/tools/kvm/include/kvm/kvm.h b/tools/kvm/include/kvm/kvm.h > index 6a17362..d22a849 100644 > --- a/tools/kvm/include/kvm/kvm.h > +++ b/tools/kvm/include/kvm/kvm.h > @@ -12,6 +12,7 @@ > #define KVM_32BIT_GAP_START ((1ULL << 32) - KVM_32BIT_GAP_SIZE) > > #define SIGKVMEXIT (SIGRTMIN + 0) > +#define SIGKVMPAUSE (SIGRTMIN + 1) > > struct kvm { > int sys_fd; /* For system ioctls(), i.e. /dev/kvm */ > @@ -50,6 +51,9 @@ bool kvm__emulate_io(struct kvm *kvm, u16 port, void *data, int direction, int s > bool kvm__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len, u8 is_write); > bool kvm__register_mmio(u64 phys_addr, u64 phys_addr_len, void (*kvm_mmio_callback_fn)(u64 addr, u8 *data, u32 len, u8 is_write)); > bool kvm__deregister_mmio(u64 phys_addr); > +void kvm__pause(void); > +void kvm__continue(void); > +void kvm__notify_paused(void); > > /* > * Debugging > diff --git a/tools/kvm/kvm-cpu.c b/tools/kvm/kvm-cpu.c > index de0591f..81f479f 100644 > --- a/tools/kvm/kvm-cpu.c > +++ b/tools/kvm/kvm-cpu.c > @@ -383,11 +383,15 @@ void kvm_cpu__run(struct kvm_cpu *vcpu) > die_perror("KVM_RUN failed"); > } > > -static void kvm_cpu_exit_handler(int signum) > +static void kvm_cpu_signal_handler(int signum) > { > - if (current_kvm_cpu->is_running) { > - current_kvm_cpu->is_running = false; > - pthread_kill(pthread_self(), SIGKVMEXIT); > + if (signum == SIGKVMEXIT) { > + if (current_kvm_cpu->is_running) { > + current_kvm_cpu->is_running = false; > + pthread_kill(pthread_self(), SIGKVMEXIT); > + } > + } else if (signum == SIGKVMPAUSE) { > + current_kvm_cpu->paused = 1; > } > } > > @@ -400,12 +404,16 @@ int kvm_cpu__start(struct kvm_cpu *cpu) > > pthread_sigmask(SIG_BLOCK, &sigset, NULL); > > - signal(SIGKVMEXIT, kvm_cpu_exit_handler); > + signal(SIGKVMEXIT, kvm_cpu_signal_handler); > + signal(SIGKVMPAUSE, kvm_cpu_signal_handler); > > kvm_cpu__setup_cpuid(cpu); > kvm_cpu__reset_vcpu(cpu); > > for (;;) { > + if (cpu->paused) > + kvm__notify_paused(); > + > kvm_cpu__run(cpu); > > switch (cpu->kvm_run->exit_reason) { > diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c > index 48b8e70..761ac0d 100644 > --- a/tools/kvm/kvm-run.c > +++ b/tools/kvm/kvm-run.c > @@ -47,8 +47,8 @@ > #define MIN_RAM_SIZE_MB (64ULL) > #define MIN_RAM_SIZE_BYTE (MIN_RAM_SIZE_MB << MB_SHIFT) > > -static struct kvm *kvm; > -static struct kvm_cpu *kvm_cpus[KVM_NR_CPUS]; > +struct kvm *kvm; > +struct kvm_cpu *kvm_cpus[KVM_NR_CPUS]; > __thread struct kvm_cpu *current_kvm_cpu; > > static u64 ram_size; > diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c > index 1d756e0..1e22566 100644 > --- a/tools/kvm/kvm.c > +++ b/tools/kvm/kvm.c > @@ -6,6 +6,8 @@ > #include "kvm/interrupt.h" > #include "kvm/mptable.h" > #include "kvm/util.h" > +#include "kvm/mutex.h" > +#include "kvm/kvm-cpu.h" > > #include <linux/kvm.h> > > @@ -25,6 +27,7 @@ > #include <stdio.h> > #include <fcntl.h> > #include <time.h> > +#include <sys/eventfd.h> > > #define DEFINE_KVM_EXIT_REASON(reason) [reason] = #reason > > @@ -68,6 +71,10 @@ struct { > { DEFINE_KVM_EXT(KVM_CAP_EXT_CPUID) }, > }; > > +extern struct kvm_cpu *kvm_cpus[KVM_NR_CPUS]; > +static int pause_event; > +static DEFINE_MUTEX(pause_lock); > + > static bool kvm__supports_extension(struct kvm *kvm, unsigned int extension) > { > int ret; > @@ -575,3 +582,41 @@ void kvm__dump_mem(struct kvm *kvm, unsigned long addr, unsigned long size) > p[n + 4], p[n + 5], p[n + 6], p[n + 7]); > } > } > + > +void kvm__pause(void) > +{ > + int i, paused_vcpus = 0; > + > + mutex_lock(&pause_lock); > + > + pause_event = eventfd(0, 0); > + if (pause_event < 0) > + die("Failed creating pause notification event"); > + for (i = 0; i < kvm.nrcpus; i++) > + pthread_kill(kvm_cpus[i]->thread, SIGKVMPAUSE); > + > + while (paused_vcpus < kvm.nrcpus) { > + u64 cur_read; > + > + if (read(pause_event, &cur_read, sizeof(cur_read)) < 0) > + die("Failed reading pause event"); > + paused_vcpus += cur_read; > + } > + close(pause_event); > +} > + > +void kvm__continue(void) > +{ > + mutex_unlock(&pause_lock); > +} > + > +void kvm__notify_paused(void) > +{ > + u64 p = 1; > + > + if (write(pause_event, &p, sizeof(p)) < 0) > + die("Failed notifying of paused VCPU."); > + > + mutex_lock(&pause_lock); > + mutex_unlock(&pause_lock); > +} -- Sasha. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html