aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJens Freimann <jfrei@linux.vnet.ibm.com>2014-07-28 09:37:58 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-11-28 07:59:01 -0500
commit0146a7b0b0e8691e74d6c8d1d82ad40e3d526ac2 (patch)
treef3a96ff1f0698c3de9762951ffbf007716dfde8c
parent9fcf93b5de063e5cadb95a7bd0130bf73edcd3b5 (diff)
KVM: s390: refactor interrupt injection code
In preparation for the rework of the local interrupt injection code, factor out injection routines from kvm_s390_inject_vcpu(). Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com> Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
-rw-r--r--arch/s390/kvm/interrupt.c221
1 files changed, 167 insertions, 54 deletions
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index ead52bfb4c1d..8f50f8ccced3 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -719,6 +719,16 @@ int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu)
719 return rc; 719 return rc;
720} 720}
721 721
722static int __inject_prog_irq(struct kvm_vcpu *vcpu,
723 struct kvm_s390_interrupt_info *inti)
724{
725 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
726
727 list_add(&inti->list, &li->list);
728 atomic_set(&li->active, 1);
729 return 0;
730}
731
722int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code) 732int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
723{ 733{
724 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; 734 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
@@ -746,6 +756,7 @@ int kvm_s390_inject_prog_irq(struct kvm_vcpu *vcpu,
746{ 756{
747 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; 757 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
748 struct kvm_s390_interrupt_info *inti; 758 struct kvm_s390_interrupt_info *inti;
759 int rc;
749 760
750 inti = kzalloc(sizeof(*inti), GFP_KERNEL); 761 inti = kzalloc(sizeof(*inti), GFP_KERNEL);
751 if (!inti) 762 if (!inti)
@@ -759,10 +770,133 @@ int kvm_s390_inject_prog_irq(struct kvm_vcpu *vcpu,
759 inti->type = KVM_S390_PROGRAM_INT; 770 inti->type = KVM_S390_PROGRAM_INT;
760 memcpy(&inti->pgm, pgm_info, sizeof(inti->pgm)); 771 memcpy(&inti->pgm, pgm_info, sizeof(inti->pgm));
761 spin_lock(&li->lock); 772 spin_lock(&li->lock);
762 list_add(&inti->list, &li->list); 773 rc = __inject_prog_irq(vcpu, inti);
763 atomic_set(&li->active, 1);
764 BUG_ON(waitqueue_active(li->wq)); 774 BUG_ON(waitqueue_active(li->wq));
765 spin_unlock(&li->lock); 775 spin_unlock(&li->lock);
776 return rc;
777}
778
779static int __inject_pfault_init(struct kvm_vcpu *vcpu,
780 struct kvm_s390_interrupt *s390int,
781 struct kvm_s390_interrupt_info *inti)
782{
783 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
784
785 inti->ext.ext_params2 = s390int->parm64;
786 list_add_tail(&inti->list, &li->list);
787 atomic_set(&li->active, 1);
788 atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
789 return 0;
790}
791
792static int __inject_extcall(struct kvm_vcpu *vcpu,
793 struct kvm_s390_interrupt *s390int,
794 struct kvm_s390_interrupt_info *inti)
795{
796 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
797
798 VCPU_EVENT(vcpu, 3, "inject: external call source-cpu:%u",
799 s390int->parm);
800 if (s390int->parm & 0xffff0000)
801 return -EINVAL;
802 inti->extcall.code = s390int->parm;
803 list_add_tail(&inti->list, &li->list);
804 atomic_set(&li->active, 1);
805 atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
806 return 0;
807}
808
809static int __inject_set_prefix(struct kvm_vcpu *vcpu,
810 struct kvm_s390_interrupt *s390int,
811 struct kvm_s390_interrupt_info *inti)
812{
813 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
814
815 VCPU_EVENT(vcpu, 3, "inject: set prefix to %x (from user)",
816 s390int->parm);
817 inti->prefix.address = s390int->parm;
818 list_add_tail(&inti->list, &li->list);
819 atomic_set(&li->active, 1);
820 return 0;
821}
822
823static int __inject_sigp_stop(struct kvm_vcpu *vcpu,
824 struct kvm_s390_interrupt *s390int,
825 struct kvm_s390_interrupt_info *inti)
826{
827 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
828
829 list_add_tail(&inti->list, &li->list);
830 atomic_set(&li->active, 1);
831 li->action_bits |= ACTION_STOP_ON_STOP;
832 return 0;
833}
834
835static int __inject_sigp_restart(struct kvm_vcpu *vcpu,
836 struct kvm_s390_interrupt *s390int,
837 struct kvm_s390_interrupt_info *inti)
838{
839 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
840
841 VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
842 list_add_tail(&inti->list, &li->list);
843 atomic_set(&li->active, 1);
844 return 0;
845}
846
847static int __inject_sigp_emergency(struct kvm_vcpu *vcpu,
848 struct kvm_s390_interrupt *s390int,
849 struct kvm_s390_interrupt_info *inti)
850{
851 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
852
853 VCPU_EVENT(vcpu, 3, "inject: emergency %u\n", s390int->parm);
854 if (s390int->parm & 0xffff0000)
855 return -EINVAL;
856 inti->emerg.code = s390int->parm;
857 list_add_tail(&inti->list, &li->list);
858 atomic_set(&li->active, 1);
859 atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
860 return 0;
861}
862
863static int __inject_mchk(struct kvm_vcpu *vcpu,
864 struct kvm_s390_interrupt *s390int,
865 struct kvm_s390_interrupt_info *inti)
866{
867 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
868
869 VCPU_EVENT(vcpu, 5, "inject: machine check parm64:%llx",
870 s390int->parm64);
871 inti->mchk.mcic = s390int->parm64;
872 list_add_tail(&inti->list, &li->list);
873 atomic_set(&li->active, 1);
874 return 0;
875}
876
877static int __inject_ckc(struct kvm_vcpu *vcpu,
878 struct kvm_s390_interrupt *s390int,
879 struct kvm_s390_interrupt_info *inti)
880{
881 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
882
883 VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
884 list_add_tail(&inti->list, &li->list);
885 atomic_set(&li->active, 1);
886 atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
887 return 0;
888}
889
890static int __inject_cpu_timer(struct kvm_vcpu *vcpu,
891 struct kvm_s390_interrupt *s390int,
892 struct kvm_s390_interrupt_info *inti)
893{
894 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
895
896 VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type);
897 list_add_tail(&inti->list, &li->list);
898 atomic_set(&li->active, 1);
899 atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
766 return 0; 900 return 0;
767} 901}
768 902
@@ -933,89 +1067,68 @@ void kvm_s390_reinject_io_int(struct kvm *kvm,
933int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, 1067int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
934 struct kvm_s390_interrupt *s390int) 1068 struct kvm_s390_interrupt *s390int)
935{ 1069{
936 struct kvm_s390_local_interrupt *li; 1070 struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
937 struct kvm_s390_interrupt_info *inti; 1071 struct kvm_s390_interrupt_info *inti;
1072 int rc;
938 1073
939 inti = kzalloc(sizeof(*inti), GFP_KERNEL); 1074 inti = kzalloc(sizeof(*inti), GFP_KERNEL);
940 if (!inti) 1075 if (!inti)
941 return -ENOMEM; 1076 return -ENOMEM;
942 1077
943 switch (s390int->type) { 1078 inti->type = s390int->type;
1079
1080 trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, s390int->type,
1081 s390int->parm, 0, 2);
1082 spin_lock(&li->lock);
1083 switch (inti->type) {
944 case KVM_S390_PROGRAM_INT: 1084 case KVM_S390_PROGRAM_INT:
945 if (s390int->parm & 0xffff0000) {
946 kfree(inti);
947 return -EINVAL;
948 }
949 inti->type = s390int->type;
950 inti->pgm.code = s390int->parm;
951 VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)", 1085 VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)",
952 s390int->parm); 1086 s390int->parm);
1087 inti->pgm.code = s390int->parm;
1088 if (s390int->parm & 0xffff0000)
1089 rc = -EINVAL;
1090 else
1091 rc = __inject_prog_irq(vcpu, inti);
953 break; 1092 break;
954 case KVM_S390_SIGP_SET_PREFIX: 1093 case KVM_S390_SIGP_SET_PREFIX:
955 inti->prefix.address = s390int->parm; 1094 rc = __inject_set_prefix(vcpu, s390int, inti);
956 inti->type = s390int->type;
957 VCPU_EVENT(vcpu, 3, "inject: set prefix to %x (from user)",
958 s390int->parm);
959 break; 1095 break;
960 case KVM_S390_SIGP_STOP: 1096 case KVM_S390_SIGP_STOP:
1097 rc = __inject_sigp_stop(vcpu, s390int, inti);
1098 break;
961 case KVM_S390_RESTART: 1099 case KVM_S390_RESTART:
1100 rc = __inject_sigp_restart(vcpu, s390int, inti);
1101 break;
962 case KVM_S390_INT_CLOCK_COMP: 1102 case KVM_S390_INT_CLOCK_COMP:
1103 rc = __inject_ckc(vcpu, s390int, inti);
1104 break;
963 case KVM_S390_INT_CPU_TIMER: 1105 case KVM_S390_INT_CPU_TIMER:
964 VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type); 1106 rc = __inject_cpu_timer(vcpu, s390int, inti);
965 inti->type = s390int->type;
966 break; 1107 break;
967 case KVM_S390_INT_EXTERNAL_CALL: 1108 case KVM_S390_INT_EXTERNAL_CALL:
968 if (s390int->parm & 0xffff0000) { 1109 rc = __inject_extcall(vcpu, s390int, inti);
969 kfree(inti);
970 return -EINVAL;
971 }
972 VCPU_EVENT(vcpu, 3, "inject: external call source-cpu:%u",
973 s390int->parm);
974 inti->type = s390int->type;
975 inti->extcall.code = s390int->parm;
976 break; 1110 break;
977 case KVM_S390_INT_EMERGENCY: 1111 case KVM_S390_INT_EMERGENCY:
978 if (s390int->parm & 0xffff0000) { 1112 rc = __inject_sigp_emergency(vcpu, s390int, inti);
979 kfree(inti);
980 return -EINVAL;
981 }
982 VCPU_EVENT(vcpu, 3, "inject: emergency %u\n", s390int->parm);
983 inti->type = s390int->type;
984 inti->emerg.code = s390int->parm;
985 break; 1113 break;
986 case KVM_S390_MCHK: 1114 case KVM_S390_MCHK:
987 VCPU_EVENT(vcpu, 5, "inject: machine check parm64:%llx", 1115 rc = __inject_mchk(vcpu, s390int, inti);
988 s390int->parm64);
989 inti->type = s390int->type;
990 inti->mchk.mcic = s390int->parm64;
991 break; 1116 break;
992 case KVM_S390_INT_PFAULT_INIT: 1117 case KVM_S390_INT_PFAULT_INIT:
993 inti->type = s390int->type; 1118 rc = __inject_pfault_init(vcpu, s390int, inti);
994 inti->ext.ext_params2 = s390int->parm64;
995 break; 1119 break;
996 case KVM_S390_INT_VIRTIO: 1120 case KVM_S390_INT_VIRTIO:
997 case KVM_S390_INT_SERVICE: 1121 case KVM_S390_INT_SERVICE:
998 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: 1122 case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
999 default: 1123 default:
1000 kfree(inti); 1124 rc = -EINVAL;
1001 return -EINVAL;
1002 } 1125 }
1003 trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, s390int->type, s390int->parm,
1004 s390int->parm64, 2);
1005
1006 li = &vcpu->arch.local_int;
1007 spin_lock(&li->lock);
1008 if (inti->type == KVM_S390_PROGRAM_INT)
1009 list_add(&inti->list, &li->list);
1010 else
1011 list_add_tail(&inti->list, &li->list);
1012 atomic_set(&li->active, 1);
1013 if (inti->type == KVM_S390_SIGP_STOP)
1014 li->action_bits |= ACTION_STOP_ON_STOP;
1015 atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
1016 spin_unlock(&li->lock); 1126 spin_unlock(&li->lock);
1017 kvm_s390_vcpu_wakeup(vcpu); 1127 if (!rc)
1018 return 0; 1128 kvm_s390_vcpu_wakeup(vcpu);
1129 else
1130 kfree(inti);
1131 return rc;
1019} 1132}
1020 1133
1021void kvm_s390_clear_float_irqs(struct kvm *kvm) 1134void kvm_s390_clear_float_irqs(struct kvm *kvm)