From 9b747530d928800c9eb7f0c131dffd2cc868c475 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 26 Jun 2012 16:06:37 +0200 Subject: s390/smp/kvm: unifiy sigp definitions The smp and the kvm code have different defines for the sigp order codes. Let's just have a single place where these are defined. Also move the sigp condition code and sigp cpu status bits to the new sigp.h header file. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky Signed-off-by: Cornelia Huck Signed-off-by: Marcelo Tosatti --- arch/s390/kvm/sigp.c | 46 +++++++++------------------------------------- 1 file changed, 9 insertions(+), 37 deletions(-) (limited to 'arch/s390/kvm/sigp.c') diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index 0ad4cf2..fda1d64 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -15,38 +15,10 @@ #include #include #include +#include #include "gaccess.h" #include "kvm-s390.h" -/* sigp order codes */ -#define SIGP_SENSE 0x01 -#define SIGP_EXTERNAL_CALL 0x02 -#define SIGP_EMERGENCY 0x03 -#define SIGP_START 0x04 -#define SIGP_STOP 0x05 -#define SIGP_RESTART 0x06 -#define SIGP_STOP_STORE_STATUS 0x09 -#define SIGP_INITIAL_CPU_RESET 0x0b -#define SIGP_CPU_RESET 0x0c -#define SIGP_SET_PREFIX 0x0d -#define SIGP_STORE_STATUS_ADDR 0x0e -#define SIGP_SET_ARCH 0x12 -#define SIGP_SENSE_RUNNING 0x15 - -/* cpu status bits */ -#define SIGP_STAT_EQUIPMENT_CHECK 0x80000000UL -#define SIGP_STAT_NOT_RUNNING 0x00000400UL -#define SIGP_STAT_INCORRECT_STATE 0x00000200UL -#define SIGP_STAT_INVALID_PARAMETER 0x00000100UL -#define SIGP_STAT_EXT_CALL_PENDING 0x00000080UL -#define SIGP_STAT_STOPPED 0x00000040UL -#define SIGP_STAT_OPERATOR_INTERV 0x00000020UL -#define SIGP_STAT_CHECK_STOP 0x00000010UL -#define SIGP_STAT_INOPERATIVE 0x00000004UL -#define SIGP_STAT_INVALID_ORDER 0x00000002UL -#define SIGP_STAT_RECEIVER_CHECK 0x00000001UL - - static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, u64 *reg) { @@ -65,7 +37,7 @@ static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, rc = 1; /* status stored */ } else { *reg &= 0xffffffff00000000UL; - *reg |= SIGP_STAT_STOPPED; + *reg |= SIGP_STATUS_STOPPED; rc = 1; /* status stored */ } spin_unlock(&fi->lock); @@ -235,7 +207,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, address = address & 0x7fffe000u; if (copy_from_guest_absolute(vcpu, &tmp, address, 1) || copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1)) { - *reg |= SIGP_STAT_INVALID_PARAMETER; + *reg |= SIGP_STATUS_INVALID_PARAMETER; return 1; /* invalid parameter */ } @@ -249,7 +221,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, if (li == NULL) { rc = 1; /* incorrect state */ - *reg &= SIGP_STAT_INCORRECT_STATE; + *reg &= SIGP_STATUS_INCORRECT_STATE; kfree(inti); goto out_fi; } @@ -258,7 +230,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, /* cpu must be in stopped state */ if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) { rc = 1; /* incorrect state */ - *reg &= SIGP_STAT_INCORRECT_STATE; + *reg &= SIGP_STATUS_INCORRECT_STATE; kfree(inti); goto out_li; } @@ -300,7 +272,7 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr, } else { /* not running */ *reg &= 0xffffffff00000000UL; - *reg |= SIGP_STAT_NOT_RUNNING; + *reg |= SIGP_STATUS_NOT_RUNNING; rc = 0; } } @@ -375,7 +347,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) vcpu->stat.instruction_sigp_external_call++; rc = __sigp_external_call(vcpu, cpu_addr); break; - case SIGP_EMERGENCY: + case SIGP_EMERGENCY_SIGNAL: vcpu->stat.instruction_sigp_emergency++; rc = __sigp_emergency(vcpu, cpu_addr); break; @@ -383,12 +355,12 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) vcpu->stat.instruction_sigp_stop++; rc = __sigp_stop(vcpu, cpu_addr, ACTION_STOP_ON_STOP); break; - case SIGP_STOP_STORE_STATUS: + case SIGP_STOP_AND_STORE_STATUS: vcpu->stat.instruction_sigp_stop++; rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP | ACTION_STOP_ON_STOP); break; - case SIGP_SET_ARCH: + case SIGP_SET_ARCHITECTURE: vcpu->stat.instruction_sigp_arch++; rc = __sigp_set_arch(vcpu, parameter); break; -- cgit v1.1 From 7ba26c482fcb42b01785ee1f39871fcc636ab3fe Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 26 Jun 2012 16:06:38 +0200 Subject: KVM: s390: fix sigp sense running condition code handling Only if the sensed cpu is not running a status is stored, which is reflected by condition code 1. If the cpu is running, condition code 0 should be returned. Just the opposite of what the code is doing. Acked-by: Cornelia Huck Signed-off-by: Heiko Carstens Signed-off-by: Cornelia Huck Signed-off-by: Marcelo Tosatti --- arch/s390/kvm/sigp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/s390/kvm/sigp.c') diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index fda1d64..caccc0e 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -268,12 +268,12 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr, if (atomic_read(fi->local_int[cpu_addr]->cpuflags) & CPUSTAT_RUNNING) { /* running */ - rc = 1; + rc = 0; } else { /* not running */ *reg &= 0xffffffff00000000UL; *reg |= SIGP_STATUS_NOT_RUNNING; - rc = 0; + rc = 1; } } spin_unlock(&fi->lock); -- cgit v1.1 From 0744426e28490357855aafd2ca76c819231851c5 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 26 Jun 2012 16:06:39 +0200 Subject: KVM: s390: fix sigp set prefix status stored cases If an invalid parameter is passed or the addressed cpu is in an incorrect state sigp set prefix will store a status. This status must only have bits set as defined by the architecture. The current kvm implementation missed to clear bits and also did not set the intended status bit ("and" instead of "or" operation). Signed-off-by: Heiko Carstens Signed-off-by: Cornelia Huck Signed-off-by: Marcelo Tosatti --- arch/s390/kvm/sigp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch/s390/kvm/sigp.c') diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index caccc0e..ca544d5 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -207,6 +207,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, address = address & 0x7fffe000u; if (copy_from_guest_absolute(vcpu, &tmp, address, 1) || copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1)) { + *reg &= 0xffffffff00000000UL; *reg |= SIGP_STATUS_INVALID_PARAMETER; return 1; /* invalid parameter */ } @@ -220,8 +221,9 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, li = fi->local_int[cpu_addr]; if (li == NULL) { + *reg &= 0xffffffff00000000UL; + *reg |= SIGP_STATUS_INCORRECT_STATE; rc = 1; /* incorrect state */ - *reg &= SIGP_STATUS_INCORRECT_STATE; kfree(inti); goto out_fi; } @@ -229,8 +231,9 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, spin_lock_bh(&li->lock); /* cpu must be in stopped state */ if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) { + *reg &= 0xffffffff00000000UL; + *reg |= SIGP_STATUS_INCORRECT_STATE; rc = 1; /* incorrect state */ - *reg &= SIGP_STATUS_INCORRECT_STATE; kfree(inti); goto out_li; } -- cgit v1.1 From ea1918dd3d1a8fcb7ce26816fdf31a50f7d04689 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 26 Jun 2012 16:06:40 +0200 Subject: KVM: s390: use sigp condition code defines Just use the defines instead of using plain numbers and adding a comment behind each line. Signed-off-by: Heiko Carstens Signed-off-by: Cornelia Huck Signed-off-by: Marcelo Tosatti --- arch/s390/kvm/sigp.c | 58 ++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'arch/s390/kvm/sigp.c') diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index ca544d5..97c9f36 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -26,19 +26,19 @@ static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, int rc; if (cpu_addr >= KVM_MAX_VCPUS) - return 3; /* not operational */ + return SIGP_CC_NOT_OPERATIONAL; spin_lock(&fi->lock); if (fi->local_int[cpu_addr] == NULL) - rc = 3; /* not operational */ + rc = SIGP_CC_NOT_OPERATIONAL; else if (!(atomic_read(fi->local_int[cpu_addr]->cpuflags) & CPUSTAT_STOPPED)) { *reg &= 0xffffffff00000000UL; - rc = 1; /* status stored */ + rc = SIGP_CC_STATUS_STORED; } else { *reg &= 0xffffffff00000000UL; *reg |= SIGP_STATUS_STOPPED; - rc = 1; /* status stored */ + rc = SIGP_CC_STATUS_STORED; } spin_unlock(&fi->lock); @@ -54,7 +54,7 @@ static int __sigp_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr) int rc; if (cpu_addr >= KVM_MAX_VCPUS) - return 3; /* not operational */ + return SIGP_CC_NOT_OPERATIONAL; inti = kzalloc(sizeof(*inti), GFP_KERNEL); if (!inti) @@ -66,7 +66,7 @@ static int __sigp_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr) spin_lock(&fi->lock); li = fi->local_int[cpu_addr]; if (li == NULL) { - rc = 3; /* not operational */ + rc = SIGP_CC_NOT_OPERATIONAL; kfree(inti); goto unlock; } @@ -77,7 +77,7 @@ static int __sigp_emergency(struct kvm_vcpu *vcpu, u16 cpu_addr) if (waitqueue_active(&li->wq)) wake_up_interruptible(&li->wq); spin_unlock_bh(&li->lock); - rc = 0; /* order accepted */ + rc = SIGP_CC_ORDER_CODE_ACCEPTED; VCPU_EVENT(vcpu, 4, "sent sigp emerg to cpu %x", cpu_addr); unlock: spin_unlock(&fi->lock); @@ -92,7 +92,7 @@ static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr) int rc; if (cpu_addr >= KVM_MAX_VCPUS) - return 3; /* not operational */ + return SIGP_CC_NOT_OPERATIONAL; inti = kzalloc(sizeof(*inti), GFP_KERNEL); if (!inti) @@ -104,7 +104,7 @@ static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr) spin_lock(&fi->lock); li = fi->local_int[cpu_addr]; if (li == NULL) { - rc = 3; /* not operational */ + rc = SIGP_CC_NOT_OPERATIONAL; kfree(inti); goto unlock; } @@ -115,7 +115,7 @@ static int __sigp_external_call(struct kvm_vcpu *vcpu, u16 cpu_addr) if (waitqueue_active(&li->wq)) wake_up_interruptible(&li->wq); spin_unlock_bh(&li->lock); - rc = 0; /* order accepted */ + rc = SIGP_CC_ORDER_CODE_ACCEPTED; VCPU_EVENT(vcpu, 4, "sent sigp ext call to cpu %x", cpu_addr); unlock: spin_unlock(&fi->lock); @@ -143,7 +143,7 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action) out: spin_unlock_bh(&li->lock); - return 0; /* order accepted */ + return SIGP_CC_ORDER_CODE_ACCEPTED; } static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action) @@ -153,12 +153,12 @@ static int __sigp_stop(struct kvm_vcpu *vcpu, u16 cpu_addr, int action) int rc; if (cpu_addr >= KVM_MAX_VCPUS) - return 3; /* not operational */ + return SIGP_CC_NOT_OPERATIONAL; spin_lock(&fi->lock); li = fi->local_int[cpu_addr]; if (li == NULL) { - rc = 3; /* not operational */ + rc = SIGP_CC_NOT_OPERATIONAL; goto unlock; } @@ -182,11 +182,11 @@ static int __sigp_set_arch(struct kvm_vcpu *vcpu, u32 parameter) switch (parameter & 0xff) { case 0: - rc = 3; /* not operational */ + rc = SIGP_CC_NOT_OPERATIONAL; break; case 1: case 2: - rc = 0; /* order accepted */ + rc = SIGP_CC_ORDER_CODE_ACCEPTED; break; default: rc = -EOPNOTSUPP; @@ -209,12 +209,12 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1)) { *reg &= 0xffffffff00000000UL; *reg |= SIGP_STATUS_INVALID_PARAMETER; - return 1; /* invalid parameter */ + return SIGP_CC_STATUS_STORED; } inti = kzalloc(sizeof(*inti), GFP_KERNEL); if (!inti) - return 2; /* busy */ + return SIGP_CC_BUSY; spin_lock(&fi->lock); if (cpu_addr < KVM_MAX_VCPUS) @@ -223,7 +223,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, if (li == NULL) { *reg &= 0xffffffff00000000UL; *reg |= SIGP_STATUS_INCORRECT_STATE; - rc = 1; /* incorrect state */ + rc = SIGP_CC_STATUS_STORED; kfree(inti); goto out_fi; } @@ -233,7 +233,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) { *reg &= 0xffffffff00000000UL; *reg |= SIGP_STATUS_INCORRECT_STATE; - rc = 1; /* incorrect state */ + rc = SIGP_CC_STATUS_STORED; kfree(inti); goto out_li; } @@ -245,7 +245,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address, atomic_set(&li->active, 1); if (waitqueue_active(&li->wq)) wake_up_interruptible(&li->wq); - rc = 0; /* order accepted */ + rc = SIGP_CC_ORDER_CODE_ACCEPTED; VCPU_EVENT(vcpu, 4, "set prefix of cpu %02x to %x", cpu_addr, address); out_li: @@ -262,21 +262,21 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr, struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; if (cpu_addr >= KVM_MAX_VCPUS) - return 3; /* not operational */ + return SIGP_CC_NOT_OPERATIONAL; spin_lock(&fi->lock); if (fi->local_int[cpu_addr] == NULL) - rc = 3; /* not operational */ + rc = SIGP_CC_NOT_OPERATIONAL; else { if (atomic_read(fi->local_int[cpu_addr]->cpuflags) & CPUSTAT_RUNNING) { /* running */ - rc = 0; + rc = SIGP_CC_ORDER_CODE_ACCEPTED; } else { /* not running */ *reg &= 0xffffffff00000000UL; *reg |= SIGP_STATUS_NOT_RUNNING; - rc = 1; + rc = SIGP_CC_STATUS_STORED; } } spin_unlock(&fi->lock); @@ -289,23 +289,23 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr, static int __sigp_restart(struct kvm_vcpu *vcpu, u16 cpu_addr) { - int rc = 0; struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int; struct kvm_s390_local_interrupt *li; + int rc = SIGP_CC_ORDER_CODE_ACCEPTED; if (cpu_addr >= KVM_MAX_VCPUS) - return 3; /* not operational */ + return SIGP_CC_NOT_OPERATIONAL; spin_lock(&fi->lock); li = fi->local_int[cpu_addr]; if (li == NULL) { - rc = 3; /* not operational */ + rc = SIGP_CC_NOT_OPERATIONAL; goto out; } spin_lock_bh(&li->lock); if (li->action_bits & ACTION_STOP_ON_STOP) - rc = 2; /* busy */ + rc = SIGP_CC_BUSY; else VCPU_EVENT(vcpu, 4, "sigp restart %x to handle userspace", cpu_addr); @@ -380,7 +380,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) case SIGP_RESTART: vcpu->stat.instruction_sigp_restart++; rc = __sigp_restart(vcpu, cpu_addr); - if (rc == 2) /* busy */ + if (rc == SIGP_CC_BUSY) break; /* user space must know about restart */ default: -- cgit v1.1 From 21b26c08535c992802402c7ba2d789ca9e1a5707 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Tue, 26 Jun 2012 16:06:41 +0200 Subject: KVM: s390: Fix sigp sense handling. If sigp sense doesn't have any status bits to report, it should set cc 0 and leave the register as-is. Since we know about the external call pending bit, we should report it if it is set as well. Acked-by: Heiko Carstens Reviewed-by: Christian Borntraeger Signed-off-by: Cornelia Huck Signed-off-by: Marcelo Tosatti --- arch/s390/kvm/sigp.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'arch/s390/kvm/sigp.c') diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index 97c9f36..6ed8175 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c @@ -32,12 +32,16 @@ static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr, if (fi->local_int[cpu_addr] == NULL) rc = SIGP_CC_NOT_OPERATIONAL; else if (!(atomic_read(fi->local_int[cpu_addr]->cpuflags) - & CPUSTAT_STOPPED)) { - *reg &= 0xffffffff00000000UL; - rc = SIGP_CC_STATUS_STORED; - } else { + & (CPUSTAT_ECALL_PEND | CPUSTAT_STOPPED))) + rc = SIGP_CC_ORDER_CODE_ACCEPTED; + else { *reg &= 0xffffffff00000000UL; - *reg |= SIGP_STATUS_STOPPED; + if (atomic_read(fi->local_int[cpu_addr]->cpuflags) + & CPUSTAT_ECALL_PEND) + *reg |= SIGP_STATUS_EXT_CALL_PENDING; + if (atomic_read(fi->local_int[cpu_addr]->cpuflags) + & CPUSTAT_STOPPED) + *reg |= SIGP_STATUS_STOPPED; rc = SIGP_CC_STATUS_STORED; } spin_unlock(&fi->lock); -- cgit v1.1