KVM: s390: sigp: separate preparation handlers

This patch introduces in preparation for further code changes separate handler
functions for:
- SIGP (RE)START - will not be allowed to terminate pending orders
- SIGP (INITIAL) CPU RESET - will be allowed to terminate certain pending orders
- unknown sigp orders

All sigp orders that require user space intervention are logged.

Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
This commit is contained in:
David Hildenbrand 2014-05-23 12:22:56 +02:00 committed by Christian Borntraeger
parent 3d95c7d2d7
commit b898383082
2 changed files with 33 additions and 15 deletions

View File

@ -10,6 +10,7 @@
#define SIGP_RESTART 6 #define SIGP_RESTART 6
#define SIGP_STOP_AND_STORE_STATUS 9 #define SIGP_STOP_AND_STORE_STATUS 9
#define SIGP_INITIAL_CPU_RESET 11 #define SIGP_INITIAL_CPU_RESET 11
#define SIGP_CPU_RESET 12
#define SIGP_SET_PREFIX 13 #define SIGP_SET_PREFIX 13
#define SIGP_STORE_STATUS_AT_ADDRESS 14 #define SIGP_STORE_STATUS_AT_ADDRESS 14
#define SIGP_SET_ARCHITECTURE 18 #define SIGP_SET_ARCHITECTURE 18

View File

@ -284,11 +284,12 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu,
return rc; return rc;
} }
/* Test whether the destination CPU is available and not busy */ static int __prepare_sigp_re_start(struct kvm_vcpu *vcpu,
static int sigp_check_callable(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu) struct kvm_vcpu *dst_vcpu, u8 order_code)
{ {
struct kvm_s390_local_interrupt *li = &dst_vcpu->arch.local_int; struct kvm_s390_local_interrupt *li = &dst_vcpu->arch.local_int;
int rc = SIGP_CC_ORDER_CODE_ACCEPTED; /* handle (RE)START in user space */
int rc = -EOPNOTSUPP;
spin_lock(&li->lock); spin_lock(&li->lock);
if (li->action_bits & ACTION_STOP_ON_STOP) if (li->action_bits & ACTION_STOP_ON_STOP)
@ -298,6 +299,20 @@ static int sigp_check_callable(struct kvm_vcpu *vcpu, struct kvm_vcpu *dst_vcpu)
return rc; return rc;
} }
static int __prepare_sigp_cpu_reset(struct kvm_vcpu *vcpu,
struct kvm_vcpu *dst_vcpu, u8 order_code)
{
/* handle (INITIAL) CPU RESET in user space */
return -EOPNOTSUPP;
}
static int __prepare_sigp_unknown(struct kvm_vcpu *vcpu,
struct kvm_vcpu *dst_vcpu)
{
/* handle unknown orders in user space */
return -EOPNOTSUPP;
}
static int handle_sigp_dst(struct kvm_vcpu *vcpu, u8 order_code, static int handle_sigp_dst(struct kvm_vcpu *vcpu, u8 order_code,
u16 cpu_addr, u32 parameter, u64 *status_reg) u16 cpu_addr, u32 parameter, u64 *status_reg)
{ {
@ -350,25 +365,27 @@ static int handle_sigp_dst(struct kvm_vcpu *vcpu, u8 order_code,
rc = __sigp_sense_running(vcpu, dst_vcpu, status_reg); rc = __sigp_sense_running(vcpu, dst_vcpu, status_reg);
break; break;
case SIGP_START: case SIGP_START:
rc = sigp_check_callable(vcpu, dst_vcpu); rc = __prepare_sigp_re_start(vcpu, dst_vcpu, order_code);
if (rc == SIGP_CC_ORDER_CODE_ACCEPTED)
rc = -EOPNOTSUPP; /* Handle START in user space */
break; break;
case SIGP_RESTART: case SIGP_RESTART:
vcpu->stat.instruction_sigp_restart++; vcpu->stat.instruction_sigp_restart++;
rc = sigp_check_callable(vcpu, dst_vcpu); rc = __prepare_sigp_re_start(vcpu, dst_vcpu, order_code);
if (rc == SIGP_CC_ORDER_CODE_ACCEPTED) { break;
VCPU_EVENT(vcpu, 4, case SIGP_INITIAL_CPU_RESET:
"sigp restart %x to handle userspace", rc = __prepare_sigp_cpu_reset(vcpu, dst_vcpu, order_code);
cpu_addr); break;
/* user space must know about restart */ case SIGP_CPU_RESET:
rc = -EOPNOTSUPP; rc = __prepare_sigp_cpu_reset(vcpu, dst_vcpu, order_code);
}
break; break;
default: default:
rc = -EOPNOTSUPP; rc = __prepare_sigp_unknown(vcpu, dst_vcpu);
} }
if (rc == -EOPNOTSUPP)
VCPU_EVENT(vcpu, 4,
"sigp order %u -> cpu %x: handled in user space",
order_code, dst_vcpu->vcpu_id);
return rc; return rc;
} }