diff options
author | Thomas Huth <thuth@linux.vnet.ibm.com> | 2013-09-12 04:33:45 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-09-24 13:12:19 -0400 |
commit | 800c1065c3207a1b04d4ac457a57a37ce19eeb21 (patch) | |
tree | 62d1230e8b487587110150dc4a26c3157a23877c | |
parent | a76ccff6f5ed89153bf58ef4215b5512a0316877 (diff) |
KVM: s390: Lock kvm->srcu at the appropriate places
The kvm->srcu lock has to be held while accessing the memory of
guests and during certain other actions. This patch now adds
the locks to the __vcpu_run function so that all affected code
is protected now (and additionally to the KVM_S390_STORE_STATUS
ioctl, which can be called out-of-band and needs a separate lock).
Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Acked-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | arch/s390/kvm/diag.c | 4 | ||||
-rw-r--r-- | arch/s390/kvm/interrupt.c | 3 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 12 |
3 files changed, 16 insertions, 3 deletions
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index 3a74d8af0d69..78d967f180f4 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c | |||
@@ -107,14 +107,13 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu) | |||
107 | 107 | ||
108 | static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu) | 108 | static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu) |
109 | { | 109 | { |
110 | int ret, idx; | 110 | int ret; |
111 | 111 | ||
112 | /* No virtio-ccw notification? Get out quickly. */ | 112 | /* No virtio-ccw notification? Get out quickly. */ |
113 | if (!vcpu->kvm->arch.css_support || | 113 | if (!vcpu->kvm->arch.css_support || |
114 | (vcpu->run->s.regs.gprs[1] != KVM_S390_VIRTIO_CCW_NOTIFY)) | 114 | (vcpu->run->s.regs.gprs[1] != KVM_S390_VIRTIO_CCW_NOTIFY)) |
115 | return -EOPNOTSUPP; | 115 | return -EOPNOTSUPP; |
116 | 116 | ||
117 | idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
118 | /* | 117 | /* |
119 | * The layout is as follows: | 118 | * The layout is as follows: |
120 | * - gpr 2 contains the subchannel id (passed as addr) | 119 | * - gpr 2 contains the subchannel id (passed as addr) |
@@ -125,7 +124,6 @@ static int __diag_virtio_hypercall(struct kvm_vcpu *vcpu) | |||
125 | vcpu->run->s.regs.gprs[2], | 124 | vcpu->run->s.regs.gprs[2], |
126 | 8, &vcpu->run->s.regs.gprs[3], | 125 | 8, &vcpu->run->s.regs.gprs[3], |
127 | vcpu->run->s.regs.gprs[4]); | 126 | vcpu->run->s.regs.gprs[4]); |
128 | srcu_read_unlock(&vcpu->kvm->srcu, idx); | ||
129 | 127 | ||
130 | /* | 128 | /* |
131 | * Return cookie in gpr 2, but don't overwrite the register if the | 129 | * Return cookie in gpr 2, but don't overwrite the register if the |
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 7f35cb33e510..e7323cd9f109 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -436,6 +436,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) | |||
436 | hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); | 436 | hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); |
437 | VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime); | 437 | VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime); |
438 | no_timer: | 438 | no_timer: |
439 | srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); | ||
439 | spin_lock(&vcpu->arch.local_int.float_int->lock); | 440 | spin_lock(&vcpu->arch.local_int.float_int->lock); |
440 | spin_lock_bh(&vcpu->arch.local_int.lock); | 441 | spin_lock_bh(&vcpu->arch.local_int.lock); |
441 | add_wait_queue(&vcpu->wq, &wait); | 442 | add_wait_queue(&vcpu->wq, &wait); |
@@ -455,6 +456,8 @@ no_timer: | |||
455 | remove_wait_queue(&vcpu->wq, &wait); | 456 | remove_wait_queue(&vcpu->wq, &wait); |
456 | spin_unlock_bh(&vcpu->arch.local_int.lock); | 457 | spin_unlock_bh(&vcpu->arch.local_int.lock); |
457 | spin_unlock(&vcpu->arch.local_int.float_int->lock); | 458 | spin_unlock(&vcpu->arch.local_int.float_int->lock); |
459 | vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
460 | |||
458 | hrtimer_try_to_cancel(&vcpu->arch.ckc_timer); | 461 | hrtimer_try_to_cancel(&vcpu->arch.ckc_timer); |
459 | return 0; | 462 | return 0; |
460 | } | 463 | } |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 8eec7abc5664..1e4e7b97337a 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -752,11 +752,18 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) | |||
752 | { | 752 | { |
753 | int rc, exit_reason; | 753 | int rc, exit_reason; |
754 | 754 | ||
755 | /* | ||
756 | * We try to hold kvm->srcu during most of vcpu_run (except when run- | ||
757 | * ning the guest), so that memslots (and other stuff) are protected | ||
758 | */ | ||
759 | vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
760 | |||
755 | do { | 761 | do { |
756 | rc = vcpu_pre_run(vcpu); | 762 | rc = vcpu_pre_run(vcpu); |
757 | if (rc) | 763 | if (rc) |
758 | break; | 764 | break; |
759 | 765 | ||
766 | srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); | ||
760 | /* | 767 | /* |
761 | * As PF_VCPU will be used in fault handler, between | 768 | * As PF_VCPU will be used in fault handler, between |
762 | * guest_enter and guest_exit should be no uaccess. | 769 | * guest_enter and guest_exit should be no uaccess. |
@@ -767,10 +774,12 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) | |||
767 | exit_reason = sie64a(vcpu->arch.sie_block, | 774 | exit_reason = sie64a(vcpu->arch.sie_block, |
768 | vcpu->run->s.regs.gprs); | 775 | vcpu->run->s.regs.gprs); |
769 | kvm_guest_exit(); | 776 | kvm_guest_exit(); |
777 | vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
770 | 778 | ||
771 | rc = vcpu_post_run(vcpu, exit_reason); | 779 | rc = vcpu_post_run(vcpu, exit_reason); |
772 | } while (!signal_pending(current) && !rc); | 780 | } while (!signal_pending(current) && !rc); |
773 | 781 | ||
782 | srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); | ||
774 | return rc; | 783 | return rc; |
775 | } | 784 | } |
776 | 785 | ||
@@ -968,6 +977,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, | |||
968 | { | 977 | { |
969 | struct kvm_vcpu *vcpu = filp->private_data; | 978 | struct kvm_vcpu *vcpu = filp->private_data; |
970 | void __user *argp = (void __user *)arg; | 979 | void __user *argp = (void __user *)arg; |
980 | int idx; | ||
971 | long r; | 981 | long r; |
972 | 982 | ||
973 | switch (ioctl) { | 983 | switch (ioctl) { |
@@ -981,7 +991,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp, | |||
981 | break; | 991 | break; |
982 | } | 992 | } |
983 | case KVM_S390_STORE_STATUS: | 993 | case KVM_S390_STORE_STATUS: |
994 | idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
984 | r = kvm_s390_vcpu_store_status(vcpu, arg); | 995 | r = kvm_s390_vcpu_store_status(vcpu, arg); |
996 | srcu_read_unlock(&vcpu->kvm->srcu, idx); | ||
985 | break; | 997 | break; |
986 | case KVM_S390_SET_INITIAL_PSW: { | 998 | case KVM_S390_SET_INITIAL_PSW: { |
987 | psw_t psw; | 999 | psw_t psw; |