aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2016-05-18 10:03:47 -0400
committerChristian Borntraeger <borntraeger@de.ibm.com>2016-06-10 06:07:17 -0400
commit0a763c780b7cb830c250d00ead975778ab948f40 (patch)
treef7d7448dcaf8f74032a55dadc21db3f4ec4958e9 /arch/s390/kvm
parent1afd43e0fbba4a92effc22977e3a7e64213ee860 (diff)
KVM: s390: interface to query and configure cpu subfunctions
We have certain instructions that indicate available subfunctions via a query subfunction (crypto functions and ptff), or via a test bit function (plo). By exposing these "subfunction blocks" to user space, we allow user space to 1) query available subfunctions and make sure subfunctions won't get lost during migration - e.g. properly indicate them via a CPU model 2) change the subfunctions to be reported to the guest (even adding unavailable ones) This mechanism works just like the way we indicate the stfl(e) list to user space. This way, user space could even emulate some subfunctions in QEMU in the future. If this is ever applicable, we have to make sure later on, that unsupported subfunctions result in an intercept to QEMU. Please note that support to indicate them to the guest is still missing and requires hardware support. Usually, the IBC takes already care of these subfunctions for migration safety. QEMU should make sure to always set these bits properly according to the machine generation to be emulated. Available subfunctions are only valid in combination with STFLE bits retrieved via KVM_S390_VM_CPU_MACHINE and enabled via KVM_S390_VM_CPU_PROCESSOR. If the applicable bits are available, the indicated subfunctions are guaranteed to be correct. Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch/s390/kvm')
-rw-r--r--arch/s390/kvm/kvm-s390.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 2b5c14da3227..f746a35e3950 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -36,6 +36,8 @@
36#include <asm/switch_to.h> 36#include <asm/switch_to.h>
37#include <asm/isc.h> 37#include <asm/isc.h>
38#include <asm/sclp.h> 38#include <asm/sclp.h>
39#include <asm/cpacf.h>
40#include <asm/etr.h>
39#include "kvm-s390.h" 41#include "kvm-s390.h"
40#include "gaccess.h" 42#include "gaccess.h"
41 43
@@ -135,6 +137,8 @@ unsigned long kvm_s390_fac_list_mask_size(void)
135 137
136/* available cpu features supported by kvm */ 138/* available cpu features supported by kvm */
137static DECLARE_BITMAP(kvm_s390_available_cpu_feat, KVM_S390_VM_CPU_FEAT_NR_BITS); 139static DECLARE_BITMAP(kvm_s390_available_cpu_feat, KVM_S390_VM_CPU_FEAT_NR_BITS);
140/* available subfunctions indicated via query / "test bit" */
141static struct kvm_s390_vm_cpu_subfunc kvm_s390_available_subfunc;
138 142
139static struct gmap_notifier gmap_notifier; 143static struct gmap_notifier gmap_notifier;
140debug_info_t *kvm_s390_dbf; 144debug_info_t *kvm_s390_dbf;
@@ -198,8 +202,52 @@ static void allow_cpu_feat(unsigned long nr)
198 set_bit_inv(nr, kvm_s390_available_cpu_feat); 202 set_bit_inv(nr, kvm_s390_available_cpu_feat);
199} 203}
200 204
205static inline int plo_test_bit(unsigned char nr)
206{
207 register unsigned long r0 asm("0") = (unsigned long) nr | 0x100;
208 int cc = 3; /* subfunction not available */
209
210 asm volatile(
211 /* Parameter registers are ignored for "test bit" */
212 " plo 0,0,0,0(0)\n"
213 " ipm %0\n"
214 " srl %0,28\n"
215 : "=d" (cc)
216 : "d" (r0)
217 : "cc");
218 return cc == 0;
219}
220
201static void kvm_s390_cpu_feat_init(void) 221static void kvm_s390_cpu_feat_init(void)
202{ 222{
223 int i;
224
225 for (i = 0; i < 256; ++i) {
226 if (plo_test_bit(i))
227 kvm_s390_available_subfunc.plo[i >> 3] |= 0x80 >> (i & 7);
228 }
229
230 if (test_facility(28)) /* TOD-clock steering */
231 etr_ptff(kvm_s390_available_subfunc.ptff, ETR_PTFF_QAF);
232
233 if (test_facility(17)) { /* MSA */
234 __cpacf_query(CPACF_KMAC, kvm_s390_available_subfunc.kmac);
235 __cpacf_query(CPACF_KMC, kvm_s390_available_subfunc.kmc);
236 __cpacf_query(CPACF_KM, kvm_s390_available_subfunc.km);
237 __cpacf_query(CPACF_KIMD, kvm_s390_available_subfunc.kimd);
238 __cpacf_query(CPACF_KLMD, kvm_s390_available_subfunc.klmd);
239 }
240 if (test_facility(76)) /* MSA3 */
241 __cpacf_query(CPACF_PCKMO, kvm_s390_available_subfunc.pckmo);
242 if (test_facility(77)) { /* MSA4 */
243 __cpacf_query(CPACF_KMCTR, kvm_s390_available_subfunc.kmctr);
244 __cpacf_query(CPACF_KMF, kvm_s390_available_subfunc.kmf);
245 __cpacf_query(CPACF_KMO, kvm_s390_available_subfunc.kmo);
246 __cpacf_query(CPACF_PCC, kvm_s390_available_subfunc.pcc);
247 }
248 if (test_facility(57)) /* MSA5 */
249 __cpacf_query(CPACF_PPNO, kvm_s390_available_subfunc.ppno);
250
203 if (MACHINE_HAS_ESOP) 251 if (MACHINE_HAS_ESOP)
204 allow_cpu_feat(KVM_S390_VM_CPU_FEAT_ESOP); 252 allow_cpu_feat(KVM_S390_VM_CPU_FEAT_ESOP);
205} 253}
@@ -717,6 +765,16 @@ static int kvm_s390_set_processor_feat(struct kvm *kvm,
717 return ret; 765 return ret;
718} 766}
719 767
768static int kvm_s390_set_processor_subfunc(struct kvm *kvm,
769 struct kvm_device_attr *attr)
770{
771 /*
772 * Once supported by kernel + hw, we have to store the subfunctions
773 * in kvm->arch and remember that user space configured them.
774 */
775 return -ENXIO;
776}
777
720static int kvm_s390_set_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr) 778static int kvm_s390_set_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
721{ 779{
722 int ret = -ENXIO; 780 int ret = -ENXIO;
@@ -728,6 +786,9 @@ static int kvm_s390_set_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
728 case KVM_S390_VM_CPU_PROCESSOR_FEAT: 786 case KVM_S390_VM_CPU_PROCESSOR_FEAT:
729 ret = kvm_s390_set_processor_feat(kvm, attr); 787 ret = kvm_s390_set_processor_feat(kvm, attr);
730 break; 788 break;
789 case KVM_S390_VM_CPU_PROCESSOR_SUBFUNC:
790 ret = kvm_s390_set_processor_subfunc(kvm, attr);
791 break;
731 } 792 }
732 return ret; 793 return ret;
733} 794}
@@ -801,6 +862,25 @@ static int kvm_s390_get_machine_feat(struct kvm *kvm,
801 return 0; 862 return 0;
802} 863}
803 864
865static int kvm_s390_get_processor_subfunc(struct kvm *kvm,
866 struct kvm_device_attr *attr)
867{
868 /*
869 * Once we can actually configure subfunctions (kernel + hw support),
870 * we have to check if they were already set by user space, if so copy
871 * them from kvm->arch.
872 */
873 return -ENXIO;
874}
875
876static int kvm_s390_get_machine_subfunc(struct kvm *kvm,
877 struct kvm_device_attr *attr)
878{
879 if (copy_to_user((void __user *)attr->addr, &kvm_s390_available_subfunc,
880 sizeof(struct kvm_s390_vm_cpu_subfunc)))
881 return -EFAULT;
882 return 0;
883}
804static int kvm_s390_get_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr) 884static int kvm_s390_get_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
805{ 885{
806 int ret = -ENXIO; 886 int ret = -ENXIO;
@@ -818,6 +898,12 @@ static int kvm_s390_get_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
818 case KVM_S390_VM_CPU_MACHINE_FEAT: 898 case KVM_S390_VM_CPU_MACHINE_FEAT:
819 ret = kvm_s390_get_machine_feat(kvm, attr); 899 ret = kvm_s390_get_machine_feat(kvm, attr);
820 break; 900 break;
901 case KVM_S390_VM_CPU_PROCESSOR_SUBFUNC:
902 ret = kvm_s390_get_processor_subfunc(kvm, attr);
903 break;
904 case KVM_S390_VM_CPU_MACHINE_SUBFUNC:
905 ret = kvm_s390_get_machine_subfunc(kvm, attr);
906 break;
821 } 907 }
822 return ret; 908 return ret;
823} 909}
@@ -903,8 +989,11 @@ static int kvm_s390_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
903 case KVM_S390_VM_CPU_MACHINE: 989 case KVM_S390_VM_CPU_MACHINE:
904 case KVM_S390_VM_CPU_PROCESSOR_FEAT: 990 case KVM_S390_VM_CPU_PROCESSOR_FEAT:
905 case KVM_S390_VM_CPU_MACHINE_FEAT: 991 case KVM_S390_VM_CPU_MACHINE_FEAT:
992 case KVM_S390_VM_CPU_MACHINE_SUBFUNC:
906 ret = 0; 993 ret = 0;
907 break; 994 break;
995 /* configuring subfunctions is not supported yet */
996 case KVM_S390_VM_CPU_PROCESSOR_SUBFUNC:
908 default: 997 default:
909 ret = -ENXIO; 998 ret = -ENXIO;
910 break; 999 break;