aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2012-12-20 09:32:12 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2013-01-07 16:53:43 -0500
commitfa6b7fe9928d50444c29b29c8563746c6b0c6299 (patch)
tree0be284cf322eb82eefdb3df2743740e5578ba5c4
parentd6712df95bcfea597fc3ea2405ec13e8b69a7b8c (diff)
KVM: s390: Add support for channel I/O instructions.
Add a new capability, KVM_CAP_S390_CSS_SUPPORT, which will pass intercepts for channel I/O instructions to userspace. Only I/O instructions interacting with I/O interrupts need to be handled in-kernel: - TEST PENDING INTERRUPTION (tpi) dequeues and stores pending interrupts entirely in-kernel. - TEST SUBCHANNEL (tsch) dequeues pending interrupts in-kernel and exits via KVM_EXIT_S390_TSCH to userspace for subchannel- related processing. Reviewed-by: Marcelo Tosatti <mtosatti@redhat.com> Reviewed-by: Alexander Graf <agraf@suse.de> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r--Documentation/virtual/kvm/api.txt30
-rw-r--r--arch/s390/include/asm/kvm_host.h1
-rw-r--r--arch/s390/kvm/intercept.c1
-rw-r--r--arch/s390/kvm/interrupt.c37
-rw-r--r--arch/s390/kvm/kvm-s390.c12
-rw-r--r--arch/s390/kvm/kvm-s390.h2
-rw-r--r--arch/s390/kvm/priv.c91
-rw-r--r--arch/s390/kvm/trace-s390.h20
-rw-r--r--include/trace/events/kvm.h2
-rw-r--r--include/uapi/linux/kvm.h11
10 files changed, 202 insertions, 5 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 73bd159c5559..f2d6391178b9 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2350,6 +2350,22 @@ The possible hypercalls are defined in the Power Architecture Platform
2350Requirements (PAPR) document available from www.power.org (free 2350Requirements (PAPR) document available from www.power.org (free
2351developer registration required to access it). 2351developer registration required to access it).
2352 2352
2353 /* KVM_EXIT_S390_TSCH */
2354 struct {
2355 __u16 subchannel_id;
2356 __u16 subchannel_nr;
2357 __u32 io_int_parm;
2358 __u32 io_int_word;
2359 __u32 ipb;
2360 __u8 dequeued;
2361 } s390_tsch;
2362
2363s390 specific. This exit occurs when KVM_CAP_S390_CSS_SUPPORT has been enabled
2364and TEST SUBCHANNEL was intercepted. If dequeued is set, a pending I/O
2365interrupt for the target subchannel has been dequeued and subchannel_id,
2366subchannel_nr, io_int_parm and io_int_word contain the parameters for that
2367interrupt. ipb is needed for instruction parameter decoding.
2368
2353 /* Fix the size of the union. */ 2369 /* Fix the size of the union. */
2354 char padding[256]; 2370 char padding[256];
2355 }; 2371 };
@@ -2471,3 +2487,17 @@ For mmu types KVM_MMU_FSL_BOOKE_NOHV and KVM_MMU_FSL_BOOKE_HV:
2471 where "num_sets" is the tlb_sizes[] value divided by the tlb_ways[] value. 2487 where "num_sets" is the tlb_sizes[] value divided by the tlb_ways[] value.
2472 - The tsize field of mas1 shall be set to 4K on TLB0, even though the 2488 - The tsize field of mas1 shall be set to 4K on TLB0, even though the
2473 hardware ignores this value for TLB0. 2489 hardware ignores this value for TLB0.
2490
24916.4 KVM_CAP_S390_CSS_SUPPORT
2492
2493Architectures: s390
2494Parameters: none
2495Returns: 0 on success; -1 on error
2496
2497This capability enables support for handling of channel I/O instructions.
2498
2499TEST PENDING INTERRUPTION and the interrupt portion of TEST SUBCHANNEL are
2500handled in-kernel, while the other I/O instructions are passed to userspace.
2501
2502When this capability is enabled, KVM_EXIT_S390_TSCH will occur on TEST
2503SUBCHANNEL intercepts.
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 29363d155cd5..16bd5d169cdb 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -262,6 +262,7 @@ struct kvm_arch{
262 debug_info_t *dbf; 262 debug_info_t *dbf;
263 struct kvm_s390_float_interrupt float_int; 263 struct kvm_s390_float_interrupt float_int;
264 struct gmap *gmap; 264 struct gmap *gmap;
265 int css_support;
265}; 266};
266 267
267extern int sie64a(struct kvm_s390_sie_block *, u64 *); 268extern int sie64a(struct kvm_s390_sie_block *, u64 *);
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index 71af87dbb42c..f26ff1e31bdb 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -264,6 +264,7 @@ static const intercept_handler_t intercept_funcs[] = {
264 [0x0C >> 2] = handle_instruction_and_prog, 264 [0x0C >> 2] = handle_instruction_and_prog,
265 [0x10 >> 2] = handle_noop, 265 [0x10 >> 2] = handle_noop,
266 [0x14 >> 2] = handle_noop, 266 [0x14 >> 2] = handle_noop,
267 [0x18 >> 2] = handle_noop,
267 [0x1C >> 2] = kvm_s390_handle_wait, 268 [0x1C >> 2] = kvm_s390_handle_wait,
268 [0x20 >> 2] = handle_validity, 269 [0x20 >> 2] = handle_validity,
269 [0x28 >> 2] = handle_stop, 270 [0x28 >> 2] = handle_stop,
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index b3b4748485ee..9a128357fd15 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -709,6 +709,43 @@ int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
709 return 0; 709 return 0;
710} 710}
711 711
712struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
713 u64 cr6, u64 schid)
714{
715 struct kvm_s390_float_interrupt *fi;
716 struct kvm_s390_interrupt_info *inti, *iter;
717
718 if ((!schid && !cr6) || (schid && cr6))
719 return NULL;
720 mutex_lock(&kvm->lock);
721 fi = &kvm->arch.float_int;
722 spin_lock(&fi->lock);
723 inti = NULL;
724 list_for_each_entry(iter, &fi->list, list) {
725 if (!is_ioint(iter->type))
726 continue;
727 if (cr6 && ((cr6 & iter->io.io_int_word) == 0))
728 continue;
729 if (schid) {
730 if (((schid & 0x00000000ffff0000) >> 16) !=
731 iter->io.subchannel_id)
732 continue;
733 if ((schid & 0x000000000000ffff) !=
734 iter->io.subchannel_nr)
735 continue;
736 }
737 inti = iter;
738 break;
739 }
740 if (inti)
741 list_del_init(&inti->list);
742 if (list_empty(&fi->list))
743 atomic_set(&fi->active, 0);
744 spin_unlock(&fi->lock);
745 mutex_unlock(&kvm->lock);
746 return inti;
747}
748
712int kvm_s390_inject_vm(struct kvm *kvm, 749int kvm_s390_inject_vm(struct kvm *kvm,
713 struct kvm_s390_interrupt *s390int) 750 struct kvm_s390_interrupt *s390int)
714{ 751{
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 5ff26033825c..5b01f0953900 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -141,6 +141,7 @@ int kvm_dev_ioctl_check_extension(long ext)
141 case KVM_CAP_SYNC_REGS: 141 case KVM_CAP_SYNC_REGS:
142 case KVM_CAP_ONE_REG: 142 case KVM_CAP_ONE_REG:
143 case KVM_CAP_ENABLE_CAP: 143 case KVM_CAP_ENABLE_CAP:
144 case KVM_CAP_S390_CSS_SUPPORT:
144 r = 1; 145 r = 1;
145 break; 146 break;
146 case KVM_CAP_NR_VCPUS: 147 case KVM_CAP_NR_VCPUS:
@@ -235,6 +236,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
235 if (!kvm->arch.gmap) 236 if (!kvm->arch.gmap)
236 goto out_nogmap; 237 goto out_nogmap;
237 } 238 }
239
240 kvm->arch.css_support = 0;
241
238 return 0; 242 return 0;
239out_nogmap: 243out_nogmap:
240 debug_unregister(kvm->arch.dbf); 244 debug_unregister(kvm->arch.dbf);
@@ -658,6 +662,7 @@ rerun_vcpu:
658 case KVM_EXIT_INTR: 662 case KVM_EXIT_INTR:
659 case KVM_EXIT_S390_RESET: 663 case KVM_EXIT_S390_RESET:
660 case KVM_EXIT_S390_UCONTROL: 664 case KVM_EXIT_S390_UCONTROL:
665 case KVM_EXIT_S390_TSCH:
661 break; 666 break;
662 default: 667 default:
663 BUG(); 668 BUG();
@@ -818,6 +823,13 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
818 return -EINVAL; 823 return -EINVAL;
819 824
820 switch (cap->cap) { 825 switch (cap->cap) {
826 case KVM_CAP_S390_CSS_SUPPORT:
827 if (!vcpu->kvm->arch.css_support) {
828 vcpu->kvm->arch.css_support = 1;
829 trace_kvm_s390_enable_css(vcpu->kvm);
830 }
831 r = 0;
832 break;
821 default: 833 default:
822 r = -EINVAL; 834 r = -EINVAL;
823 break; 835 break;
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 211b340385a7..3e05deff21b6 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -113,6 +113,8 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
113 struct kvm_s390_interrupt *s390int); 113 struct kvm_s390_interrupt *s390int);
114int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code);