aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2014-10-09 08:10:13 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2015-01-23 07:25:37 -0500
commit2444b352c3acf54897b0e2803a7c4e66699f9f43 (patch)
tree42490c1860791c4d674fe8c40aaf77c4d0407ab7 /arch/s390
parent9fbd80828cef1b1bba5a293609a021047bb86a7e (diff)
KVM: s390: forward most SIGP orders to user space
Most SIGP orders are handled partially in kernel and partially in user space. In order to: - Get a correct SIGP SET PREFIX handler that informs user space - Avoid race conditions between concurrently executed SIGP orders - Serialize SIGP orders per VCPU We need to handle all "slow" SIGP orders in user space. The remaining ones to be handled completely in kernel are: - SENSE - SENSE RUNNING - EXTERNAL CALL - EMERGENCY SIGNAL - CONDITIONAL EMERGENCY SIGNAL According to the PoP, they have to be fast. They can be executed without conflicting to the actions of other pending/concurrently executing orders (e.g. STOP vs. START). This patch introduces a new capability that will - when enabled - forward all but the mentioned SIGP orders to user space. The instruction counters in the kernel are still updated. Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/kvm_host.h1
-rw-r--r--arch/s390/kvm/kvm-s390.c5
-rw-r--r--arch/s390/kvm/sigp.c49
3 files changed, 55 insertions, 0 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index b6170520380b..a2dcd0e099f7 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -521,6 +521,7 @@ struct kvm_arch{
521 int use_irqchip; 521 int use_irqchip;
522 int use_cmma; 522 int use_cmma;
523 int user_cpu_state_ctrl; 523 int user_cpu_state_ctrl;
524 int user_sigp;
524 struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS]; 525 struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS];
525 wait_queue_head_t ipte_wq; 526 wait_queue_head_t ipte_wq;
526 int ipte_lock_count; 527 int ipte_lock_count;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index bfb2b990da9b..3677b8ca647f 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -166,6 +166,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
166 case KVM_CAP_S390_IRQCHIP: 166 case KVM_CAP_S390_IRQCHIP:
167 case KVM_CAP_VM_ATTRIBUTES: 167 case KVM_CAP_VM_ATTRIBUTES:
168 case KVM_CAP_MP_STATE: 168 case KVM_CAP_MP_STATE:
169 case KVM_CAP_S390_USER_SIGP:
169 r = 1; 170 r = 1;
170 break; 171 break;
171 case KVM_CAP_NR_VCPUS: 172 case KVM_CAP_NR_VCPUS:
@@ -254,6 +255,10 @@ static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
254 kvm->arch.use_irqchip = 1; 255 kvm->arch.use_irqchip = 1;
255 r = 0; 256 r = 0;
256 break; 257 break;
258 case KVM_CAP_S390_USER_SIGP:
259 kvm->arch.user_sigp = 1;
260 r = 0;
261 break;
257 default: 262 default:
258 r = -EINVAL; 263 r = -EINVAL;
259 break; 264 break;
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 1524be9120ad..23b1e86b2122 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -371,6 +371,53 @@ static int handle_sigp_dst(struct kvm_vcpu *vcpu, u8 order_code,
371 return rc; 371 return rc;
372} 372}
373 373
374static int handle_sigp_order_in_user_space(struct kvm_vcpu *vcpu, u8 order_code)
375{
376 if (!vcpu->kvm->arch.user_sigp)
377 return 0;
378
379 switch (order_code) {
380 case SIGP_SENSE:
381 case SIGP_EXTERNAL_CALL:
382 case SIGP_EMERGENCY_SIGNAL:
383 case SIGP_COND_EMERGENCY_SIGNAL:
384 case SIGP_SENSE_RUNNING:
385 return 0;
386 /* update counters as we're directly dropping to user space */
387 case SIGP_STOP:
388 vcpu->stat.instruction_sigp_stop++;
389 break;
390 case SIGP_STOP_AND_STORE_STATUS:
391 vcpu->stat.instruction_sigp_stop_store_status++;
392 break;
393 case SIGP_STORE_STATUS_AT_ADDRESS:
394 vcpu->stat.instruction_sigp_store_status++;
395 break;
396 case SIGP_SET_PREFIX:
397 vcpu->stat.instruction_sigp_prefix++;
398 break;
399 case SIGP_START:
400 vcpu->stat.instruction_sigp_start++;
401 break;
402 case SIGP_RESTART:
403 vcpu->stat.instruction_sigp_restart++;
404 break;
405 case SIGP_INITIAL_CPU_RESET:
406 vcpu->stat.instruction_sigp_init_cpu_reset++;
407 break;
408 case SIGP_CPU_RESET:
409 vcpu->stat.instruction_sigp_cpu_reset++;
410 break;
411 default:
412 vcpu->stat.instruction_sigp_unknown++;
413 }
414
415 VCPU_EVENT(vcpu, 4, "sigp order %u: completely handled in user space",
416 order_code);
417
418 return 1;
419}
420
374int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) 421int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
375{ 422{
376 int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; 423 int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
@@ -385,6 +432,8 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
385 return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP); 432 return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
386 433
387 order_code = kvm_s390_get_base_disp_rs(vcpu); 434 order_code = kvm_s390_get_base_disp_rs(vcpu);
435 if (handle_sigp_order_in_user_space(vcpu, order_code))
436 return -EOPNOTSUPP;
388 437
389 if (r1 % 2) 438 if (r1 % 2)
390 parameter = vcpu->run->s.regs.gprs[r1]; 439 parameter = vcpu->run->s.regs.gprs[r1];