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>
This commit is contained in:
parent
3439a8da16
commit
9e6dabeffd
@ -47,7 +47,7 @@ struct sca_block {
|
|||||||
#define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1))
|
#define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1))
|
||||||
#define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE)
|
#define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE)
|
||||||
|
|
||||||
#define CPUSTAT_HOST 0x80000000
|
#define CPUSTAT_STOPPED 0x80000000
|
||||||
#define CPUSTAT_WAIT 0x10000000
|
#define CPUSTAT_WAIT 0x10000000
|
||||||
#define CPUSTAT_ECALL_PEND 0x08000000
|
#define CPUSTAT_ECALL_PEND 0x08000000
|
||||||
#define CPUSTAT_STOP_INT 0x04000000
|
#define CPUSTAT_STOP_INT 0x04000000
|
||||||
|
@ -70,7 +70,7 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
|
|||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
|
atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
|
||||||
vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM;
|
vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM;
|
||||||
vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL;
|
vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL;
|
||||||
vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT;
|
vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT;
|
||||||
|
@ -132,7 +132,6 @@ static int handle_stop(struct kvm_vcpu *vcpu)
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
vcpu->stat.exit_stop_request++;
|
vcpu->stat.exit_stop_request++;
|
||||||
atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
|
|
||||||
spin_lock_bh(&vcpu->arch.local_int.lock);
|
spin_lock_bh(&vcpu->arch.local_int.lock);
|
||||||
if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
|
if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
|
||||||
vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
|
vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
|
||||||
@ -149,6 +148,8 @@ static int handle_stop(struct kvm_vcpu *vcpu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
|
if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
|
||||||
|
atomic_set_mask(CPUSTAT_STOPPED,
|
||||||
|
&vcpu->arch.sie_block->cpuflags);
|
||||||
vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
|
vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
|
||||||
VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
|
VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
|
||||||
rc = -EOPNOTSUPP;
|
rc = -EOPNOTSUPP;
|
||||||
|
@ -252,6 +252,7 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
|
|||||||
offsetof(struct _lowcore, restart_psw), sizeof(psw_t));
|
offsetof(struct _lowcore, restart_psw), sizeof(psw_t));
|
||||||
if (rc == -EFAULT)
|
if (rc == -EFAULT)
|
||||||
exception = 1;
|
exception = 1;
|
||||||
|
atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KVM_S390_PROGRAM_INT:
|
case KVM_S390_PROGRAM_INT:
|
||||||
|
@ -270,10 +270,12 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
|||||||
restore_fp_regs(&vcpu->arch.guest_fpregs);
|
restore_fp_regs(&vcpu->arch.guest_fpregs);
|
||||||
restore_access_regs(vcpu->arch.guest_acrs);
|
restore_access_regs(vcpu->arch.guest_acrs);
|
||||||
gmap_enable(vcpu->arch.gmap);
|
gmap_enable(vcpu->arch.gmap);
|
||||||
|
atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
|
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
|
atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
|
||||||
gmap_disable(vcpu->arch.gmap);
|
gmap_disable(vcpu->arch.gmap);
|
||||||
save_fp_regs(&vcpu->arch.guest_fpregs);
|
save_fp_regs(&vcpu->arch.guest_fpregs);
|
||||||
save_access_regs(vcpu->arch.guest_acrs);
|
save_access_regs(vcpu->arch.guest_acrs);
|
||||||
@ -301,7 +303,9 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
|
|||||||
|
|
||||||
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
|
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | CPUSTAT_SM);
|
atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
|
||||||
|
CPUSTAT_SM |
|
||||||
|
CPUSTAT_STOPPED);
|
||||||
vcpu->arch.sie_block->ecb = 6;
|
vcpu->arch.sie_block->ecb = 6;
|
||||||
vcpu->arch.sie_block->eca = 0xC1002001U;
|
vcpu->arch.sie_block->eca = 0xC1002001U;
|
||||||
vcpu->arch.sie_block->fac = (int) (long) facilities;
|
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)
|
|||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING)
|
if (!(atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED))
|
||||||
rc = -EBUSY;
|
rc = -EBUSY;
|
||||||
else {
|
else {
|
||||||
vcpu->run->psw_mask = psw.mask;
|
vcpu->run->psw_mask = psw.mask;
|
||||||
@ -501,7 +505,7 @@ rerun_vcpu:
|
|||||||
if (vcpu->sigset_active)
|
if (vcpu->sigset_active)
|
||||||
sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
|
sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
|
||||||
|
|
||||||
atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
|
atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
|
||||||
|
|
||||||
BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
|
BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
|
||||||
|
|
||||||
|
@ -57,8 +57,8 @@ static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr,
|
|||||||
spin_lock(&fi->lock);
|
spin_lock(&fi->lock);
|
||||||
if (fi->local_int[cpu_addr] == NULL)
|
if (fi->local_int[cpu_addr] == NULL)
|
||||||
rc = 3; /* not operational */
|
rc = 3; /* not operational */
|
||||||
else if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
|
else if (!(atomic_read(fi->local_int[cpu_addr]->cpuflags)
|
||||||
& CPUSTAT_RUNNING) {
|
& CPUSTAT_STOPPED)) {
|
||||||
*reg &= 0xffffffff00000000UL;
|
*reg &= 0xffffffff00000000UL;
|
||||||
rc = 1; /* status stored */
|
rc = 1; /* status stored */
|
||||||
} else {
|
} else {
|
||||||
@ -251,7 +251,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
|
|||||||
|
|
||||||
spin_lock_bh(&li->lock);
|
spin_lock_bh(&li->lock);
|
||||||
/* cpu must be in stopped state */
|
/* cpu must be in stopped state */
|
||||||
if (atomic_read(li->cpuflags) & CPUSTAT_RUNNING) {
|
if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
|
||||||
rc = 1; /* incorrect state */
|
rc = 1; /* incorrect state */
|
||||||
*reg &= SIGP_STAT_INCORRECT_STATE;
|
*reg &= SIGP_STAT_INCORRECT_STATE;
|
||||||
kfree(inti);
|
kfree(inti);
|
||||||
|
Loading…
Reference in New Issue
Block a user