Skip to content

Commit

Permalink
target/arm/kvm64: max cpu: Enable SVE when available
Browse files Browse the repository at this point in the history
Enable SVE in the KVM guest when the 'max' cpu type is configured
and KVM supports it. KVM SVE requires use of the new finalize
vcpu ioctl, so we add that now too. For starters SVE can only be
turned on or off, getting all vector lengths the host CPU supports
when on. We'll add the other SVE CPU properties in later patches.

Signed-off-by: Andrew Jones <[email protected]>
Reviewed-by: Richard Henderson <[email protected]>
Reviewed-by: Eric Auger <[email protected]>
Tested-by: Masayoshi Mizuma <[email protected]>
Reviewed-by: Beata Michalska <[email protected]>
Message-id: [email protected]
Signed-off-by: Peter Maydell <[email protected]>
  • Loading branch information
Andrew Jones authored and pm215 committed Nov 1, 2019
1 parent 40b3fd2 commit 14e99e0
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 4 deletions.
17 changes: 14 additions & 3 deletions target/arm/cpu64.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,11 @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
return;
}

if (value && kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
error_setg(errp, "'sve' feature not supported by KVM on this host");
return;
}

t = cpu->isar.id_aa64pfr0;
t = FIELD_DP64(t, ID_AA64PFR0, SVE, value);
cpu->isar.id_aa64pfr0 = t;
Expand All @@ -507,11 +512,16 @@ static void aarch64_max_initfn(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
uint32_t vq;
uint64_t t;

if (kvm_enabled()) {
kvm_arm_set_cpu_features_from_host(cpu);
if (kvm_arm_sve_supported(CPU(cpu))) {
t = cpu->isar.id_aa64pfr0;
t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1);
cpu->isar.id_aa64pfr0 = t;
}
} else {
uint64_t t;
uint32_t u;
aarch64_a57_initfn(obj);

Expand Down Expand Up @@ -612,8 +622,6 @@ static void aarch64_max_initfn(Object *obj)

object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
cpu_max_set_sve_max_vq, NULL, NULL, &error_fatal);
object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
cpu_arm_set_sve, NULL, NULL, &error_fatal);

for (vq = 1; vq <= ARM_MAX_VQ; ++vq) {
char name[8];
Expand All @@ -622,6 +630,9 @@ static void aarch64_max_initfn(Object *obj)
cpu_arm_set_sve_vq, NULL, NULL, &error_fatal);
}
}

object_property_add(obj, "sve", "bool", cpu_arm_get_sve,
cpu_arm_set_sve, NULL, NULL, &error_fatal);
}

struct ARMCPUInfo {
Expand Down
5 changes: 5 additions & 0 deletions target/arm/kvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ int kvm_arm_vcpu_init(CPUState *cs)
return kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_INIT, &init);
}

int kvm_arm_vcpu_finalize(CPUState *cs, int feature)
{
return kvm_vcpu_ioctl(cs, KVM_ARM_VCPU_FINALIZE, &feature);
}

void kvm_arm_init_serror_injection(CPUState *cs)
{
cap_has_inject_serror_esr = kvm_check_extension(cs->kvm_state,
Expand Down
20 changes: 19 additions & 1 deletion target/arm/kvm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,13 @@ bool kvm_arm_aarch32_supported(CPUState *cpu)
return kvm_check_extension(s, KVM_CAP_ARM_EL1_32BIT);
}

bool kvm_arm_sve_supported(CPUState *cpu)
{
KVMState *s = KVM_STATE(current_machine->accelerator);

return kvm_check_extension(s, KVM_CAP_ARM_SVE);
}

#define ARM_CPU_ID_MPIDR 3, 0, 0, 0, 5

int kvm_arch_init_vcpu(CPUState *cs)
Expand Down Expand Up @@ -630,20 +637,31 @@ int kvm_arch_init_vcpu(CPUState *cs)
cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_EL1_32BIT;
}
if (!kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_PMU_V3)) {
cpu->has_pmu = false;
cpu->has_pmu = false;
}
if (cpu->has_pmu) {
cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_PMU_V3;
} else {
unset_feature(&env->features, ARM_FEATURE_PMU);
}
if (cpu_isar_feature(aa64_sve, cpu)) {
assert(kvm_arm_sve_supported(cs));
cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_SVE;
}

/* Do KVM_ARM_VCPU_INIT ioctl */
ret = kvm_arm_vcpu_init(cs);
if (ret) {
return ret;
}

if (cpu_isar_feature(aa64_sve, cpu)) {
ret = kvm_arm_vcpu_finalize(cs, KVM_ARM_VCPU_SVE);
if (ret) {
return ret;
}
}

/*
* When KVM is in use, PSCI is emulated in-kernel and not by qemu.
* Currently KVM has its own idea about MPIDR assignment, so we
Expand Down
27 changes: 27 additions & 0 deletions target/arm/kvm_arm.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@
*/
int kvm_arm_vcpu_init(CPUState *cs);

/**
* kvm_arm_vcpu_finalize
* @cs: CPUState
* @feature: int
*
* Finalizes the configuration of the specified VCPU feature by
* invoking the KVM_ARM_VCPU_FINALIZE ioctl. Features requiring
* this are documented in the "KVM_ARM_VCPU_FINALIZE" section of
* KVM's API documentation.
*
* Returns: 0 if success else < 0 error code
*/
int kvm_arm_vcpu_finalize(CPUState *cs, int feature);

/**
* kvm_arm_register_device:
* @mr: memory region for this device
Expand Down Expand Up @@ -225,6 +239,14 @@ bool kvm_arm_aarch32_supported(CPUState *cs);
*/
bool kvm_arm_pmu_supported(CPUState *cs);

/**
* bool kvm_arm_sve_supported:
* @cs: CPUState
*
* Returns true if the KVM VCPU can enable SVE and false otherwise.
*/
bool kvm_arm_sve_supported(CPUState *cs);

/**
* kvm_arm_get_max_vm_ipa_size - Returns the number of bits in the
* IPA address space supported by KVM
Expand Down Expand Up @@ -276,6 +298,11 @@ static inline bool kvm_arm_pmu_supported(CPUState *cs)
return false;
}

static inline bool kvm_arm_sve_supported(CPUState *cs)
{
return false;
}

static inline int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
{
return -ENOENT;
Expand Down
4 changes: 4 additions & 0 deletions tests/arm-cpu-features.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,12 +417,16 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
assert_has_feature(qts, "host", "aarch64");
assert_has_feature(qts, "host", "pmu");

assert_has_feature(qts, "max", "sve");

assert_error(qts, "cortex-a15",
"We cannot guarantee the CPU type 'cortex-a15' works "
"with KVM on this host", NULL);
} else {
assert_has_not_feature(qts, "host", "aarch64");
assert_has_not_feature(qts, "host", "pmu");

assert_has_not_feature(qts, "max", "sve");
}

qtest_quit(qts);
Expand Down

0 comments on commit 14e99e0

Please sign in to comment.