mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 21:33:00 +00:00
KVM: s390: implement CPU model only facilities
Some facilities should only be provided to the guest, if they are enabled by a CPU model. This allows us to avoid capabilities and to simply fall back to the cpumodel for deciding about a facility without enabling it for older QEMUs or QEMUs without a CPU model. Reviewed-by: David Hildenbrand <david@redhat.com> Reviewed-by: Cornelia Huck <cohuck@redhat.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
This commit is contained in:
parent
f07afa0462
commit
c3b9e3e1ea
@ -152,13 +152,33 @@ static int nested;
|
||||
module_param(nested, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(nested, "Nested virtualization support");
|
||||
|
||||
/* upper facilities limit for kvm */
|
||||
unsigned long kvm_s390_fac_list_mask[16] = { FACILITIES_KVM };
|
||||
|
||||
unsigned long kvm_s390_fac_list_mask_size(void)
|
||||
/*
|
||||
* For now we handle at most 16 double words as this is what the s390 base
|
||||
* kernel handles and stores in the prefix page. If we ever need to go beyond
|
||||
* this, this requires changes to code, but the external uapi can stay.
|
||||
*/
|
||||
#define SIZE_INTERNAL 16
|
||||
|
||||
/*
|
||||
* Base feature mask that defines default mask for facilities. Consists of the
|
||||
* defines in FACILITIES_KVM and the non-hypervisor managed bits.
|
||||
*/
|
||||
static unsigned long kvm_s390_fac_base[SIZE_INTERNAL] = { FACILITIES_KVM };
|
||||
/*
|
||||
* Extended feature mask. Consists of the defines in FACILITIES_KVM_CPUMODEL
|
||||
* and defines the facilities that can be enabled via a cpu model.
|
||||
*/
|
||||
static unsigned long kvm_s390_fac_ext[SIZE_INTERNAL] = { FACILITIES_KVM_CPUMODEL };
|
||||
|
||||
static unsigned long kvm_s390_fac_size(void)
|
||||
{
|
||||
BUILD_BUG_ON(ARRAY_SIZE(kvm_s390_fac_list_mask) > S390_ARCH_FAC_MASK_SIZE_U64);
|
||||
return ARRAY_SIZE(kvm_s390_fac_list_mask);
|
||||
BUILD_BUG_ON(SIZE_INTERNAL > S390_ARCH_FAC_MASK_SIZE_U64);
|
||||
BUILD_BUG_ON(SIZE_INTERNAL > S390_ARCH_FAC_LIST_SIZE_U64);
|
||||
BUILD_BUG_ON(SIZE_INTERNAL * sizeof(unsigned long) >
|
||||
sizeof(S390_lowcore.stfle_fac_list));
|
||||
|
||||
return SIZE_INTERNAL;
|
||||
}
|
||||
|
||||
/* available cpu features supported by kvm */
|
||||
@ -1967,20 +1987,15 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
|
||||
if (!kvm->arch.sie_page2)
|
||||
goto out_err;
|
||||
|
||||
/* Populate the facility mask initially. */
|
||||
memcpy(kvm->arch.model.fac_mask, S390_lowcore.stfle_fac_list,
|
||||
sizeof(S390_lowcore.stfle_fac_list));
|
||||
for (i = 0; i < S390_ARCH_FAC_LIST_SIZE_U64; i++) {
|
||||
if (i < kvm_s390_fac_list_mask_size())
|
||||
kvm->arch.model.fac_mask[i] &= kvm_s390_fac_list_mask[i];
|
||||
else
|
||||
kvm->arch.model.fac_mask[i] = 0UL;
|
||||
}
|
||||
|
||||
/* Populate the facility list initially. */
|
||||
kvm->arch.model.fac_list = kvm->arch.sie_page2->fac_list;
|
||||
memcpy(kvm->arch.model.fac_list, kvm->arch.model.fac_mask,
|
||||
S390_ARCH_FAC_LIST_SIZE_BYTE);
|
||||
|
||||
for (i = 0; i < kvm_s390_fac_size(); i++) {
|
||||
kvm->arch.model.fac_mask[i] = S390_lowcore.stfle_fac_list[i] &
|
||||
(kvm_s390_fac_base[i] |
|
||||
kvm_s390_fac_ext[i]);
|
||||
kvm->arch.model.fac_list[i] = S390_lowcore.stfle_fac_list[i] &
|
||||
kvm_s390_fac_base[i];
|
||||
}
|
||||
|
||||
/* we are always in czam mode - even on pre z14 machines */
|
||||
set_kvm_facility(kvm->arch.model.fac_mask, 138);
|
||||
@ -4044,7 +4059,7 @@ static int __init kvm_s390_init(void)
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
kvm_s390_fac_list_mask[i] |=
|
||||
kvm_s390_fac_base[i] |=
|
||||
S390_lowcore.stfle_fac_list[i] & nonhyp_mask(i);
|
||||
|
||||
return kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
|
||||
|
@ -294,8 +294,6 @@ void exit_sie(struct kvm_vcpu *vcpu);
|
||||
void kvm_s390_sync_request(int req, struct kvm_vcpu *vcpu);
|
||||
int kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu);
|
||||
void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu);
|
||||
unsigned long kvm_s390_fac_list_mask_size(void);
|
||||
extern unsigned long kvm_s390_fac_list_mask[];
|
||||
void kvm_s390_set_cpu_timer(struct kvm_vcpu *vcpu, __u64 cputm);
|
||||
__u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu);
|
||||
|
||||
|
@ -62,6 +62,13 @@ static struct facility_def facility_defs[] = {
|
||||
}
|
||||
},
|
||||
{
|
||||
/*
|
||||
* FACILITIES_KVM contains the list of facilities that are part
|
||||
* of the default facility mask and list that are passed to the
|
||||
* initial CPU model. If no CPU model is used, this, together
|
||||
* with the non-hypervisor managed bits, is the maximum list of
|
||||
* guest facilities supported by KVM.
|
||||
*/
|
||||
.name = "FACILITIES_KVM",
|
||||
.bits = (int[]){
|
||||
0, /* N3 instructions */
|
||||
@ -89,6 +96,19 @@ static struct facility_def facility_defs[] = {
|
||||
-1 /* END */
|
||||
}
|
||||
},
|
||||
{
|
||||
/*
|
||||
* FACILITIES_KVM_CPUMODEL contains the list of facilities
|
||||
* that can be enabled by CPU model code if the host supports
|
||||
* it. These facilities are not passed to the guest without
|
||||
* CPU model support.
|
||||
*/
|
||||
|
||||
.name = "FACILITIES_KVM_CPUMODEL",
|
||||
.bits = (int[]){
|
||||
-1 /* END */
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static void print_facility_list(struct facility_def *def)
|
||||
|
Loading…
Reference in New Issue
Block a user