aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-03-05 12:46:05 -0500
committerAvi Kivity <avi@qumranet.com>2007-05-03 03:52:24 -0400
commit1961d276c877b99f5f16aaf36377c75e0e191c3a (patch)
tree4ea92fc2821bd0f9013ee567ee2f11c6cc532d79 /drivers
parent6722c51c51518af9581ab6cd9b6aec93774334a6 (diff)
KVM: Add guest mode signal mask
Allow a special signal mask to be used while executing in guest mode. This allows signals to be used to interrupt a vcpu without requiring signal delivery to a userspace handler, which is quite expensive. Userspace still receives -EINTR and can get the signal via sigwait(). Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/kvm/kvm.h3
-rw-r--r--drivers/kvm/kvm_main.c41
2 files changed, 44 insertions, 0 deletions
diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
index be3a0e7ecae4..1c4a581938bf 100644
--- a/drivers/kvm/kvm.h
+++ b/drivers/kvm/kvm.h
@@ -277,6 +277,9 @@ struct kvm_vcpu {
277 gpa_t mmio_phys_addr; 277 gpa_t mmio_phys_addr;
278 int pio_pending; 278 int pio_pending;
279 279
280 int sigset_active;
281 sigset_t sigset;
282
280 struct { 283 struct {
281 int active; 284 int active;
282 u8 save_iopl; 285 u8 save_iopl;
diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
index ac44df551aa8..df85f5f65489 100644
--- a/drivers/kvm/kvm_main.c
+++ b/drivers/kvm/kvm_main.c
@@ -1591,9 +1591,13 @@ static void complete_pio(struct kvm_vcpu *vcpu)
1591static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 1591static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1592{ 1592{
1593 int r; 1593 int r;
1594 sigset_t sigsaved;
1594 1595
1595 vcpu_load(vcpu); 1596 vcpu_load(vcpu);
1596 1597
1598 if (vcpu->sigset_active)
1599 sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
1600
1597 /* re-sync apic's tpr */ 1601 /* re-sync apic's tpr */
1598 vcpu->cr8 = kvm_run->cr8; 1602 vcpu->cr8 = kvm_run->cr8;
1599 1603
@@ -1616,6 +1620,9 @@ static int kvm_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1616 1620
1617 r = kvm_arch_ops->run(vcpu, kvm_run); 1621 r = kvm_arch_ops->run(vcpu, kvm_run);
1618 1622
1623 if (vcpu->sigset_active)
1624 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1625
1619 vcpu_put(vcpu); 1626 vcpu_put(vcpu);
1620 return r; 1627 return r;
1621} 1628}
@@ -2142,6 +2149,17 @@ out:
2142 return r; 2149 return r;
2143} 2150}
2144 2151
2152static int kvm_vcpu_ioctl_set_sigmask(struct kvm_vcpu *vcpu, sigset_t *sigset)
2153{
2154 if (sigset) {
2155 sigdelsetmask(sigset, sigmask(SIGKILL)|sigmask(SIGSTOP));
2156 vcpu->sigset_active = 1;
2157 vcpu->sigset = *sigset;
2158 } else
2159 vcpu->sigset_active = 0;
2160 return 0;
2161}
2162
2145static long kvm_vcpu_ioctl(struct file *filp, 2163static long kvm_vcpu_ioctl(struct file *filp,
2146 unsigned int ioctl, unsigned long arg) 2164 unsigned int ioctl, unsigned long arg)
2147{ 2165{
@@ -2260,6 +2278,29 @@ static long kvm_vcpu_ioctl(struct file *filp,
2260 goto out; 2278 goto out;
2261 break; 2279 break;
2262 } 2280 }
2281 case KVM_SET_SIGNAL_MASK: {
2282 struct kvm_signal_mask __user *sigmask_arg = argp;
2283 struct kvm_signal_mask kvm_sigmask;
2284 sigset_t sigset, *p;
2285
2286 p = NULL;
2287 if (argp) {
2288 r = -EFAULT;
2289 if (copy_from_user(&kvm_sigmask, argp,
2290 sizeof kvm_sigmask))
2291 goto out;
2292 r = -EINVAL;
2293 if (kvm_sigmask.len != sizeof sigset)
2294 goto out;
2295 r = -EFAULT;
2296 if (copy_from_user(&sigset, sigmask_arg->sigset,
2297 sizeof sigset))
2298 goto out;
2299 p = &sigset;
2300 }
2301 r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
2302 break;
2303 }
2263 default: 2304 default:
2264 ; 2305 ;
2265 } 2306 }