aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCollin L. Walling <walling@linux.vnet.ibm.com>2016-07-26 15:29:44 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2017-08-29 09:15:54 -0400
commit8fa1696ea78162ca3112a26879d9379483443c85 (patch)
tree3930f3b5b7b71e39dd8117c87704392b7badc840
parentb697e435aeee99b7f5b2d8f8dbb51f791be99b16 (diff)
KVM: s390: Multiple Epoch Facility support
Allow for the enablement of MEF and the support for the extended epoch in SIE and VSIE for the extended guest TOD-Clock. A new interface is used for getting/setting a guest's extended TOD-Clock that uses a single ioctl invocation, KVM_S390_VM_TOD_EXT. Since the host time is a moving target that might see an epoch switch or STP sync checks we need an atomic ioctl and cannot use the exisiting two interfaces. The old method of getting and setting the guest TOD-Clock is still retained and is used when the old ioctls are called. Signed-off-by: Collin L. Walling <walling@linux.vnet.ibm.com> Reviewed-by: Janosch Frank <frankja@linux.vnet.ibm.com> Reviewed-by: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com> Reviewed-by: Jason J. Herne <jjherne@linux.vnet.ibm.com> Reviewed-by: Cornelia Huck <cohuck@redhat.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
-rw-r--r--Documentation/virtual/kvm/devices/vm.txt14
-rw-r--r--arch/s390/include/asm/kvm_host.h6
-rw-r--r--arch/s390/include/uapi/asm/kvm.h6
-rw-r--r--arch/s390/kvm/kvm-s390.c101
-rw-r--r--arch/s390/kvm/kvm-s390.h2
-rw-r--r--arch/s390/kvm/vsie.c10
-rw-r--r--arch/s390/tools/gen_facilities.c1
7 files changed, 138 insertions, 2 deletions
diff --git a/Documentation/virtual/kvm/devices/vm.txt b/Documentation/virtual/kvm/devices/vm.txt
index 903fc926860b..95ca68d663a4 100644
--- a/Documentation/virtual/kvm/devices/vm.txt
+++ b/Documentation/virtual/kvm/devices/vm.txt
@@ -176,7 +176,8 @@ Architectures: s390
176 176
1773.1. ATTRIBUTE: KVM_S390_VM_TOD_HIGH 1773.1. ATTRIBUTE: KVM_S390_VM_TOD_HIGH
178 178
179Allows user space to set/get the TOD clock extension (u8). 179Allows user space to set/get the TOD clock extension (u8) (superseded by
180KVM_S390_VM_TOD_EXT).
180 181
181Parameters: address of a buffer in user space to store the data (u8) to 182Parameters: address of a buffer in user space to store the data (u8) to
182Returns: -EFAULT if the given address is not accessible from kernel space 183Returns: -EFAULT if the given address is not accessible from kernel space
@@ -190,6 +191,17 @@ the POP (u64).
190Parameters: address of a buffer in user space to store the data (u64) to 191Parameters: address of a buffer in user space to store the data (u64) to
191Returns: -EFAULT if the given address is not accessible from kernel space 192Returns: -EFAULT if the given address is not accessible from kernel space
192 193
1943.3. ATTRIBUTE: KVM_S390_VM_TOD_EXT
195Allows user space to set/get bits 0-63 of the TOD clock register as defined in
196the POP (u64). If the guest CPU model supports the TOD clock extension (u8), it
197also allows user space to get/set it. If the guest CPU model does not support
198it, it is stored as 0 and not allowed to be set to a value != 0.
199
200Parameters: address of a buffer in user space to store the data
201 (kvm_s390_vm_tod_clock) to
202Returns: -EFAULT if the given address is not accessible from kernel space
203 -EINVAL if setting the TOD clock extension to != 0 is not supported
204
1934. GROUP: KVM_S390_VM_CRYPTO 2054. GROUP: KVM_S390_VM_CRYPTO
194Architectures: s390 206Architectures: s390
195 207
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index a409d5991934..51375e766e90 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -226,7 +226,9 @@ struct kvm_s390_sie_block {
226#define ECB3_RI 0x01 226#define ECB3_RI 0x01
227 __u8 ecb3; /* 0x0063 */ 227 __u8 ecb3; /* 0x0063 */
228 __u32 scaol; /* 0x0064 */ 228 __u32 scaol; /* 0x0064 */
229 __u8 reserved68[4]; /* 0x0068 */ 229 __u8 reserved68; /* 0x0068 */
230 __u8 epdx; /* 0x0069 */
231 __u8 reserved6a[2]; /* 0x006a */
230 __u32 todpr; /* 0x006c */ 232 __u32 todpr; /* 0x006c */
231 __u8 reserved70[16]; /* 0x0070 */ 233 __u8 reserved70[16]; /* 0x0070 */
232 __u64 mso; /* 0x0080 */ 234 __u64 mso; /* 0x0080 */
@@ -265,6 +267,7 @@ struct kvm_s390_sie_block {
265 __u64 cbrlo; /* 0x01b8 */ 267 __u64 cbrlo; /* 0x01b8 */
266 __u8 reserved1c0[8]; /* 0x01c0 */ 268 __u8 reserved1c0[8]; /* 0x01c0 */
267#define ECD_HOSTREGMGMT 0x20000000 269#define ECD_HOSTREGMGMT 0x20000000
270#define ECD_MEF 0x08000000
268 __u32 ecd; /* 0x01c8 */ 271 __u32 ecd; /* 0x01c8 */
269 __u8 reserved1cc[18]; /* 0x01cc */ 272 __u8 reserved1cc[18]; /* 0x01cc */
270 __u64 pp; /* 0x01de */ 273 __u64 pp; /* 0x01de */
@@ -739,6 +742,7 @@ struct kvm_arch{
739 struct kvm_s390_cpu_model model; 742 struct kvm_s390_cpu_model model;
740 struct kvm_s390_crypto crypto; 743 struct kvm_s390_crypto crypto;
741 struct kvm_s390_vsie vsie; 744 struct kvm_s390_vsie vsie;
745 u8 epdx;
742 u64 epoch; 746 u64 epoch;
743 struct kvm_s390_migration_state *migration_state; 747 struct kvm_s390_migration_state *migration_state;
744 /* subset of available cpu features enabled by user space */ 748 /* subset of available cpu features enabled by user space */
diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h
index 69d09c39bbcd..cd7359e23d86 100644
--- a/arch/s390/include/uapi/asm/kvm.h
+++ b/arch/s390/include/uapi/asm/kvm.h
@@ -88,6 +88,12 @@ struct kvm_s390_io_adapter_req {
88/* kvm attributes for KVM_S390_VM_TOD */ 88/* kvm attributes for KVM_S390_VM_TOD */
89#define KVM_S390_VM_TOD_LOW 0 89#define KVM_S390_VM_TOD_LOW 0
90#define KVM_S390_VM_TOD_HIGH 1 90#define KVM_S390_VM_TOD_HIGH 1
91#define KVM_S390_VM_TOD_EXT 2
92
93struct kvm_s390_vm_tod_clock {
94 __u8 epoch_idx;
95 __u64 tod;
96};
91 97
92/* kvm attributes for KVM_S390_VM_CPU_MODEL */ 98/* kvm attributes for KVM_S390_VM_CPU_MODEL */
93/* processor related attributes are r/w */ 99/* processor related attributes are r/w */
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index af09d3437631..e65b7637cc45 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -130,6 +130,12 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
130 { NULL } 130 { NULL }
131}; 131};
132 132
133struct kvm_s390_tod_clock_ext {
134 __u8 epoch_idx;
135 __u64 tod;
136 __u8 reserved[7];
137} __packed;
138
133/* allow nested virtualization in KVM (if enabled by user space) */ 139/* allow nested virtualization in KVM (if enabled by user space) */
134static int nested; 140static int nested;
135module_param(nested, int, S_IRUGO); 141module_param(nested, int, S_IRUGO);
@@ -874,6 +880,26 @@ static int kvm_s390_vm_get_migration(struct kvm *kvm,
874 return 0; 880 return 0;
875} 881}
876 882
883static int kvm_s390_set_tod_ext(struct kvm *kvm, struct kvm_device_attr *attr)
884{
885 struct kvm_s390_vm_tod_clock gtod;
886
887 if (copy_from_user(&gtod, (void __user *)attr->addr, sizeof(gtod)))
888 return -EFAULT;
889
890 if (test_kvm_facility(kvm, 139))
891 kvm_s390_set_tod_clock_ext(kvm, &gtod);
892 else if (gtod.epoch_idx == 0)
893 kvm_s390_set_tod_clock(kvm, gtod.tod);
894 else
895 return -EINVAL;
896
897 VM_EVENT(kvm, 3, "SET: TOD extension: 0x%x, TOD base: 0x%llx",
898 gtod.epoch_idx, gtod.tod);
899
900 return 0;
901}
902
877static int kvm_s390_set_tod_high(struct kvm *kvm, struct kvm_device_attr *attr) 903static int kvm_s390_set_tod_high(struct kvm *kvm, struct kvm_device_attr *attr)
878{ 904{
879 u8 gtod_high; 905 u8 gtod_high;
@@ -909,6 +935,9 @@ static int kvm_s390_set_tod(struct kvm *kvm, struct kvm_device_attr *attr)
909 return -EINVAL; 935 return -EINVAL;
910 936
911 switch (attr->attr) { 937 switch (attr->attr) {
938 case KVM_S390_VM_TOD_EXT:
939 ret = kvm_s390_set_tod_ext(kvm, attr);
940 break;
912 case KVM_S390_VM_TOD_HIGH: 941 case KVM_S390_VM_TOD_HIGH:
913 ret = kvm_s390_set_tod_high(kvm, attr); 942 ret = kvm_s390_set_tod_high(kvm, attr);
914 break; 943 break;
@@ -922,6 +951,43 @@ static int kvm_s390_set_tod(struct kvm *kvm, struct kvm_device_attr *attr)
922 return ret; 951 return ret;
923} 952}
924 953
954static void kvm_s390_get_tod_clock_ext(struct kvm *kvm,
955 struct kvm_s390_vm_tod_clock *gtod)
956{
957 struct kvm_s390_tod_clock_ext htod;
958
959 preempt_disable();
960
961 get_tod_clock_ext((char *)&htod);
962
963 gtod->tod = htod.tod + kvm->arch.epoch;
964 gtod->epoch_idx = htod.epoch_idx + kvm->arch.epdx;
965
966 if (gtod->tod < htod.tod)
967 gtod->epoch_idx += 1;
968
969 preempt_enable();
970}
971
972static int kvm_s390_get_tod_ext(struct kvm *kvm, struct kvm_device_attr *attr)
973{
974 struct kvm_s390_vm_tod_clock gtod;
975
976 memset(&gtod, 0, sizeof(gtod));
977
978 if (test_kvm_facility(kvm, 139))
979 kvm_s390_get_tod_clock_ext(kvm, &gtod);
980 else
981 gtod.tod = kvm_s390_get_tod_clock_fast(kvm);
982
983 if (copy_to_user((void __user *)attr->addr, &gtod, sizeof(gtod)))
984 return -EFAULT;
985
986 VM_EVENT(kvm, 3, "QUERY: TOD extension: 0x%x, TOD base: 0x%llx",
987 gtod.epoch_idx, gtod.tod);
988 return 0;
989}
990
925static int kvm_s390_get_tod_high(struct kvm *kvm, struct kvm_device_attr *attr) 991static int kvm_s390_get_tod_high(struct kvm *kvm, struct kvm_device_attr *attr)
926{ 992{
927 u8 gtod_high = 0; 993 u8 gtod_high = 0;
@@ -954,6 +1020,9 @@ static int kvm_s390_get_tod(struct kvm *kvm, struct kvm_device_attr *attr)
954 return -EINVAL; 1020 return -EINVAL;
955 1021
956 switch (attr->attr) { 1022 switch (attr->attr) {
1023 case KVM_S390_VM_TOD_EXT:
1024 ret = kvm_s390_get_tod_ext(kvm, attr);
1025 break;
957 case KVM_S390_VM_TOD_HIGH: 1026 case KVM_S390_VM_TOD_HIGH:
958 ret = kvm_s390_get_tod_high(kvm, attr); 1027 ret = kvm_s390_get_tod_high(kvm, attr);
959 break; 1028 break;
@@ -2369,6 +2438,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
2369 vcpu->arch.sie_block->eca |= ECA_VX; 2438 vcpu->arch.sie_block->eca |= ECA_VX;
2370 vcpu->arch.sie_block->ecd |= ECD_HOSTREGMGMT; 2439 vcpu->arch.sie_block->ecd |= ECD_HOSTREGMGMT;
2371 } 2440 }
2441 if (test_kvm_facility(vcpu->kvm, 139))
2442 vcpu->arch.sie_block->ecd |= ECD_MEF;
2443
2372 vcpu->arch.sie_block->sdnxo = ((unsigned long) &vcpu->run->s.regs.sdnx) 2444 vcpu->arch.sie_block->sdnxo = ((unsigned long) &vcpu->run->s.regs.sdnx)
2373 | SDNXC; 2445 | SDNXC;
2374 vcpu->arch.sie_block->riccbd = (unsigned long) &vcpu->run->s.regs.riccb; 2446 vcpu->arch.sie_block->riccbd = (unsigned long) &vcpu->run->s.regs.riccb;
@@ -2855,6 +2927,35 @@ retry:
2855 return 0; 2927 return 0;
2856} 2928}
2857 2929
2930void kvm_s390_set_tod_clock_ext(struct kvm *kvm,
2931 const struct kvm_s390_vm_tod_clock *gtod)
2932{
2933 struct kvm_vcpu *vcpu;
2934 struct kvm_s390_tod_clock_ext htod;
2935 int i;
2936
2937 mutex_lock(&kvm->lock);
2938 preempt_disable();
2939
2940 get_tod_clock_ext((char *)&htod);
2941
2942 kvm->arch.epoch = gtod->tod - htod.tod;
2943 kvm->arch.epdx = gtod->epoch_idx - htod.epoch_idx;
2944
2945 if (kvm->arch.epoch > gtod->tod)
2946 kvm->arch.epdx -= 1;
2947
2948 kvm_s390_vcpu_block_all(kvm);
2949 kvm_for_each_vcpu(i, vcpu, kvm) {
2950 vcpu->arch.sie_block->epoch = kvm->arch.epoch;
2951 vcpu->arch.sie_block->epdx = kvm->arch.epdx;
2952 }
2953
2954 kvm_s390_vcpu_unblock_all(kvm);
2955 preempt_enable();
2956 mutex_unlock(&kvm->lock);
2957}
2958
2858void kvm_s390_set_tod_clock(struct kvm *kvm, u64 tod) 2959void kvm_s390_set_tod_clock(struct kvm *kvm, u64 tod)
2859{ 2960{
2860 struct kvm_vcpu *vcpu; 2961 struct kvm_vcpu *vcpu;
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 6fedc8bc7a37..9f8fdd7b2311 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -272,6 +272,8 @@ int kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu);
272int handle_sthyi(struct kvm_vcpu *vcpu); 272int handle_sthyi(struct kvm_vcpu *vcpu);
273 273
274/* implemented in kvm-s390.c */ 274/* implemented in kvm-s390.c */
275void kvm_s390_set_tod_clock_ext(struct kvm *kvm,
276 const struct kvm_s390_vm_tod_clock *gtod);
275void kvm_s390_set_tod_clock(struct kvm *kvm, u64 tod); 277void kvm_s390_set_tod_clock(struct kvm *kvm, u64 tod);
276long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable); 278long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable);
277int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr); 279int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr);
diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c
index 715c19c45d9a..d471910bd9ea 100644
--- a/arch/s390/kvm/vsie.c
+++ b/arch/s390/kvm/vsie.c
@@ -349,6 +349,9 @@ static int shadow_scb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
349 scb_s->eca |= scb_o->eca & ECA_IB; 349 scb_s->eca |= scb_o->eca & ECA_IB;
350 if (test_kvm_cpu_feat(vcpu->kvm, KVM_S390_VM_CPU_FEAT_CEI)) 350 if (test_kvm_cpu_feat(vcpu->kvm, KVM_S390_VM_CPU_FEAT_CEI))
351 scb_s->eca |= scb_o->eca & ECA_CEI; 351 scb_s->eca |= scb_o->eca & ECA_CEI;
352 /* Epoch Extension */
353 if (test_kvm_facility(vcpu->kvm, 139))
354 scb_s->ecd |= scb_o->ecd & ECD_MEF;
352 355
353 prepare_ibc(vcpu, vsie_page); 356 prepare_ibc(vcpu, vsie_page);
354 rc = shadow_crycb(vcpu, vsie_page); 357 rc = shadow_crycb(vcpu, vsie_page);
@@ -919,6 +922,13 @@ static void register_shadow_scb(struct kvm_vcpu *vcpu,
919 */ 922 */
920 preempt_disable(); 923 preempt_disable();
921 scb_s->epoch += vcpu->kvm->arch.epoch; 924 scb_s->epoch += vcpu->kvm->arch.epoch;
925
926 if (scb_s->ecd & ECD_MEF) {
927 scb_s->epdx += vcpu->kvm->arch.epdx;
928 if (scb_s->epoch < vcpu->kvm->arch.epoch)
929 scb_s->epdx += 1;
930 }
931
922 preempt_enable(); 932 preempt_enable();
923} 933}
924 934
diff --git a/arch/s390/tools/gen_facilities.c b/arch/s390/tools/gen_facilities.c
index 181db5b8f8b3..601bfcf99e2a 100644
--- a/arch/s390/tools/gen_facilities.c
+++ b/arch/s390/tools/gen_facilities.c
@@ -81,6 +81,7 @@ static struct facility_def facility_defs[] = {
81 130, /* instruction-execution-protection */ 81 130, /* instruction-execution-protection */
82 131, /* enhanced-SOP 2 and side-effect */ 82 131, /* enhanced-SOP 2 and side-effect */
83 138, /* configuration z/architecture mode (czam) */ 83 138, /* configuration z/architecture mode (czam) */
84 139, /* multiple epoch facility */
84 146, /* msa extension 8 */ 85 146, /* msa extension 8 */
85 -1 /* END */ 86 -1 /* END */
86 } 87 }