diff options
author | David Hildenbrand <dahi@linux.vnet.ibm.com> | 2014-10-09 08:10:13 -0400 |
---|---|---|
committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2015-01-23 07:25:37 -0500 |
commit | 2444b352c3acf54897b0e2803a7c4e66699f9f43 (patch) | |
tree | 42490c1860791c4d674fe8c40aaf77c4d0407ab7 | |
parent | 9fbd80828cef1b1bba5a293609a021047bb86a7e (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.txt | 20 | ||||
-rw-r--r-- | arch/s390/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 5 | ||||
-rw-r--r-- | arch/s390/kvm/sigp.c | 49 | ||||
-rw-r--r-- | include/uapi/linux/kvm.h | 1 |
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. | |||
3225 | If the hcall number specified is not one that has an in-kernel | 3225 | If the hcall number specified is not one that has an in-kernel |
3226 | implementation, the KVM_ENABLE_CAP ioctl will fail with an EINVAL | 3226 | implementation, the KVM_ENABLE_CAP ioctl will fail with an EINVAL |
3227 | error. | 3227 | error. |
3228 | |||
3229 | 7.2 KVM_CAP_S390_USER_SIGP | ||
3230 | |||
3231 | Architectures: s390 | ||
3232 | Parameters: none | ||
3233 | |||
3234 | This capability controls which SIGP orders will be handled completely in user | ||
3235 | space. With this capability enabled, all fast orders will be handled completely | ||
3236 | in the kernel: | ||
3237 | - SENSE | ||
3238 | - SENSE RUNNING | ||
3239 | - EXTERNAL CALL | ||
3240 | - EMERGENCY SIGNAL | ||
3241 | - CONDITIONAL EMERGENCY SIGNAL | ||
3242 | |||
3243 | All other orders will be handled completely in user space. | ||
3244 | |||
3245 | Only privileged operation exceptions will be checked for in the kernel (or even | ||
3246 | in the hardware prior to interception). If this capability is not enabled, the | ||
3247 | old 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 | ||
374 | static 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 | |||
374 | int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) | 421 | int 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 | ||