diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2011-11-17 05:00:41 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-11-17 09:25:43 -0500 |
commit | 9e6dabeffd1d0ec2aa19aa076c4886067238d442 (patch) | |
tree | 6f5f2a06184a0e4ec0b8cff8db912ce6013c5056 /arch | |
parent | 3439a8da16bcad6b0982ece938c9f8299bb53584 (diff) |
KVM: s390: Fix RUNNING flag misinterpretation
CPUSTAT_RUNNING was implemented signifying that a vcpu is not stopped.
This is not, however, what the architecture says: RUNNING should be
set when the host is acting on the behalf of the guest operating
system.
CPUSTAT_RUNNING has been changed to be set in kvm_arch_vcpu_load()
and to be unset in kvm_arch_vcpu_put().
For signifying stopped state of a vcpu, a host-controlled bit has
been used and is set/unset basically on the reverse as the old
CPUSTAT_RUNNING bit (including pushing it down into stop handling
proper in handle_stop()).
Cc: stable@kernel.org
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Carsten Otte <cotte@de.ibm.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/s390/include/asm/kvm_host.h | 2 | ||||
-rw-r--r-- | arch/s390/kvm/diag.c | 2 | ||||
-rw-r--r-- | arch/s390/kvm/intercept.c | 3 | ||||
-rw-r--r-- | arch/s390/kvm/interrupt.c | 1 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 10 | ||||
-rw-r--r-- | arch/s390/kvm/sigp.c | 6 |
6 files changed, 15 insertions, 9 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 24e18473d926..20f9068cd6b5 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
@@ -47,7 +47,7 @@ struct sca_block { | |||
47 | #define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1)) | 47 | #define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1)) |
48 | #define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE) | 48 | #define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE) |
49 | 49 | ||
50 | #define CPUSTAT_HOST 0x80000000 | 50 | #define CPUSTAT_STOPPED 0x80000000 |
51 | #define CPUSTAT_WAIT 0x10000000 | 51 | #define CPUSTAT_WAIT 0x10000000 |
52 | #define CPUSTAT_ECALL_PEND 0x08000000 | 52 | #define CPUSTAT_ECALL_PEND 0x08000000 |
53 | #define CPUSTAT_STOP_INT 0x04000000 | 53 | #define CPUSTAT_STOP_INT 0x04000000 |
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c index 87cedd61be04..8943e82cd4d9 100644 --- a/arch/s390/kvm/diag.c +++ b/arch/s390/kvm/diag.c | |||
@@ -70,7 +70,7 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu) | |||
70 | return -EOPNOTSUPP; | 70 | return -EOPNOTSUPP; |
71 | } | 71 | } |
72 | 72 | ||
73 | atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); | 73 | atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags); |
74 | vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM; | 74 | vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM; |
75 | vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL; | 75 | vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL; |
76 | vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT; | 76 | vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT; |
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index c7c51898984e..02434543eabb 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c | |||
@@ -132,7 +132,6 @@ static int handle_stop(struct kvm_vcpu *vcpu) | |||
132 | int rc = 0; | 132 | int rc = 0; |
133 | 133 | ||
134 | vcpu->stat.exit_stop_request++; | 134 | vcpu->stat.exit_stop_request++; |
135 | atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); | ||
136 | spin_lock_bh(&vcpu->arch.local_int.lock); | 135 | spin_lock_bh(&vcpu->arch.local_int.lock); |
137 | if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) { | 136 | if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) { |
138 | vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP; | 137 | vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP; |
@@ -149,6 +148,8 @@ static int handle_stop(struct kvm_vcpu *vcpu) | |||
149 | } | 148 | } |
150 | 149 | ||
151 | if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) { | 150 | if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) { |
151 | atomic_set_mask(CPUSTAT_STOPPED, | ||
152 | &vcpu->arch.sie_block->cpuflags); | ||
152 | vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP; | 153 | vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP; |
153 | VCPU_EVENT(vcpu, 3, "%s", "cpu stopped"); | 154 | VCPU_EVENT(vcpu, 3, "%s", "cpu stopped"); |
154 | rc = -EOPNOTSUPP; | 155 | rc = -EOPNOTSUPP; |
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 87c16705b381..278ee009ce65 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -252,6 +252,7 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, | |||
252 | offsetof(struct _lowcore, restart_psw), sizeof(psw_t)); | 252 | offsetof(struct _lowcore, restart_psw), sizeof(psw_t)); |
253 | if (rc == -EFAULT) | 253 | if (rc == -EFAULT) |
254 | exception = 1; | 254 | exception = 1; |
255 | atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags); | ||
255 | break; | 256 | break; |
256 | 257 | ||
257 | case KVM_S390_PROGRAM_INT: | 258 | case KVM_S390_PROGRAM_INT: |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 0bd3bea1e4cd..630ab65b488b 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -270,10 +270,12 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | |||
270 | restore_fp_regs(&vcpu->arch.guest_fpregs); | 270 | restore_fp_regs(&vcpu->arch.guest_fpregs); |
271 | restore_access_regs(vcpu->arch.guest_acrs); | 271 | restore_access_regs(vcpu->arch.guest_acrs); |
272 | gmap_enable(vcpu->arch.gmap); | 272 | gmap_enable(vcpu->arch.gmap); |
273 | atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); | ||
273 | } | 274 | } |
274 | 275 | ||
275 | void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) | 276 | void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) |
276 | { | 277 | { |
278 | atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); | ||
277 | gmap_disable(vcpu->arch.gmap); | 279 | gmap_disable(vcpu->arch.gmap); |
278 | save_fp_regs(&vcpu->arch.guest_fpregs); | 280 | save_fp_regs(&vcpu->arch.guest_fpregs); |
279 | save_access_regs(vcpu->arch.guest_acrs); | 281 | save_access_regs(vcpu->arch.guest_acrs); |
@@ -301,7 +303,9 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu) | |||
301 | 303 | ||
302 | int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | 304 | int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) |
303 | { | 305 | { |
304 | atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | CPUSTAT_SM); | 306 | atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | |
307 | CPUSTAT_SM | | ||
308 | CPUSTAT_STOPPED); | ||
305 | vcpu->arch.sie_block->ecb = 6; | 309 | vcpu->arch.sie_block->ecb = 6; |
306 | vcpu->arch.sie_block->eca = 0xC1002001U; | 310 | vcpu->arch.sie_block->eca = 0xC1002001U; |
307 | vcpu->arch.sie_block->fac = (int) (long) facilities; | 311 | vcpu->arch.sie_block->fac = (int) (long) facilities; |
@@ -428,7 +432,7 @@ static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw) | |||
428 | { | 432 | { |
429 | int rc = 0; | 433 | int rc = 0; |
430 | 434 | ||
431 | if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING) | 435 | if (!(atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED)) |
432 | rc = -EBUSY; | 436 | rc = -EBUSY; |
433 | else { | 437 | else { |
434 | vcpu->run->psw_mask = psw.mask; | 438 | vcpu->run->psw_mask = psw.mask; |
@@ -501,7 +505,7 @@ rerun_vcpu: | |||
501 | if (vcpu->sigset_active) | 505 | if (vcpu->sigset_active) |
502 | sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); | 506 | sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); |
503 | 507 | ||
504 | atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags); | 508 | atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags); |
505 | 509 | ||
506 | BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL); | 510 | BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL); |
507 | 511 | ||
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index f815118835f3..4a488a98d7f8 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c | |||
@@ -57,8 +57,8 @@ static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, | |||
57 | spin_lock(&fi->lock); | 57 | spin_lock(&fi->lock); |
58 | if (fi->local_int[cpu_addr] == NULL) | 58 | if (fi->local_int[cpu_addr] == NULL) |
59 | rc = 3; /* not operational */ | 59 | rc = 3; /* not operational */ |
60 | else if (atomic_read(fi->local_int[cpu_addr]->cpuflags) | 60 | else if (!(atomic_read(fi->local_int[cpu_addr]->cpuflags) |
61 | & CPUSTAT_RUNNING) { | 61 | & CPUSTAT_STOPPED)) { |
62 | *reg &= 0xffffffff00000000UL; | 62 | *reg &= 0xffffffff00000000UL; |
63 | rc = 1; /* status stored */ | 63 | rc = 1; /* status stored */ |
64 | } else { | 64 | } else { |
@@ -251,7 +251,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, | |||
251 | 251 | ||
252 | spin_lock_bh(&li->lock); | 252 | spin_lock_bh(&li->lock); |
253 | /* cpu must be in stopped state */ | 253 | /* cpu must be in stopped state */ |
254 | if (atomic_read(li->cpuflags) & CPUSTAT_RUNNING) { | 254 | if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) { |
255 | rc = 1; /* incorrect state */ | 255 | rc = 1; /* incorrect state */ |
256 | *reg &= SIGP_STAT_INCORRECT_STATE; | 256 | *reg &= SIGP_STAT_INCORRECT_STATE; |
257 | kfree(inti); | 257 | kfree(inti); |