KVM: s390: interface to query and configure cpu features
For now, we only have an interface to query and configure facilities indicated via STFL(E). However, we also have features indicated via SCLP, that have to be indicated to the guest by user space and usually require KVM support. This patch allows user space to query and configure available cpu features for the guest. Please note that disabling a feature doesn't necessarily mean that it is completely disabled (e.g. ESOP is mostly handled by the SIE). We will try our best to disable it. Most features (e.g. SCLP) can't directly be forwarded, as most of them need in addition to hardware support, support in KVM. As we later on want to turn these features in KVM explicitly on/off (to simulate different behavior), we have to filter all features provided by the hardware and make them configurable. Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Este cometimento está contido em:

cometido por
Christian Borntraeger

ascendente
c1778e5157
cometimento
15c9705f0c
@@ -26,6 +26,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/lowcore.h>
|
||||
#include <asm/etr.h>
|
||||
@@ -132,6 +133,9 @@ unsigned long kvm_s390_fac_list_mask_size(void)
|
||||
return ARRAY_SIZE(kvm_s390_fac_list_mask);
|
||||
}
|
||||
|
||||
/* available cpu features supported by kvm */
|
||||
static DECLARE_BITMAP(kvm_s390_available_cpu_feat, KVM_S390_VM_CPU_FEAT_NR_BITS);
|
||||
|
||||
static struct gmap_notifier gmap_notifier;
|
||||
debug_info_t *kvm_s390_dbf;
|
||||
|
||||
@@ -677,6 +681,29 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kvm_s390_set_processor_feat(struct kvm *kvm,
|
||||
struct kvm_device_attr *attr)
|
||||
{
|
||||
struct kvm_s390_vm_cpu_feat data;
|
||||
int ret = -EBUSY;
|
||||
|
||||
if (copy_from_user(&data, (void __user *)attr->addr, sizeof(data)))
|
||||
return -EFAULT;
|
||||
if (!bitmap_subset((unsigned long *) data.feat,
|
||||
kvm_s390_available_cpu_feat,
|
||||
KVM_S390_VM_CPU_FEAT_NR_BITS))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&kvm->lock);
|
||||
if (!atomic_read(&kvm->online_vcpus)) {
|
||||
bitmap_copy(kvm->arch.cpu_feat, (unsigned long *) data.feat,
|
||||
KVM_S390_VM_CPU_FEAT_NR_BITS);
|
||||
ret = 0;
|
||||
}
|
||||
mutex_unlock(&kvm->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kvm_s390_set_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
|
||||
{
|
||||
int ret = -ENXIO;
|
||||
@@ -685,6 +712,9 @@ static int kvm_s390_set_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
|
||||
case KVM_S390_VM_CPU_PROCESSOR:
|
||||
ret = kvm_s390_set_processor(kvm, attr);
|
||||
break;
|
||||
case KVM_S390_VM_CPU_PROCESSOR_FEAT:
|
||||
ret = kvm_s390_set_processor_feat(kvm, attr);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -733,6 +763,31 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kvm_s390_get_processor_feat(struct kvm *kvm,
|
||||
struct kvm_device_attr *attr)
|
||||
{
|
||||
struct kvm_s390_vm_cpu_feat data;
|
||||
|
||||
bitmap_copy((unsigned long *) data.feat, kvm->arch.cpu_feat,
|
||||
KVM_S390_VM_CPU_FEAT_NR_BITS);
|
||||
if (copy_to_user((void __user *)attr->addr, &data, sizeof(data)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_s390_get_machine_feat(struct kvm *kvm,
|
||||
struct kvm_device_attr *attr)
|
||||
{
|
||||
struct kvm_s390_vm_cpu_feat data;
|
||||
|
||||
bitmap_copy((unsigned long *) data.feat,
|
||||
kvm_s390_available_cpu_feat,
|
||||
KVM_S390_VM_CPU_FEAT_NR_BITS);
|
||||
if (copy_to_user((void __user *)attr->addr, &data, sizeof(data)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int kvm_s390_get_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
|
||||
{
|
||||
int ret = -ENXIO;
|
||||
@@ -744,6 +799,12 @@ static int kvm_s390_get_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
|
||||
case KVM_S390_VM_CPU_MACHINE:
|
||||
ret = kvm_s390_get_machine(kvm, attr);
|
||||
break;
|
||||
case KVM_S390_VM_CPU_PROCESSOR_FEAT:
|
||||
ret = kvm_s390_get_processor_feat(kvm, attr);
|
||||
break;
|
||||
case KVM_S390_VM_CPU_MACHINE_FEAT:
|
||||
ret = kvm_s390_get_machine_feat(kvm, attr);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -827,6 +888,8 @@ static int kvm_s390_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
|
||||
switch (attr->attr) {
|
||||
case KVM_S390_VM_CPU_PROCESSOR:
|
||||
case KVM_S390_VM_CPU_MACHINE:
|
||||
case KVM_S390_VM_CPU_PROCESSOR_FEAT:
|
||||
case KVM_S390_VM_CPU_MACHINE_FEAT:
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
|
@@ -175,6 +175,12 @@ static inline int set_kvm_facility(u64 *fac_list, unsigned long nr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int test_kvm_cpu_feat(struct kvm *kvm, unsigned long nr)
|
||||
{
|
||||
WARN_ON_ONCE(nr >= KVM_S390_VM_CPU_FEAT_NR_BITS);
|
||||
return test_bit_inv(nr, kvm->arch.cpu_feat);
|
||||
}
|
||||
|
||||
/* are cpu states controlled by user space */
|
||||
static inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm)
|
||||
{
|
||||
|
Criar uma nova questão referindo esta
Bloquear um utilizador