aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/kvm/kvm.h3
-rw-r--r--drivers/kvm/kvm_main.c41
-rw-r--r--include/linux/kvm.h7
3 files changed, 51 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 }
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index b3af92e7bf5d..c0d10cd8088e 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -234,6 +234,12 @@ struct kvm_cpuid {
234 struct kvm_cpuid_entry entries[0]; 234 struct kvm_cpuid_entry entries[0];
235}; 235};
236 236
237/* for KVM_SET_SIGNAL_MASK */
238struct kvm_signal_mask {
239 __u32 len;
240 __u8 sigset[0];
241};
242
237#define KVMIO 0xAE 243#define KVMIO 0xAE
238 244
239/* 245/*
@@ -273,5 +279,6 @@ struct kvm_cpuid {
273#define KVM_GET_MSRS _IOWR(KVMIO, 0x88, struct kvm_msrs) 279#define KVM_GET_MSRS _IOWR(KVMIO, 0x88, struct kvm_msrs)
274#define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs) 280#define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs)
275#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid) 281#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid)
282#define KVM_SET_SIGNAL_MASK _IOW(KVMIO, 0x8b, struct kvm_signal_mask)
276 283
277#endif 284#endif