This helper calls kvm_arm_create_scratch_host_vcpu() with preferred target and kvm_vcpu_init.features[0] set with SVE, EL2, PMUv3 and PAUTH if the associated feature caps are advertised by KVM.
The new helper gets used in kvm_arm_get_host_cpu_features for now. Signed-off-by: Eric Auger <[email protected]> --- target/arm/kvm_arm.h | 20 ++++++++ target/arm/kvm-stub.c | 7 +++ target/arm/kvm.c | 108 +++++++++++++++++++++++------------------- 3 files changed, 86 insertions(+), 49 deletions(-) diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index d049334d6d..aafb3cd232 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -125,6 +125,26 @@ bool kvm_arm_create_scratch_host_vcpu(int *fdarray, */ void kvm_arm_destroy_scratch_host_vcpu(int *fdarray); +/** + * kvm_arm_create_scratch_max_host_vcpu: + * @fdarray: filled in with kvmfd, vmfd, cpufd file descriptors in that order + * @init_features0: kvm_vcpu_init.features[0] feature flags used during + * the init + * @target: target eventually chosen + * @errp: Error handle + * + * calls kvm_arm_create_scratch_host_vcpu() with kvm_vcpu_init initialized + * with all max kvm capabilities supported by the platform among + * KVM_CAP_ARM_PMU_V3, KVM_CAP_ARM_SVE, KVM_CAP_ARM_PTRAUTH_ADDRESS, + * KVM_CAP_ARM_PTRAUTH_GENERIC, KVM_CAP_ARM_EL2 + * + * Returns: true on success (and fdarray and init are filled in), + * false on failure (and fdarray and init are not valid). + */ +bool kvm_arm_create_scratch_max_host_vcpu(int *fdarray, + uint32_t *init_features0, + uint32_t *target, Error **errp); + /** * kvm_arm_set_cpu_features_from_host: * @cpu: ARMCPU to set the features for diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c index 264938d2c5..0d6c841a24 100644 --- a/target/arm/kvm-stub.c +++ b/target/arm/kvm-stub.c @@ -125,3 +125,10 @@ bool kvm_idreg_write_scratch_vcpu(int cpufd, Visitor *v, const char *name, { g_assert_not_reached(); } + +bool kvm_arm_create_scratch_max_host_vcpu(int *fdarray, + uint32_t *init_features0, + uint32_t *target, Error **errp) +{ + g_assert_not_reached(); +} diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 8a7f5982fb..e3a0dc07de 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -200,6 +200,46 @@ void kvm_arm_destroy_scratch_host_vcpu(int *fdarray) } } +static bool kvm_arm_pauth_supported(void) +{ + return (kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_ADDRESS) && + kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_GENERIC)); +} + +bool kvm_arm_create_scratch_max_host_vcpu(int *fdarray, + uint32_t *init_features, + uint32_t *target, Error **errp) +{ + struct kvm_vcpu_init init = { .target = -1, }; + bool ret; + + if (!kvm_enabled()) { + return false; + } + + if (kvm_check_extension(kvm_state, KVM_CAP_ARM_SVE)) { + init.features[0] |= 1 << KVM_ARM_VCPU_SVE; + } + if (kvm_arm_el2_supported()) { + init.features[0] |= 1 << KVM_ARM_VCPU_HAS_EL2; + } + if (kvm_arm_pauth_supported()) { + init.features[0] |= (1 << KVM_ARM_VCPU_PTRAUTH_ADDRESS | + 1 << KVM_ARM_VCPU_PTRAUTH_GENERIC); + } + if (kvm_check_extension(kvm_state, KVM_CAP_ARM_PMU_V3)) { + init.features[0] |= 1 << KVM_ARM_VCPU_PMU_V3; + } + + ret = kvm_arm_create_scratch_host_vcpu(fdarray, &init, errp); + + if (ret) { + *init_features = init.features[0]; + *target = init.target; + } + return ret; +} + static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id) { uint64_t ret; @@ -223,13 +263,6 @@ static int read_sys_reg64(int fd, uint64_t *pret, uint64_t id) return ioctl(fd, KVM_GET_ONE_REG, &idreg); } -static bool kvm_arm_pauth_supported(void) -{ - return (kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_ADDRESS) && - kvm_check_extension(kvm_state, KVM_CAP_ARM_PTRAUTH_GENERIC)); -} - - static uint64_t idregs_sysreg_to_kvm_reg(ARMSysRegs sysreg) { return ARM64_SYS_REG((sysreg & CP_REG_ARM64_SYSREG_OP0_MASK) >> CP_REG_ARM64_SYSREG_OP0_SHIFT, @@ -543,11 +576,11 @@ kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) * and then query that CPU for the relevant ID registers. */ int fdarray[3]; - bool sve_supported; - bool el2_supported; - bool pmu_supported = false; + bool sve_supported, pmu_supported; + uint32_t init_features0 = 0; uint64_t features = 0; Error *local_err = NULL; + uint32_t target; int err; ahcf->target = QEMU_KVM_ARM_TARGET_NONE; @@ -558,48 +591,25 @@ kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) } /* - * target = -1 informs kvm_arm_create_scratch_host_vcpu() - * to use the preferred target + * Instantiate a scratch vcpu of preferred target with the following + * features, if advertised by KVM: + * SVE (so that ID_AA64ZFR0 can be queried, otherwise RAS), PMUv3, EL2, + * PAUTH (to get the unsanitized field values for AA64ISAR1_EL1) */ - struct kvm_vcpu_init init = { .target = -1, }; - - /* - * Ask for SVE if supported, so that we can query ID_AA64ZFR0, - * which is otherwise RAZ. - */ - sve_supported = kvm_check_extension(kvm_state, KVM_CAP_ARM_SVE); - if (sve_supported) { - init.features[0] |= 1 << KVM_ARM_VCPU_SVE; - } - - /* - * Ask for EL2 if supported. - */ - el2_supported = kvm_arm_el2_supported(); - if (el2_supported) { - init.features[0] |= 1 << KVM_ARM_VCPU_HAS_EL2; - } - - /* - * Ask for Pointer Authentication if supported, so that we get - * the unsanitized field values for AA64ISAR1_EL1. - */ - if (kvm_arm_pauth_supported()) { - init.features[0] |= (1 << KVM_ARM_VCPU_PTRAUTH_ADDRESS | - 1 << KVM_ARM_VCPU_PTRAUTH_GENERIC); - } - - if (kvm_check_extension(kvm_state, KVM_CAP_ARM_PMU_V3)) { - init.features[0] |= 1 << KVM_ARM_VCPU_PMU_V3; - pmu_supported = true; - features |= 1ULL << ARM_FEATURE_PMU; - } - - if (!kvm_arm_create_scratch_host_vcpu(fdarray, &init, &local_err)) { + if (!kvm_arm_create_scratch_max_host_vcpu(fdarray, + &init_features0, &target, + &local_err)) { error_report_err(local_err); return; } + pmu_supported = init_features0 & (1 << KVM_ARM_VCPU_PMU_V3); + sve_supported = init_features0 & (1 << KVM_ARM_VCPU_SVE); + + if (pmu_supported) { + features |= 1ULL << ARM_FEATURE_PMU; + } + int fd = fdarray[2]; err = get_host_cpu_reg(fd, ahcf, ID_AA64PFR0_EL1_IDX); @@ -746,11 +756,11 @@ kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) features |= 1ULL << ARM_FEATURE_AARCH64; features |= 1ULL << ARM_FEATURE_GENERIC_TIMER; - if (el2_supported) { + if (init_features0 & (1 << KVM_ARM_VCPU_HAS_EL2)) { features |= 1ULL << ARM_FEATURE_EL2; } - ahcf->target = init.target; + ahcf->target = target; ahcf->features = features; } -- 2.53.0
