diff options
author | Michael Mueller <mimu@linux.vnet.ibm.com> | 2015-02-24 07:51:04 -0500 |
---|---|---|
committer | Christian Borntraeger <borntraeger@de.ibm.com> | 2015-03-04 04:33:25 -0500 |
commit | 981467c930bdfa4be59acbbc9f3a80eb9e3167a8 (patch) | |
tree | 053681bb659da7ff0923bad2a338609f8e58f5fa /arch | |
parent | 94422ee880afc4af050bac172ea39af8e2130034 (diff) |
KVM: s390: include guest facilities in kvm facility test
Most facility related decisions in KVM have to take into account:
- the facilities offered by the underlying run container (LPAR/VM)
- the facilities supported by the KVM code itself
- the facilities requested by a guest VM
This patch adds the KVM driver requested facilities to the test routine.
It additionally renames struct s390_model_fac to kvm_s390_fac and its field
names to be more meaningful.
The semantics of the facilities stored in the KVM architecture structure
is changed. The address arch.model.fac->list now points to the guest
facility list and arch.model.fac->mask points to the KVM facility mask.
This patch fixes the behaviour of KVM for some facilities for guests
that ignore the guest visible facility bits, e.g. guests could use
transactional memory intructions on hosts supporting them even if the
chosen cpu model would not offer them.
The userspace interface is not affected by this change.
Signed-off-by: Michael Mueller <mimu@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/s390/include/asm/kvm_host.h | 12 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 30 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.h | 3 | ||||
-rw-r--r-- | arch/s390/kvm/priv.c | 2 |
4 files changed, 25 insertions, 22 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index d84559e31f32..f407bbf5ee94 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
@@ -515,15 +515,15 @@ struct s390_io_adapter { | |||
515 | #define S390_ARCH_FAC_MASK_SIZE_U64 \ | 515 | #define S390_ARCH_FAC_MASK_SIZE_U64 \ |
516 | (S390_ARCH_FAC_MASK_SIZE_BYTE / sizeof(u64)) | 516 | (S390_ARCH_FAC_MASK_SIZE_BYTE / sizeof(u64)) |
517 | 517 | ||
518 | struct s390_model_fac { | 518 | struct kvm_s390_fac { |
519 | /* facilities used in SIE context */ | 519 | /* facility list requested by guest */ |
520 | __u64 sie[S390_ARCH_FAC_LIST_SIZE_U64]; | 520 | __u64 list[S390_ARCH_FAC_LIST_SIZE_U64]; |
521 | /* subset enabled by kvm */ | 521 | /* facility mask supported by kvm & hosting machine */ |
522 | __u64 kvm[S390_ARCH_FAC_LIST_SIZE_U64]; | 522 | __u64 mask[S390_ARCH_FAC_LIST_SIZE_U64]; |
523 | }; | 523 | }; |
524 | 524 | ||
525 | struct kvm_s390_cpu_model { | 525 | struct kvm_s390_cpu_model { |
526 | struct s390_model_fac *fac; | 526 | struct kvm_s390_fac *fac; |
527 | struct cpuid cpu_id; | 527 | struct cpuid cpu_id; |
528 | unsigned short ibc; | 528 | unsigned short ibc; |
529 | }; | 529 | }; |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 76894c8db4d7..5a02be4628f1 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -522,7 +522,7 @@ static int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr) | |||
522 | memcpy(&kvm->arch.model.cpu_id, &proc->cpuid, | 522 | memcpy(&kvm->arch.model.cpu_id, &proc->cpuid, |
523 | sizeof(struct cpuid)); | 523 | sizeof(struct cpuid)); |
524 | kvm->arch.model.ibc = proc->ibc; | 524 | kvm->arch.model.ibc = proc->ibc; |
525 | memcpy(kvm->arch.model.fac->kvm, proc->fac_list, | 525 | memcpy(kvm->arch.model.fac->list, proc->fac_list, |
526 | S390_ARCH_FAC_LIST_SIZE_BYTE); | 526 | S390_ARCH_FAC_LIST_SIZE_BYTE); |
527 | } else | 527 | } else |
528 | ret = -EFAULT; | 528 | ret = -EFAULT; |
@@ -556,7 +556,7 @@ static int kvm_s390_get_processor(struct kvm *kvm, struct kvm_device_attr *attr) | |||
556 | } | 556 | } |
557 | memcpy(&proc->cpuid, &kvm->arch.model.cpu_id, sizeof(struct cpuid)); | 557 | memcpy(&proc->cpuid, &kvm->arch.model.cpu_id, sizeof(struct cpuid)); |
558 | proc->ibc = kvm->arch.model.ibc; | 558 | proc->ibc = kvm->arch.model.ibc; |
559 | memcpy(&proc->fac_list, kvm->arch.model.fac->kvm, S390_ARCH_FAC_LIST_SIZE_BYTE); | 559 | memcpy(&proc->fac_list, kvm->arch.model.fac->list, S390_ARCH_FAC_LIST_SIZE_BYTE); |
560 | if (copy_to_user((void __user *)attr->addr, proc, sizeof(*proc))) | 560 | if (copy_to_user((void __user *)attr->addr, proc, sizeof(*proc))) |
561 | ret = -EFAULT; | 561 | ret = -EFAULT; |
562 | kfree(proc); | 562 | kfree(proc); |
@@ -576,8 +576,8 @@ static int kvm_s390_get_machine(struct kvm *kvm, struct kvm_device_attr *attr) | |||
576 | } | 576 | } |
577 | get_cpu_id((struct cpuid *) &mach->cpuid); | 577 | get_cpu_id((struct cpuid *) &mach->cpuid); |
578 | mach->ibc = sclp_get_ibc(); | 578 | mach->ibc = sclp_get_ibc(); |
579 | memcpy(&mach->fac_mask, kvm_s390_fac_list_mask, | 579 | memcpy(&mach->fac_mask, kvm->arch.model.fac->mask, |
580 | kvm_s390_fac_list_mask_size() * sizeof(u64)); | 580 | S390_ARCH_FAC_LIST_SIZE_BYTE); |
581 | memcpy((unsigned long *)&mach->fac_list, S390_lowcore.stfle_fac_list, | 581 | memcpy((unsigned long *)&mach->fac_list, S390_lowcore.stfle_fac_list, |
582 | S390_ARCH_FAC_LIST_SIZE_BYTE); | 582 | S390_ARCH_FAC_LIST_SIZE_BYTE); |
583 | if (copy_to_user((void __user *)attr->addr, mach, sizeof(*mach))) | 583 | if (copy_to_user((void __user *)attr->addr, mach, sizeof(*mach))) |
@@ -893,16 +893,16 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | |||
893 | /* | 893 | /* |
894 | * The architectural maximum amount of facilities is 16 kbit. To store | 894 | * The architectural maximum amount of facilities is 16 kbit. To store |
895 | * this amount, 2 kbyte of memory is required. Thus we need a full | 895 | * this amount, 2 kbyte of memory is required. Thus we need a full |
896 | * page to hold the active copy (arch.model.fac->sie) and the current | 896 | * page to hold the guest facility list (arch.model.fac->list) and the |
897 | * facilities set (arch.model.fac->kvm). Its address size has to be | 897 | * facility mask (arch.model.fac->mask). Its address size has to be |
898 | * 31 bits and word aligned. | 898 | * 31 bits and word aligned. |
899 | */ | 899 | */ |
900 | kvm->arch.model.fac = | 900 | kvm->arch.model.fac = |
901 | (struct s390_model_fac *) get_zeroed_page(GFP_KERNEL | GFP_DMA); | 901 | (struct kvm_s390_fac *) get_zeroed_page(GFP_KERNEL | GFP_DMA); |
902 | if (!kvm->arch.model.fac) | 902 | if (!kvm->arch.model.fac) |
903 | goto out_nofac; | 903 | goto out_nofac; |
904 | 904 | ||
905 | memcpy(kvm->arch.model.fac->kvm, S390_lowcore.stfle_fac_list, | 905 | memcpy(kvm->arch.model.fac->mask, S390_lowcore.stfle_fac_list, |
906 | S390_ARCH_FAC_LIST_SIZE_BYTE); | 906 | S390_ARCH_FAC_LIST_SIZE_BYTE); |
907 | 907 | ||
908 | /* | 908 | /* |
@@ -914,7 +914,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | |||
914 | */ | 914 | */ |
915 | if (!MACHINE_IS_LPAR) | 915 | if (!MACHINE_IS_LPAR) |
916 | for (i = 0; i < kvm_s390_fac_list_mask_size(); i++) | 916 | for (i = 0; i < kvm_s390_fac_list_mask_size(); i++) |
917 | kvm_s390_fac_list_mask[i] &= kvm->arch.model.fac->kvm[i]; | 917 | kvm_s390_fac_list_mask[i] &= kvm->arch.model.fac->mask[i]; |
918 | 918 | ||
919 | /* | 919 | /* |
920 | * Apply the kvm facility mask to limit the kvm supported/tolerated | 920 | * Apply the kvm facility mask to limit the kvm supported/tolerated |
@@ -922,11 +922,15 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | |||
922 | */ | 922 | */ |
923 | for (i = 0; i < S390_ARCH_FAC_LIST_SIZE_U64; i++) { | 923 | for (i = 0; i < S390_ARCH_FAC_LIST_SIZE_U64; i++) { |
924 | if (i < kvm_s390_fac_list_mask_size()) | 924 | if (i < kvm_s390_fac_list_mask_size()) |
925 | kvm->arch.model.fac->kvm[i] &= kvm_s390_fac_list_mask[i]; | 925 | kvm->arch.model.fac->mask[i] &= kvm_s390_fac_list_mask[i]; |
926 | else | 926 | else |
927 | kvm->arch.model.fac->kvm[i] = 0UL; | 927 | kvm->arch.model.fac->mask[i] = 0UL; |
928 | } | 928 | } |
929 | 929 | ||
930 | /* Populate the facility list initially. */ | ||
931 | memcpy(kvm->arch.model.fac->list, kvm->arch.model.fac->mask, | ||
932 | S390_ARCH_FAC_LIST_SIZE_BYTE); | ||
933 | |||
930 | kvm_s390_get_cpu_id(&kvm->arch.model.cpu_id); | 934 | kvm_s390_get_cpu_id(&kvm->arch.model.cpu_id); |
931 | kvm->arch.model.ibc = sclp_get_ibc() & 0x0fff; | 935 | kvm->arch.model.ibc = sclp_get_ibc() & 0x0fff; |
932 | 936 | ||
@@ -1172,8 +1176,6 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | |||
1172 | 1176 | ||
1173 | mutex_lock(&vcpu->kvm->lock); | 1177 | mutex_lock(&vcpu->kvm->lock); |
1174 | vcpu->arch.cpu_id = vcpu->kvm->arch.model.cpu_id; | 1178 | vcpu->arch.cpu_id = vcpu->kvm->arch.model.cpu_id; |
1175 | memcpy(vcpu->kvm->arch.model.fac->sie, vcpu->kvm->arch.model.fac->kvm, | ||
1176 | S390_ARCH_FAC_LIST_SIZE_BYTE); | ||
1177 | vcpu->arch.sie_block->ibc = vcpu->kvm->arch.model.ibc; | 1179 | vcpu->arch.sie_block->ibc = vcpu->kvm->arch.model.ibc; |
1178 | mutex_unlock(&vcpu->kvm->lock); | 1180 | mutex_unlock(&vcpu->kvm->lock); |
1179 | 1181 | ||
@@ -1219,7 +1221,7 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, | |||
1219 | vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca; | 1221 | vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca; |
1220 | set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn); | 1222 | set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn); |
1221 | } | 1223 | } |
1222 | vcpu->arch.sie_block->fac = (int) (long) kvm->arch.model.fac->sie; | 1224 | vcpu->arch.sie_block->fac = (int) (long) kvm->arch.model.fac->list; |
1223 | 1225 | ||
1224 | spin_lock_init(&vcpu->arch.local_int.lock); | 1226 | spin_lock_init(&vcpu->arch.local_int.lock); |
1225 | vcpu->arch.local_int.float_int = &kvm->arch.float_int; | 1227 | vcpu->arch.local_int.float_int = &kvm->arch.float_int; |
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index 985c2114d7ef..c34109aa552d 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h | |||
@@ -128,7 +128,8 @@ static inline void kvm_s390_set_psw_cc(struct kvm_vcpu *vcpu, unsigned long cc) | |||
128 | /* test availability of facility in a kvm intance */ | 128 | /* test availability of facility in a kvm intance */ |
129 | static inline int test_kvm_facility(struct kvm *kvm, unsigned long nr) | 129 | static inline int test_kvm_facility(struct kvm *kvm, unsigned long nr) |
130 | { | 130 | { |
131 | return __test_facility(nr, kvm->arch.model.fac->kvm); | 131 | return __test_facility(nr, kvm->arch.model.fac->mask) && |
132 | __test_facility(nr, kvm->arch.model.fac->list); | ||
132 | } | 133 | } |
133 | 134 | ||
134 | /* are cpu states controlled by user space */ | 135 | /* are cpu states controlled by user space */ |
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index bdd9b5b17e03..351116939ea2 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -348,7 +348,7 @@ static int handle_stfl(struct kvm_vcpu *vcpu) | |||
348 | * We need to shift the lower 32 facility bits (bit 0-31) from a u64 | 348 | * We need to shift the lower 32 facility bits (bit 0-31) from a u64 |
349 | * into a u32 memory representation. They will remain bits 0-31. | 349 | * into a u32 memory representation. They will remain bits 0-31. |
350 | */ | 350 | */ |
351 | fac = *vcpu->kvm->arch.model.fac->sie >> 32; | 351 | fac = *vcpu->kvm->arch.model.fac->list >> 32; |
352 | rc = write_guest_lc(vcpu, offsetof(struct _lowcore, stfl_fac_list), | 352 | rc = write_guest_lc(vcpu, offsetof(struct _lowcore, stfl_fac_list), |
353 | &fac, sizeof(fac)); | 353 | &fac, sizeof(fac)); |
354 | if (rc) | 354 | if (rc) |