aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/virtual/kvm/api.txt20
-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
-rw-r--r--include/uapi/linux/kvm.h1
5 files changed, 76 insertions, 0 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 3ca6e0e9a769..df19837e94d4 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -3225,3 +3225,23 @@ userspace from doing that.
3225If the hcall number specified is not one that has an in-kernel 3225If the hcall number specified is not one that has an in-kernel
3226implementation, the KVM_ENABLE_CAP ioctl will fail with an EINVAL 3226implementation, the KVM_ENABLE_CAP ioctl will fail with an EINVAL
3227error. 3227error.
3228
32297.2 KVM_CAP_S390_USER_SIGP
3230
3231Architectures: s390
3232Parameters: none
3233
3234This capability controls which SIGP orders will be handled completely in user
3235space. With this capability enabled, all fast orders will be handled completely
3236in the kernel:
3237- SENSE
3238- SENSE RUNNING
3239- EXTERNAL CALL
3240- EMERGENCY SIGNAL
3241- CONDITIONAL EMERGENCY SIGNAL
3242
3243All other orders will be handled completely in user space.
3244
3245Only privileged operation exceptions will be checked for in the kernel (or even
3246in the hardware prior to interception). If this capability is not enabled, the
3247old way of handling SIGP orders is used (partially in kernel and user space).
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];
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index adc24a3fd23e..37f71c3040c3 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -759,6 +759,7 @@ struct kvm_ppc_smmu_info {
759#define KVM_CAP_PPC_FIXUP_HCALL 103 759#define KVM_CAP_PPC_FIXUP_HCALL 103
760#define KVM_CAP_PPC_ENABLE_HCALL 104 760#define KVM_CAP_PPC_ENABLE_HCALL 104
761#define KVM_CAP_CHECK_EXTENSION_VM 105 761#define KVM_CAP_CHECK_EXTENSION_VM 105
762#define KVM_CAP_S390_USER_SIGP 106
762 763
763#ifdef KVM_CAP_IRQ_ROUTING 764#ifdef KVM_CAP_IRQ_ROUTING
764 765