Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c3b9e3e1 authored by Christian Borntraeger's avatar Christian Borntraeger
Browse files

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: default avatarDavid Hildenbrand <david@redhat.com>
Reviewed-by: default avatarCornelia Huck <cohuck@redhat.com>
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
parent f07afa04
Loading
Loading
Loading
Loading
+34 −19
Original line number Diff line number Diff line
@@ -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);
+0 −2
Original line number Diff line number Diff line
@@ -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);

+20 −0
Original line number Diff line number Diff line
@@ -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)