Signed-off-by: Gregory Haskins <[EMAIL PROTECTED]> --- drivers/kvm/kvm.h | 2 + drivers/kvm/kvm_main.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 0 deletions(-)
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index 0f6cc32..b5bfc91 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h @@ -331,6 +331,8 @@ struct kvm_vcpu_irq { int deferred; struct task_struct *task; int guest_mode; + wait_queue_head_t wq; + int usignal; }; struct kvm_vcpu { diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index a160638..6b40c18 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c @@ -40,6 +40,7 @@ #include <linux/file.h> #include <linux/fs.h> #include <linux/mount.h> +#include <linux/poll.h> #include "x86_emulate.h" #include "segment_descriptor.h" @@ -304,6 +305,7 @@ static struct kvm *kvm_create_vm(void) memset(&vcpu->irq, 0, sizeof(vcpu->irq)); spin_lock_init(&vcpu->irq.lock); vcpu->irq.deferred = -1; + init_waitqueue_head(&vcpu->irq.wq); vcpu->cpu = -1; vcpu->kvm = kvm; @@ -2265,11 +2267,78 @@ static int kvm_vcpu_release(struct inode *inode, struct file *filp) return 0; } +static unsigned int kvm_vcpu_poll(struct file *filp, poll_table *wait) +{ + struct kvm_vcpu *vcpu = filp->private_data; + unsigned int events = 0; + unsigned long flags; + + poll_wait(filp, &vcpu->irq.wq, wait); + + spin_lock_irqsave(&vcpu->irq.lock, flags); + if (vcpu->irq.usignal) + events |= POLLIN; + spin_unlock_irqrestore(&vcpu->irq.lock, flags); + + return events; +} + +static ssize_t kvm_vcpu_read(struct file *filp, char __user *buf, size_t count, + loff_t *ppos) +{ + struct kvm_vcpu *vcpu = filp->private_data; + ssize_t res = -EAGAIN; + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + int val; + + if (count < sizeof(vcpu->irq.usignal)) + return -EINVAL; + + spin_lock_irqsave(&vcpu->irq.lock, flags); + + val = vcpu->irq.usignal; + + if (val > 0) + res = sizeof(val); + else if (!(filp->f_flags & O_NONBLOCK)) { + __add_wait_queue(&vcpu->irq.wq, &wait); + for (res = 0;;) { + set_current_state(TASK_INTERRUPTIBLE); + if (val > 0) { + res = sizeof(val); + break; + } + if (signal_pending(current)) { + res = -ERESTARTSYS; + break; + } + spin_unlock_irqrestore(&vcpu->irq.lock, flags); + schedule(); + spin_lock_irqsave(&vcpu->irq.lock, flags); + } + __remove_wait_queue(&vcpu->irq.wq, &wait); + __set_current_state(TASK_RUNNING); + } + + if (res > 0) + vcpu->irq.usignal = 0; + + spin_unlock_irqrestore(&vcpu->irq.lock, flags); + + if (res > 0 && put_user(val, (int __user *) buf)) + return -EFAULT; + + return res; +} + static struct file_operations kvm_vcpu_fops = { .release = kvm_vcpu_release, .unlocked_ioctl = kvm_vcpu_ioctl, .compat_ioctl = kvm_vcpu_ioctl, .mmap = kvm_vcpu_mmap, + .poll = kvm_vcpu_poll, + .read = kvm_vcpu_read, }; /* @@ -2336,6 +2405,7 @@ static void kvm_vcpu_intr(struct kvm_irqsink *this, struct kvm_vcpu *vcpu = (struct kvm_vcpu*)this->private; unsigned long flags; int direct_ipi = -1; + int indirect_sig = 0; spin_lock_irqsave(&vcpu->irq.lock, flags); @@ -2357,6 +2427,15 @@ static void kvm_vcpu_intr(struct kvm_irqsink *this, */ direct_ipi = task_cpu(vcpu->irq.task); BUG_ON(direct_ipi == smp_processor_id()); + } else { + /* + * otherwise, we must assume that we could be + * blocked anywhere, including userspace. Send + * a signal to give everyone a chance to get + * notification + */ + vcpu->irq.usignal++; + indirect_sig = 1; } } } @@ -2379,6 +2458,9 @@ static void kvm_vcpu_intr(struct kvm_irqsink *this, smp_call_function_single(direct_ipi, kvm_vcpu_guest_intr, vcpu, 0, 0); + + if (indirect_sig && waitqueue_active(&vcpu->irq.wq)) + wake_up(&vcpu->irq.wq); } static void kvm_vcpu_irqsink_init(struct kvm_vcpu *vcpu) ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/ _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel